summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/app.c10
-rw-r--r--src/ui/documentwidget.c75
-rw-r--r--src/ui/keys.c154
-rw-r--r--src/ui/keys.h17
5 files changed, 215 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 20def6a7..7d73956d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -135,6 +135,7 @@ set (SOURCES
135 src/ui/listwidget.h 135 src/ui/listwidget.h
136 src/ui/lookupwidget.c 136 src/ui/lookupwidget.c
137 src/ui/lookupwidget.h 137 src/ui/lookupwidget.h
138 src/ui/keys.c
138 src/ui/keys.h 139 src/ui/keys.h
139 src/ui/metrics.c 140 src/ui/metrics.c
140 src/ui/metrics.h 141 src/ui/metrics.h
diff --git a/src/app.c b/src/app.c
index e4c31eaf..10f5f0d2 100644
--- a/src/app.c
+++ b/src/app.c
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32#include "ui/command.h" 32#include "ui/command.h"
33#include "ui/documentwidget.h" 33#include "ui/documentwidget.h"
34#include "ui/inputwidget.h" 34#include "ui/inputwidget.h"
35#include "ui/keys.h"
35#include "ui/labelwidget.h" 36#include "ui/labelwidget.h"
36#include "ui/sidebarwidget.h" 37#include "ui/sidebarwidget.h"
37#include "ui/text.h" 38#include "ui/text.h"
@@ -357,9 +358,11 @@ static void init_App_(iApp *d, int argc, char **argv) {
357#if defined (iPlatformApple) 358#if defined (iPlatformApple)
358 setupApplication_MacOS(); 359 setupApplication_MacOS();
359#endif 360#endif
361 init_Keys();
360 loadPrefs_App_(d); 362 loadPrefs_App_(d);
363 load_Keys(dataDir_App_);
361 load_Visited(d->visited, dataDir_App_); 364 load_Visited(d->visited, dataDir_App_);
362 load_Bookmarks(d->bookmarks, dataDir_App_); 365 load_Bookmarks(d->bookmarks, dataDir_App_);
363 if (isFirstRun) { 366 if (isFirstRun) {
364 /* Create the default bookmarks for a quick start. */ 367 /* Create the default bookmarks for a quick start. */
365 add_Bookmarks(d->bookmarks, 368 add_Bookmarks(d->bookmarks,
@@ -426,6 +429,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
426 429
427static void deinit_App(iApp *d) { 430static void deinit_App(iApp *d) {
428 saveState_App_(d); 431 saveState_App_(d);
432 save_Keys(dataDir_App_);
429 savePrefs_App_(d); 433 savePrefs_App_(d);
430 deinit_Prefs(&d->prefs); 434 deinit_Prefs(&d->prefs);
431 save_Bookmarks(d->bookmarks, dataDir_App_); 435 save_Bookmarks(d->bookmarks, dataDir_App_);
@@ -501,6 +505,10 @@ void processEvents_App(enum iAppEventMode eventMode) {
501 } 505 }
502 default: { 506 default: {
503 iBool wasUsed = processEvent_Window(d->window, &ev); 507 iBool wasUsed = processEvent_Window(d->window, &ev);
508 if (!wasUsed) {
509 /* There may be a key bindings for this. */
510 wasUsed = processEvent_Keys(&ev);
511 }
504 if (ev.type == SDL_USEREVENT && ev.user.code == command_UserEventCode) { 512 if (ev.type == SDL_USEREVENT && ev.user.code == command_UserEventCode) {
505#if defined (iPlatformApple) && !defined (iPlatformIOS) 513#if defined (iPlatformApple) && !defined (iPlatformIOS)
506 handleCommand_MacOS(command_UserEvent(&ev)); 514 handleCommand_MacOS(command_UserEvent(&ev));
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 5c6780d1..a2bea17b 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1536,7 +1536,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1536 updateVisible_DocumentWidget_(d); 1536 updateVisible_DocumentWidget_(d);
1537 return iTrue; 1537 return iTrue;
1538 } 1538 }
1539 else if (equalWidget_Command(cmd, w, "scroll.page")) { 1539 else if (equal_Command(cmd, "scroll.page") && document_App() == d) {
1540 if (argLabel_Command(cmd, "repeat")) { 1540 if (argLabel_Command(cmd, "repeat")) {
1541 /* TODO: Adjust scroll animation to be linear during repeated scroll? */ 1541 /* TODO: Adjust scroll animation to be linear during repeated scroll? */
1542 } 1542 }
@@ -1547,6 +1547,40 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1547 smoothDuration_DocumentWidget_); 1547 smoothDuration_DocumentWidget_);
1548 return iTrue; 1548 return iTrue;
1549 } 1549 }
1550 else if (equal_Command(cmd, "scroll.top") && document_App() == d) {
1551 init_Anim(&d->scrollY, 0);
1552 invalidate_VisBuf(d->visBuf);
1553 scroll_DocumentWidget_(d, 0);
1554 updateVisible_DocumentWidget_(d);
1555 refresh_Widget(w);
1556 return iTrue;
1557 }
1558 else if (equal_Command(cmd, "scroll.bottom") && document_App() == d) {
1559 init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));
1560 invalidate_VisBuf(d->visBuf);
1561 scroll_DocumentWidget_(d, 0);
1562 updateVisible_DocumentWidget_(d);
1563 refresh_Widget(w);
1564 return iTrue;
1565 }
1566 else if (equal_Command(cmd, "scroll.step") && document_App() == d) {
1567 smoothScroll_DocumentWidget_(d,
1568 3 * lineHeight_Text(paragraph_FontId) * arg_Command(cmd),
1569 smoothDuration_DocumentWidget_);
1570 return iTrue;
1571 }
1572#if 0
1573 case SDLK_PAGEUP:
1574 case SDLK_PAGEDOWN:
1575 case SDLK_SPACE:
1576 postCommand_Widget(
1577 w,
1578 "scroll.page arg:%d repeat:%d",
1579 (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,
1580 ev->key.repeat != 0);
1581 return iTrue;
1582 }
1583#endif
1550 else if (equal_Command(cmd, "document.goto") && document_App() == d) { 1584 else if (equal_Command(cmd, "document.goto") && document_App() == d) {
1551 const iRangecc heading = range_Command(cmd, "heading"); 1585 const iRangecc heading = range_Command(cmd, "heading");
1552 if (heading.start) { 1586 if (heading.start) {
@@ -1790,45 +1824,6 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1790 refresh_Widget(w); 1824 refresh_Widget(w);
1791 } 1825 }
1792 break; 1826 break;
1793 case SDLK_HOME:
1794 init_Anim(&d->scrollY, 0);
1795 invalidate_VisBuf(d->visBuf);
1796 scroll_DocumentWidget_(d, 0);
1797 updateVisible_DocumentWidget_(d);
1798 refresh_Widget(w);
1799 return iTrue;
1800 case SDLK_END:
1801 init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));
1802 invalidate_VisBuf(d->visBuf);
1803 scroll_DocumentWidget_(d, 0);
1804 updateVisible_DocumentWidget_(d);
1805 refresh_Widget(w);
1806 return iTrue;
1807 case SDLK_UP:
1808 case SDLK_DOWN:
1809 if (mods == 0) {
1810 if (ev->key.repeat) {
1811// if (!d->smoothContinue) {
1812// d->smoothContinue = iTrue;
1813// }
1814// else return iTrue;
1815 }
1816 smoothScroll_DocumentWidget_(d,
1817 3 * lineHeight_Text(paragraph_FontId) *
1818 (key == SDLK_UP ? -1 : 1),
1819 /*gap_Text * */smoothDuration_DocumentWidget_);
1820 return iTrue;
1821 }
1822 break;
1823 case SDLK_PAGEUP:
1824 case SDLK_PAGEDOWN:
1825 case SDLK_SPACE:
1826 postCommand_Widget(
1827 w,
1828 "scroll.page arg:%d repeat:%d",
1829 (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,
1830 ev->key.repeat != 0);
1831 return iTrue;
1832#if 1 1827#if 1
1833 case SDLK_KP_1: 1828 case SDLK_KP_1:
1834 case '`': { 1829 case '`': {
diff --git a/src/ui/keys.c b/src/ui/keys.c
new file mode 100644
index 00000000..d46d20bf
--- /dev/null
+++ b/src/ui/keys.c
@@ -0,0 +1,154 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#include "keys.h"
24#include "util.h"
25#include "app.h"
26
27#include <the_Foundation/sortedarray.h>
28
29iDeclareType(Keys)
30iDeclareType(Binding)
31
32struct Impl_Binding {
33 int key;
34 int mods;
35 iString command;
36 iString label;
37};
38
39static int cmp_Binding_(const void *a, const void *b) {
40 const iBinding *d = a, *other = b;
41 const int cmp = iCmp(d->key, other->key);
42 if (cmp == 0) {
43 return iCmp(d->mods, other->mods);
44 }
45 return cmp;
46}
47
48struct Impl_Keys {
49 iSortedArray bindings;
50};
51
52static iKeys keys_;
53
54static void clear_Keys_(iKeys *d) {
55 iForEach(Array, i, &d->bindings.values) {
56 iBinding *bind = i.value;
57 deinit_String(&bind->command);
58 deinit_String(&bind->label);
59 }
60}
61
62static void bindDefaults_(void) {
63 bind_Keys("scroll.top", SDLK_HOME, 0);
64 bind_Keys("scroll.bottom", SDLK_END, 0);
65 bind_Keys("scroll.step arg:-1", SDLK_UP, 0);
66 bind_Keys("scroll.step arg:1", SDLK_DOWN, 0);
67 bind_Keys("scroll.page arg:-1", SDLK_PAGEUP, 0);
68 bind_Keys("scroll.page arg:-1", SDLK_SPACE, KMOD_SHIFT);
69 bind_Keys("scroll.page arg:1", SDLK_PAGEDOWN, 0);
70 bind_Keys("scroll.page arg:1", SDLK_SPACE, 0);
71}
72
73static iBinding *find_Keys_(iKeys *d, int key, int mods) {
74 const iBinding bind = { .key = key, .mods = mods };
75 size_t pos;
76 if (locate_SortedArray(&d->bindings, &bind, &pos)) {
77 return at_SortedArray(&d->bindings, pos);
78 }
79 return NULL;
80}
81
82static iBinding *findCommand_Keys_(iKeys *d, const char *command) {
83 /* Note: O(n) */
84 iForEach(Array, i, &d->bindings.values) {
85 iBinding *bind = i.value;
86 if (!cmp_String(&bind->command, command)) {
87 return bind;
88 }
89 }
90 return NULL;
91}
92
93/*----------------------------------------------------------------------------------------------*/
94
95void init_Keys(void) {
96 iKeys *d = &keys_;
97 init_SortedArray(&d->bindings, sizeof(iBinding), cmp_Binding_);
98 bindDefaults_();
99}
100
101void deinit_Keys(void) {
102 iKeys *d = &keys_;
103 clear_Keys_(d);
104 deinit_SortedArray(&d->bindings);
105}
106
107void load_Keys(const char *saveDir) {
108
109}
110
111void save_Keys(const char *saveDir) {
112
113}
114
115void bind_Keys(const char *command, int key, int mods) {
116 iKeys *d = &keys_;
117 iBinding *bind = find_Keys_(d, key, mods);
118 if (bind) {
119 setCStr_String(&bind->command, command);
120 }
121 else {
122 iBinding bind;
123 bind.key = key;
124 bind.mods = mods;
125 initCStr_String(&bind.command, command);
126 init_String(&bind.label);
127 insert_SortedArray(&d->bindings, &bind);
128 }
129}
130
131void setLabel_Keys(const char *command, const char *label) {
132 iBinding *bind = findCommand_Keys_(&keys_, command);
133 if (bind) {
134 setCStr_String(&bind->label, label);
135 }
136}
137
138//const iString *label_Keys(const char *command) {
139
140//}
141
142//const char *shortcutLabel_Keys(const char *command) {}
143
144iBool processEvent_Keys(const SDL_Event *ev) {
145 iKeys *d = &keys_;
146 if (ev->type == SDL_KEYDOWN) {
147 const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));
148 if (bind) {
149 postCommandString_App(&bind->command);
150 return iTrue;
151 }
152 }
153 return iFalse;
154}
diff --git a/src/ui/keys.h b/src/ui/keys.h
index a9b13df3..157ddea5 100644
--- a/src/ui/keys.h
+++ b/src/ui/keys.h
@@ -22,7 +22,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#pragma once 23#pragma once
24 24
25#include <the_Foundation/defs.h> 25#include <the_Foundation/string.h>
26#include <SDL_events.h>
26 27
27#if defined (iPlatformApple) 28#if defined (iPlatformApple)
28# define reload_KeyShortcut SDLK_r, KMOD_PRIMARY 29# define reload_KeyShortcut SDLK_r, KMOD_PRIMARY
@@ -41,3 +42,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
41# define byWord_KeyModifier KMOD_CTRL 42# define byWord_KeyModifier KMOD_CTRL
42# define byLine_KeyModifier 0 43# define byLine_KeyModifier 0
43#endif 44#endif
45
46void init_Keys (void);
47void deinit_Keys (void);
48
49void load_Keys (const char *saveDir);
50void save_Keys (const char *saveDir);
51
52void bind_Keys (const char *command, int key, int mods);
53void setLabel_Keys (const char *command, const char *label);
54
55//const iString * label_Keys (const char *command);
56//const char * shortcutLabel_Keys (const char *command);
57
58iBool processEvent_Keys (const SDL_Event *);