=> b1e9b313f6810afbadde0f8079326ecf04c89817
[1mdiff --git a/CMakeLists.txt b/CMakeLists.txt[m [1mindex 20def6a7..7d73956d 100644[m [1m--- a/CMakeLists.txt[m [1m+++ b/CMakeLists.txt[m [36m@@ -135,6 +135,7 @@[m [mset (SOURCES[m src/ui/listwidget.h[m src/ui/lookupwidget.c[m src/ui/lookupwidget.h[m [32m+[m[32m src/ui/keys.c[m src/ui/keys.h[m src/ui/metrics.c[m src/ui/metrics.h[m [1mdiff --git a/src/app.c b/src/app.c[m [1mindex e4c31eaf..10f5f0d2 100644[m [1m--- a/src/app.c[m [1m+++ b/src/app.c[m [36m@@ -32,6 +32,7 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m #include "ui/command.h"[m #include "ui/documentwidget.h"[m #include "ui/inputwidget.h"[m [32m+[m[32m#include "ui/keys.h"[m #include "ui/labelwidget.h"[m #include "ui/sidebarwidget.h"[m #include "ui/text.h"[m [36m@@ -357,9 +358,11 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m #if defined (iPlatformApple)[m setupApplication_MacOS();[m #endif[m [32m+[m[32m init_Keys();[m loadPrefs_App_(d);[m [32m+[m[32m load_Keys(dataDir_App_);[m load_Visited(d->visited, dataDir_App_);[m [31m- load_Bookmarks(d->bookmarks, dataDir_App_);[m [32m+[m[32m load_Bookmarks(d->bookmarks, dataDir_App_);[m[41m [m if (isFirstRun) {[m /* Create the default bookmarks for a quick start. */[m add_Bookmarks(d->bookmarks,[m [36m@@ -426,6 +429,7 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m [m static void deinit_App(iApp *d) {[m saveState_App_(d);[m [32m+[m[32m save_Keys(dataDir_App_);[m savePrefs_App_(d);[m deinit_Prefs(&d->prefs);[m save_Bookmarks(d->bookmarks, dataDir_App_);[m [36m@@ -501,6 +505,10 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m }[m default: {[m iBool wasUsed = processEvent_Window(d->window, &ev);[m [32m+[m[32m if (!wasUsed) {[m [32m+[m[32m /* There may be a key bindings for this. */[m [32m+[m[32m wasUsed = processEvent_Keys(&ev);[m [32m+[m[32m }[m if (ev.type == SDL_USEREVENT && ev.user.code == command_UserEventCode) {[m #if defined (iPlatformApple) && !defined (iPlatformIOS)[m handleCommand_MacOS(command_UserEvent(&ev));[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 5c6780d1..a2bea17b 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -1536,7 +1536,7 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m updateVisible_DocumentWidget_(d);[m return iTrue;[m }[m [31m- else if (equalWidget_Command(cmd, w, "scroll.page")) {[m [32m+[m[32m else if (equal_Command(cmd, "scroll.page") && document_App() == d) {[m if (argLabel_Command(cmd, "repeat")) {[m /* TODO: Adjust scroll animation to be linear during repeated scroll? */[m }[m [36m@@ -1547,6 +1547,40 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m smoothDuration_DocumentWidget_);[m return iTrue;[m }[m [32m+[m[32m else if (equal_Command(cmd, "scroll.top") && document_App() == d) {[m [32m+[m[32m init_Anim(&d->scrollY, 0);[m [32m+[m[32m invalidate_VisBuf(d->visBuf);[m [32m+[m[32m scroll_DocumentWidget_(d, 0);[m [32m+[m[32m updateVisible_DocumentWidget_(d);[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m else if (equal_Command(cmd, "scroll.bottom") && document_App() == d) {[m [32m+[m[32m init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));[m [32m+[m[32m invalidate_VisBuf(d->visBuf);[m [32m+[m[32m scroll_DocumentWidget_(d, 0);[m [32m+[m[32m updateVisible_DocumentWidget_(d);[m [32m+[m[32m refresh_Widget(w);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m else if (equal_Command(cmd, "scroll.step") && document_App() == d) {[m [32m+[m[32m smoothScroll_DocumentWidget_(d,[m [32m+[m[32m 3 * lineHeight_Text(paragraph_FontId) * arg_Command(cmd),[m [32m+[m[32m smoothDuration_DocumentWidget_);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m#if 0[m [32m+[m[32m case SDLK_PAGEUP:[m [32m+[m[32m case SDLK_PAGEDOWN:[m [32m+[m[32m case SDLK_SPACE:[m [32m+[m[32m postCommand_Widget([m [32m+[m[32m w,[m [32m+[m[32m "scroll.page arg:%d repeat:%d",[m [32m+[m[32m (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,[m [32m+[m[32m ev->key.repeat != 0);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m#endif[m else if (equal_Command(cmd, "document.goto") && document_App() == d) {[m const iRangecc heading = range_Command(cmd, "heading");[m if (heading.start) {[m [36m@@ -1790,45 +1824,6 @@[m [mstatic iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e[m refresh_Widget(w);[m }[m break;[m [31m- case SDLK_HOME:[m [31m- init_Anim(&d->scrollY, 0);[m [31m- invalidate_VisBuf(d->visBuf);[m [31m- scroll_DocumentWidget_(d, 0);[m [31m- updateVisible_DocumentWidget_(d);[m [31m- refresh_Widget(w);[m [31m- return iTrue;[m [31m- case SDLK_END:[m [31m- init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));[m [31m- invalidate_VisBuf(d->visBuf);[m [31m- scroll_DocumentWidget_(d, 0);[m [31m- updateVisible_DocumentWidget_(d);[m [31m- refresh_Widget(w);[m [31m- return iTrue;[m [31m- case SDLK_UP:[m [31m- case SDLK_DOWN:[m [31m- if (mods == 0) {[m [31m- if (ev->key.repeat) {[m [31m-// if (!d->smoothContinue) {[m [31m-// d->smoothContinue = iTrue;[m [31m-// }[m [31m-// else return iTrue;[m [31m- }[m [31m- smoothScroll_DocumentWidget_(d,[m [31m- 3 * lineHeight_Text(paragraph_FontId) *[m [31m- (key == SDLK_UP ? -1 : 1),[m [31m- /*gap_Text * */smoothDuration_DocumentWidget_);[m [31m- return iTrue;[m [31m- }[m [31m- break;[m [31m- case SDLK_PAGEUP:[m [31m- case SDLK_PAGEDOWN:[m [31m- case SDLK_SPACE:[m [31m- postCommand_Widget([m [31m- w,[m [31m- "scroll.page arg:%d repeat:%d",[m [31m- (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,[m [31m- ev->key.repeat != 0);[m [31m- return iTrue;[m #if 1[m case SDLK_KP_1:[m case '`': {[m [1mdiff --git a/src/ui/keys.c b/src/ui/keys.c[m [1mnew file mode 100644[m [1mindex 00000000..d46d20bf[m [1m--- /dev/null[m [1m+++ b/src/ui/keys.c[m [36m@@ -0,0 +1,154 @@[m [32m+[m[32m/* Copyright 2020 Jaakko Keränen[m [32m+[m [32m+[m[32mRedistribution and use in source and binary forms, with or without[m [32m+[m[32mmodification, are permitted provided that the following conditions are met:[m [32m+[m [32m+[m[32m1. Redistributions of source code must retain the above copyright notice, this[m [32m+[m[32m list of conditions and the following disclaimer.[m [32m+[m[32m2. Redistributions in binary form must reproduce the above copyright notice,[m [32m+[m[32m this list of conditions and the following disclaimer in the documentation[m [32m+[m[32m and/or other materials provided with the distribution.[m [32m+[m [32m+[m[32mTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND[m [32m+[m[32mANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED[m [32m+[m[32mWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE[m [32m+[m[32mDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR[m [32m+[m[32mANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES[m [32m+[m[32m(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;[m [32m+[m[32mLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON[m [32m+[m[32mANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT[m [32m+[m[32m(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS[m [32m+[m[32mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m [32m+[m [32m+[m[32m#include "keys.h"[m [32m+[m[32m#include "util.h"[m [32m+[m[32m#include "app.h"[m [32m+[m [32m+[m[32m#include [m [32m+[m [32m+[m[32miDeclareType(Keys)[m [32m+[m[32miDeclareType(Binding)[m [32m+[m [32m+[m[32mstruct Impl_Binding {[m [32m+[m[32m int key;[m [32m+[m[32m int mods;[m [32m+[m[32m iString command;[m [32m+[m[32m iString label;[m [32m+[m[32m};[m [32m+[m [32m+[m[32mstatic int cmp_Binding_(const void *a, const void *b) {[m [32m+[m[32m const iBinding *d = a, *other = b;[m [32m+[m[32m const int cmp = iCmp(d->key, other->key);[m [32m+[m[32m if (cmp == 0) {[m [32m+[m[32m return iCmp(d->mods, other->mods);[m [32m+[m[32m }[m [32m+[m[32m return cmp;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstruct Impl_Keys {[m [32m+[m[32m iSortedArray bindings;[m [32m+[m[32m};[m [32m+[m [32m+[m[32mstatic iKeys keys_;[m [32m+[m [32m+[m[32mstatic void clear_Keys_(iKeys *d) {[m [32m+[m[32m iForEach(Array, i, &d->bindings.values) {[m [32m+[m[32m iBinding *bind = i.value;[m [32m+[m[32m deinit_String(&bind->command);[m [32m+[m[32m deinit_String(&bind->label);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void bindDefaults_(void) {[m [32m+[m[32m bind_Keys("scroll.top", SDLK_HOME, 0);[m [32m+[m[32m bind_Keys("scroll.bottom", SDLK_END, 0);[m [32m+[m[32m bind_Keys("scroll.step arg:-1", SDLK_UP, 0);[m [32m+[m[32m bind_Keys("scroll.step arg:1", SDLK_DOWN, 0);[m [32m+[m[32m bind_Keys("scroll.page arg:-1", SDLK_PAGEUP, 0);[m [32m+[m[32m bind_Keys("scroll.page arg:-1", SDLK_SPACE, KMOD_SHIFT);[m [32m+[m[32m bind_Keys("scroll.page arg:1", SDLK_PAGEDOWN, 0);[m [32m+[m[32m bind_Keys("scroll.page arg:1", SDLK_SPACE, 0);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iBinding *find_Keys_(iKeys *d, int key, int mods) {[m [32m+[m[32m const iBinding bind = { .key = key, .mods = mods };[m [32m+[m[32m size_t pos;[m [32m+[m[32m if (locate_SortedArray(&d->bindings, &bind, &pos)) {[m [32m+[m[32m return at_SortedArray(&d->bindings, pos);[m [32m+[m[32m }[m [32m+[m[32m return NULL;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iBinding *findCommand_Keys_(iKeys *d, const char *command) {[m [32m+[m[32m /* Note: O(n) */[m [32m+[m[32m iForEach(Array, i, &d->bindings.values) {[m [32m+[m[32m iBinding *bind = i.value;[m [32m+[m[32m if (!cmp_String(&bind->command, command)) {[m [32m+[m[32m return bind;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m return NULL;[m [32m+[m[32m}[m [32m+[m [32m+[m[32m/*----------------------------------------------------------------------------------------------*/[m [32m+[m [32m+[m[32mvoid init_Keys(void) {[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m init_SortedArray(&d->bindings, sizeof(iBinding), cmp_Binding_);[m [32m+[m[32m bindDefaults_();[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid deinit_Keys(void) {[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m clear_Keys_(d);[m [32m+[m[32m deinit_SortedArray(&d->bindings);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid load_Keys(const char *saveDir) {[m [32m+[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid save_Keys(const char *saveDir) {[m [32m+[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid bind_Keys(const char *command, int key, int mods) {[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m iBinding *bind = find_Keys_(d, key, mods);[m [32m+[m[32m if (bind) {[m [32m+[m[32m setCStr_String(&bind->command, command);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m iBinding bind;[m [32m+[m[32m bind.key = key;[m [32m+[m[32m bind.mods = mods;[m [32m+[m[32m initCStr_String(&bind.command, command);[m [32m+[m[32m init_String(&bind.label);[m [32m+[m[32m insert_SortedArray(&d->bindings, &bind);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid setLabel_Keys(const char *command, const char *label) {[m [32m+[m[32m iBinding *bind = findCommand_Keys_(&keys_, command);[m [32m+[m[32m if (bind) {[m [32m+[m[32m setCStr_String(&bind->label, label);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32m//const iString *label_Keys(const char *command) {[m [32m+[m [32m+[m[32m//}[m [32m+[m [32m+[m[32m//const char *shortcutLabel_Keys(const char *command) {}[m [32m+[m [32m+[m[32miBool processEvent_Keys(const SDL_Event *ev) {[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m if (ev->type == SDL_KEYDOWN) {[m [32m+[m[32m const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));[m [32m+[m[32m if (bind) {[m [32m+[m[32m postCommandString_App(&bind->command);[m [32m+[m[32m return iTrue;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m return iFalse;[m [32m+[m[32m}[m [1mdiff --git a/src/ui/keys.h b/src/ui/keys.h[m [1mindex a9b13df3..157ddea5 100644[m [1m--- a/src/ui/keys.h[m [1m+++ b/src/ui/keys.h[m [36m@@ -22,7 +22,8 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m [m #pragma once[m [m [31m-#include [m [32m+[m[32m#include [m [32m+[m[32m#include [m [m #if defined (iPlatformApple)[m # define reload_KeyShortcut SDLK_r, KMOD_PRIMARY[m [36m@@ -41,3 +42,17 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m # define byWord_KeyModifier KMOD_CTRL[m # define byLine_KeyModifier 0[m #endif[m [32m+[m [32m+[m[32mvoid init_Keys (void);[m [32m+[m[32mvoid deinit_Keys (void);[m [32m+[m [32m+[m[32mvoid load_Keys (const char *saveDir);[m [32m+[m[32mvoid save_Keys (const char *saveDir);[m [32m+[m [32m+[m[32mvoid bind_Keys (const char *command, int key, int mods);[m [32m+[m[32mvoid setLabel_Keys (const char *command, const char *label);[m [32m+[m [32m+[m[32m//const iString * label_Keys (const char *command);[m [32m+[m[32m//const char * shortcutLabel_Keys (const char *command);[m [32m+[m [32m+[m[32miBool processEvent_Keys (const SDL_Event *);[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).