Lagrange [work/v1.12]
Saving and loading key bindings
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 <the_Foundation/file.h>[m
[32m+[m[32m#include <the_Foundation/path.h>[m
#include <the_Foundation/ptrset.h>[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