=> bfeb00ac6c606b083da18a113e0ddf4e18448e76
[1mdiff --git a/res/about/version.gmi b/res/about/version.gmi[m [1mindex 0c74bc20..5c90fb2c 100644[m [1m--- a/res/about/version.gmi[m [1m+++ b/res/about/version.gmi[m [36m@@ -7,6 +7,7 @@[m # Release notes[m [m ## 0.7[m [32m+[m[32m* Basic set of user-configurable key bindings.[m * Sidebar: Added a "New Identity" button and a link to "about:help" if there no identities.[m * Faster drawing of certain UI elements: site icon and current heading in the left margin, unfocused input fields, timestamp at the end of the page.[m * History is not updated until a network request finishes.[m [1mdiff --git a/src/ui/keys.c b/src/ui/keys.c[m [1mindex cc7dabef..04b4793b 100644[m [1m--- a/src/ui/keys.c[m [1m+++ b/src/ui/keys.c[m [36m@@ -24,6 +24,8 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m #include "util.h"[m #include "app.h"[m [m [32m+[m[32m#include[m [32m+[m[32m#include [m #include [m [m iDeclareType(Keys)[m [36m@@ -116,6 +118,8 @@[m [mvoid setKey_Binding(int id, int key, int mods) {[m [m /*----------------------------------------------------------------------------------------------*/[m [m [32m+[m[32mstatic const char *filename_Keys_ = "bindings.txt";[m [32m+[m void init_Keys(void) {[m iKeys *d = &keys_;[m init_Array(&d->bindings, sizeof(iBinding));[m [36m@@ -132,11 +136,55 @@[m [mvoid deinit_Keys(void) {[m }[m [m void load_Keys(const char *saveDir) {[m [31m-[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m iFile *f = iClob(newCStr_File(concatPath_CStr(saveDir, filename_Keys_)));[m [32m+[m[32m if (open_File(f, readOnly_FileMode | text_FileMode)) {[m [32m+[m[32m iBlock * src = collect_Block(readAll_File(f));[m [32m+[m[32m iRangecc line = iNullRange;[m [32m+[m[32m while (nextSplit_Rangecc(range_Block(src), "\n", &line)) {[m [32m+[m[32m int id, key;[m [32m+[m[32m char modBits[5];[m [32m+[m[32m iZap(modBits);[m [32m+[m[32m sscanf(line.start, "%d %x %4s", &id, &key, modBits);[m [32m+[m[32m iBinding *bind = findId_Keys_(d, id);[m [32m+[m[32m if (bind) {[m [32m+[m[32m bind->key = key;[m [32m+[m[32m bind->mods = 0;[m [32m+[m[32m const char *m = modBits;[m [32m+[m[32m for (int i = 0; i < 4 && *m; i++, m++) {[m [32m+[m[32m if (*m == 's') bind->mods |= KMOD_SHIFT;[m [32m+[m[32m if (*m == 'a') bind->mods |= KMOD_ALT;[m [32m+[m[32m if (*m == 'c') bind->mods |= KMOD_CTRL;[m [32m+[m[32m if (*m == 'g') bind->mods |= KMOD_GUI;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m updateLookup_Keys_(d);[m }[m [m void save_Keys(const char *saveDir) {[m [31m-[m [32m+[m[32m iKeys *d = &keys_;[m [32m+[m[32m iFile *f = newCStr_File(concatPath_CStr(saveDir, filename_Keys_));[m [32m+[m[32m if (open_File(f, writeOnly_FileMode | text_FileMode)) {[m [32m+[m[32m iString *line = collectNew_String();[m [32m+[m[32m iConstForEach(Array, i, &d->bindings) {[m [32m+[m[32m const iBinding *bind = i.value;[m [32m+[m[32m format_String(line, "%d %x ", bind->id, bind->key);[m [32m+[m[32m if (bind->mods == 0) {[m [32m+[m[32m appendCStr_String(line, "0");[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m if (bind->mods & KMOD_SHIFT) appendChar_String(line, 's');[m [32m+[m[32m if (bind->mods & KMOD_ALT) appendChar_String(line, 'a');[m [32m+[m[32m if (bind->mods & KMOD_CTRL) appendChar_String(line, 'c');[m [32m+[m[32m if (bind->mods & KMOD_GUI) appendChar_String(line, 'g');[m [32m+[m[32m }[m [32m+[m[32m appendChar_String(line, '\n');[m [32m+[m[32m write_File(f, &line->chars);[m [32m+[m[32m }[m [32m+[m[32m iRelease(f);[m [32m+[m[32m }[m }[m [m void bind_Keys(int id, const char *command, int key, int mods) {[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).