[1mdiff --git a/src/app.c b/src/app.c[m
[1mindex 3c354438..a6a2a0a2 100644[m
[1m--- a/src/app.c[m
[1m+++ b/src/app.c[m
[36m@@ -1645,19 +1645,21 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m
}[m
}[m
#endif[m
[31m- /* Per-window processing. */[m
iBool wasUsed = iFalse;[m
[31m- listWindows_App_(d, &windows);[m
[31m- iConstForEach(PtrArray, iter, &windows) {[m
[31m- iWindow *window = iter.ptr;[m
[31m- setCurrent_Window(window);[m
[31m- window->lastHover = window->hover;[m
[31m- wasUsed = processEvent_Window(window, &ev);[m
[31m- if (ev.type == SDL_MOUSEMOTION) {[m
[31m- /* Only offered to the frontmost window. */[m
[31m- break;[m
[32m+[m[32m /* Per-window processing. */[m
[32m+[m[32m if (!isEmpty_PtrArray(&d->mainWindows)) {[m
[32m+[m[32m listWindows_App_(d, &windows);[m
[32m+[m[32m iConstForEach(PtrArray, iter, &windows) {[m
[32m+[m[32m iWindow *window = iter.ptr;[m
[32m+[m[32m setCurrent_Window(window);[m
[32m+[m[32m window->lastHover = window->hover;[m
[32m+[m[32m wasUsed = processEvent_Window(window, &ev);[m
[32m+[m[32m if (ev.type == SDL_MOUSEMOTION) {[m
[32m+[m[32m /* Only offered to the frontmost window. */[m
[32m+[m[32m break;[m
[32m+[m[32m }[m
[32m+[m[32m if (wasUsed) break;[m
}[m
[31m- if (wasUsed) break;[m
}[m
setCurrent_Window(d->window);[m
if (!wasUsed) {[m
[36m@@ -1778,7 +1780,14 @@[m [mstatic int resizeWatcher_(void *user, SDL_Event *event) {[m
dispatchEvent_Window(as_Window(d->window), &u);[m
}[m
#endif[m
[31m- drawWhileResizing_MainWindow(d->window, winev->data1, winev->data2);[m
[32m+[m[32m /* Find the window that is being resized and redraw it immediately. */[m
[32m+[m[32m iConstForEach(PtrArray, i, &d->mainWindows) {[m
[32m+[m[32m const iMainWindow *win = i.ptr;[m
[32m+[m[32m if (SDL_GetWindowID(win->base.win) == winev->windowID) {[m
[32m+[m[32m drawWhileResizing_MainWindow(d->window, winev->data1, winev->data2);[m
[32m+[m[32m break;[m
[32m+[m[32m }[m
[32m+[m[32m }[m
}[m
return 0;[m
}[m
[36m@@ -2051,6 +2060,9 @@[m [mvoid addWindow_App(iMainWindow *win) {[m
void removeWindow_App(iMainWindow *win) {[m
iApp *d = &app_;[m
removeOne_PtrArray(&d->mainWindows, win);[m
[32m+[m[32m if (isEmpty_PtrArray(&d->mainWindows)) {[m
[32m+[m[32m d->window = NULL;[m
[32m+[m[32m }[m
}[m
[m
size_t numWindows_App(void) {[m
[36m@@ -2386,11 +2398,6 @@[m [mvoid closeWindow_App(iMainWindow *win) {[m
}[m
}[m
}[m
[31m- if (isEmpty_PtrArray(&d->mainWindows)) {[m
[31m- d->window = NULL;[m
[31m- setActiveWindow_App(NULL);[m
[31m- setCurrent_Window(NULL);[m
[31m- }[m
}[m
[m
static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) {[m
[36m@@ -2552,36 +2559,10 @@[m [mstatic void invalidateCachedDocuments_App_(void) {[m
}[m
}[m
[m
[31m-iBool handleCommand_App(const char *cmd) {[m
[31m- iApp *d = &app_;[m
[32m+[m[32mstatic iBool handleNonWindowRelatedCommand_App_(iApp *d, const char *cmd) {[m
const iBool isFrozen = !d->window || d->window->isDrawFrozen;[m
[31m- /* TODO: Maybe break this up a little bit? There's a very long list of ifs here. */[m
[31m- if (equal_Command(cmd, "config.error")) {[m
[31m- makeSimpleMessage_Widget(uiTextCaution_ColorEscape "CONFIG ERROR",[m
[31m- format_CStr("Error in config file: %s\n"[m
[31m- "See "about:debug" for details.",[m
[31m- suffixPtr_Command(cmd, "where")));[m
[31m- return iTrue;[m
[31m- }[m
[31m-#if 0 /* disabled in v1.11 */[m
[31m- else if (equal_Command(cmd, "fontpack.suggest.classic")) {[m
[31m- /* TODO: Don't use this when system fonts are accessible. */[m
[31m- if (!isInstalled_Fonts("classic-set") && !isInstalled_Fonts("cjk")) {[m
[31m- makeQuestion_Widget([m
[31m- uiHeading_ColorEscape "${heading.fontpack.classic}",[m
[31m- "${dlg.fontpack.classic.msg}",[m
[31m- (iMenuItem[]){[m
[31m- { "${cancel}" },[m
[31m- { uiTextAction_ColorEscape "${dlg.fontpack.classic}",[m
[31m- 0,[m
[31m- 0,[m
[31m- "!open newtab:1 url:gemini://skyjake.fi/fonts/classic-set.fontpack" } },[m
[31m- 2);[m
[31m- }[m
[31m- return iTrue;[m
[31m- }[m
[31m-#endif[m
[31m- else if (equal_Command(cmd, "prefs.changed")) {[m
[32m+[m[32m /* Commands related to preferences. */[m
[32m+[m[32m if (equal_Command(cmd, "prefs.changed")) {[m
savePrefs_App_(d);[m
return iTrue;[m
}[m
[36m@@ -2641,28 +2622,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
d->prefs.langTo = argLabel_Command(cmd, "to");[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "ui.split")) {[m
[31m- if (argLabel_Command(cmd, "swap")) {[m
[31m- swapRoots_MainWindow(d->window);[m
[31m- return iTrue;[m
[31m- }[m
[31m- if (argLabel_Command(cmd, "focusother")) {[m
[31m- iWindow *baseWin = &d->window->base;[m
[31m- if (baseWin->roots[1]) {[m
[31m- baseWin->keyRoot =[m
[31m- (baseWin->keyRoot == baseWin->roots[1] ? baseWin->roots[0] : baseWin->roots[1]);[m
[31m- }[m
[31m- }[m
[31m- d->window->pendingSplitMode =[m
[31m- (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1);[m
[31m- const char *url = suffixPtr_Command(cmd, "url");[m
[31m- setCStr_String(d->window->pendingSplitUrl, url ? url : "");[m
[31m- if (hasLabel_Command(cmd, "origin")) {[m
[31m- set_String(d->window->pendingSplitOrigin, string_Command(cmd, "origin"));[m
[31m- }[m
[31m- postRefresh_App();[m
[31m- return iTrue;[m
[31m- }[m
else if (equal_Command(cmd, "window.retain")) {[m
d->prefs.retainWindowSize = arg_Command(cmd);[m
return iTrue;[m
[36m@@ -2671,186 +2630,174 @@[m [miBool handleCommand_App(const char *cmd) {[m
d->prefs.customFrame = arg_Command(cmd);[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "window.maximize")) {[m
[31m- const size_t winIndex = argU32Label_Command(cmd, "index");[m
[31m- if (winIndex < size_PtrArray(&d->mainWindows)) {[m
[31m- iMainWindow *win = at_PtrArray(&d->mainWindows, winIndex);[m
[31m- if (!argLabel_Command(cmd, "toggle")) {[m
[31m- setSnap_MainWindow(win, maximized_WindowSnap);[m
[31m- }[m
[31m- else {[m
[31m- setSnap_MainWindow([m
[31m- win, snap_MainWindow(win) == maximized_WindowSnap ? 0 : maximized_WindowSnap);[m
[31m- }[m
[31m- }[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "window.fullscreen")) {[m
[31m- const iBool wasFull = snap_MainWindow(d->window) == fullscreen_WindowSnap;[m
[31m- setSnap_MainWindow(d->window, wasFull ? 0 : fullscreen_WindowSnap);[m
[31m- postCommandf_App("window.fullscreen.changed arg:%d", !wasFull);[m
[31m- return iTrue;[m
[31m- }[m
else if (equal_Command(cmd, "prefs.retaintabs.changed")) {[m
d->prefs.retainTabs = arg_Command(cmd);[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "font.reset")) {[m
[31m- resetFonts_App();[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.font.smooth.changed")) {[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m setFreezeDraw_MainWindow(get_MainWindow(), iTrue);[m
[32m+[m[32m }[m
[32m+[m[32m d->prefs.fontSmoothing = arg_Command(cmd) != 0;[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m resetFontCache_Text(text_Window(get_MainWindow())); /* clear the glyph cache */[m
[32m+[m[32m postCommand_App("font.changed");[m
[32m+[m[32m postCommand_App("window.unfreeze");[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "font.reload")) {[m
[31m- reload_Fonts(); /* also does font cache reset, window invalidation */[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.gemtext.ansi.fg.changed")) {[m
[32m+[m[32m iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFg_AnsiFlag, arg_Command(cmd));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "font.find")) {[m
[31m- searchOnlineLibraryForCharacters_Fonts(string_Command(cmd, "chars"));[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.gemtext.ansi.bg.changed")) {[m
[32m+[m[32m iChangeFlags(d->prefs.gemtextAnsiEscapes, allowBg_AnsiFlag, arg_Command(cmd));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "font.found")) {[m
[31m- if (hasLabel_Command(cmd, "error")) {[m
[31m- makeSimpleMessage_Widget("${heading.glyphfinder}",[m
[31m- format_CStr("%d %s",[m
[31m- argLabel_Command(cmd, "error"),[m
[31m- suffixPtr_Command(cmd, "msg")));[m
[31m- return iTrue;[m
[31m- }[m
[31m- iString *src = collectNew_String();[m
[31m- setCStr_String(src, "# ${heading.glyphfinder.results}\n\n");[m
[31m- iRangecc path = iNullRange;[m
[31m- iBool isFirst = iTrue;[m
[31m- while (nextSplit_Rangecc(range_Command(cmd, "packs"), ",", &path)) {[m
[31m- if (isFirst) {[m
[31m- appendCStr_String(src, "${glyphfinder.results}\n\n");[m
[31m- }[m
[31m- iRangecc fpath = path;[m
[31m- iRangecc fsize = path;[m
[31m- fpath.end = strchr(fpath.start, ';');[m
[31m- fsize.start = fpath.end + 1;[m
[31m- const uint32_t size = strtoul(fsize.start, NULL, 10);[m
[31m- appendFormat_String(src, "=> gemini://skyjake.fi/fonts/%s %s (%.1f MB)\n",[m
[31m- cstr_Rangecc(fpath),[m
[31m- cstr_Rangecc(fpath),[m
[31m- (double) size / 1.0e6);[m
[31m- isFirst = iFalse;[m
[31m- }[m
[31m- if (isFirst) {[m
[31m- appendFormat_String(src, "${glyphfinder.results.empty}\n");[m
[31m- }[m
[31m- appendCStr_String(src, "\n=> about:fonts ${menu.fonts}");[m
[31m- iDocumentWidget *page = newTab_App(NULL, iTrue);[m
[31m- translate_Lang(src);[m
[31m- setUrlAndSource_DocumentWidget(page,[m
[31m- collectNewCStr_String(""),[m
[31m- collectNewCStr_String("text/gemini"),[m
[31m- utf8_String(src));[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.gemtext.ansi.fontstyle.changed")) {[m
[32m+[m[32m iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFontStyle_AnsiFlag, arg_Command(cmd));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "font.set")) {[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.mono.gemini.changed") ||[m
[32m+[m[32m equal_Command(cmd, "prefs.mono.gopher.changed")) {[m
[32m+[m[32m const iBool isSet = (arg_Command(cmd) != 0);[m
if (!isFrozen) {[m
setFreezeDraw_MainWindow(get_MainWindow(), iTrue);[m
}[m
[31m- struct {[m
[31m- const char *label;[m
[31m- enum iPrefsString ps;[m
[31m- int fontId;[m
[31m- } params[] = {[m
[31m- { "ui", uiFont_PrefsString, default_FontId },[m
[31m- { "mono", monospaceFont_PrefsString, monospace_FontId },[m
[31m- { "heading", headingFont_PrefsString, documentHeading_FontId },[m
[31m- { "body", bodyFont_PrefsString, documentBody_FontId },[m
[31m- { "monodoc", monospaceDocumentFont_PrefsString, documentMonospace_FontId },[m
[31m- };[m
[31m- iBool wasChanged = iFalse;[m
[31m- iForIndices(i, params) {[m
[31m- if (hasLabel_Command(cmd, params[i].label)) {[m
[31m- iString *ps = &d->prefs.strings[params[i].ps];[m
[31m- const iString *newFont = string_Command(cmd, params[i].label);[m
[31m- if (!equal_String(ps, newFont)) {[m
[31m- set_String(ps, newFont);[m
[31m- wasChanged = iTrue;[m
[31m- }[m
[31m- }[m
[32m+[m[32m if (startsWith_CStr(cmd, "prefs.mono.gemini")) {[m
[32m+[m[32m d->prefs.monospaceGemini = isSet;[m
}[m
[31m- if (wasChanged) {[m
[31m- if (isFinishedLaunching_App()) { /* there's a reset when launch is finished */[m
[31m- resetFonts_Text(text_Window(get_MainWindow()));[m
[31m- }[m
[31m- postCommand_App("font.changed");[m
[32m+[m[32m else {[m
[32m+[m[32m d->prefs.monospaceGopher = isSet;[m
}[m
if (!isFrozen) {[m
[32m+[m[32m postCommand_App("font.changed");[m
postCommand_App("window.unfreeze");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "zoom.set")) {[m
[31m- if (!isFrozen) {[m
[31m- setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.boldlink.dark.changed") ||[m
[32m+[m[32m equal_Command(cmd, "prefs.boldlink.light.changed") ||[m
[32m+[m[32m equal_Command(cmd, "prefs.boldlink.visited.changed")) {[m
[32m+[m[32m const iBool isSet = (arg_Command(cmd) != 0);[m
[32m+[m[32m if (startsWith_CStr(cmd, "prefs.boldlink.visited")) {[m
[32m+[m[32m d->prefs.boldLinkVisited = isSet;[m
}[m
[31m- if (arg_Command(cmd) != d->prefs.zoomPercent) {[m
[31m- d->prefs.zoomPercent = arg_Command(cmd);[m
[31m- invalidateCachedDocuments_App_();[m
[32m+[m[32m else if (startsWith_CStr(cmd, "prefs.boldlink.dark")) {[m
[32m+[m[32m d->prefs.boldLinkDark = isSet;[m
}[m
[31m- setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f);[m
[31m- if (!isFrozen) {[m
[32m+[m[32m else {[m
[32m+[m[32m d->prefs.boldLinkLight = isSet;[m
[32m+[m[32m }[m
[32m+[m[32m if (!d->isLoadingPrefs) {[m
postCommand_App("font.changed");[m
[31m- postCommand_App("window.unfreeze");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "zoom.delta")) {[m
[31m- if (!isFrozen) {[m
[31m- setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */[m
[31m- }[m
[31m- int delta = arg_Command(cmd);[m
[31m- if (d->prefs.zoomPercent < 100 || (delta < 0 && d->prefs.zoomPercent == 100)) {[m
[31m- delta /= 2;[m
[31m- }[m
[31m- d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200);[m
[31m- invalidateCachedDocuments_App_();[m
[31m- setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f);[m
[31m- if (!isFrozen) {[m
[31m- postCommand_App("font.changed");[m
[31m- postCommand_App("window.unfreeze");[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.biglede.changed")) {[m
[32m+[m[32m d->prefs.bigFirstParagraph = arg_Command(cmd) != 0;[m
[32m+[m[32m if (!d->isLoadingPrefs) {[m
[32m+[m[32m postCommand_App("document.layout.changed");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "smoothscroll")) {[m
[31m- d->prefs.smoothScrolling = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.justify.changed")) {[m
[32m+[m[32m d->prefs.justifyParagraph = arg_Command(cmd) != 0;[m
[32m+[m[32m if (!d->isLoadingPrefs) {[m
[32m+[m[32m postCommand_App("document.layout.changed");[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "scrollspeed")) {[m
[31m- const int type = argLabel_Command(cmd, "type");[m
[31m- if (type == keyboard_ScrollType || type == mouse_ScrollType) {[m
[31m- d->prefs.smoothScrollSpeed[type] = iClamp(arg_Command(cmd), 1, 40);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.plaintext.wrap.changed")) {[m
[32m+[m[32m d->prefs.plainTextWrap = arg_Command(cmd) != 0;[m
[32m+[m[32m if (!d->isLoadingPrefs) {[m
[32m+[m[32m postCommand_App("document.layout.changed");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "decodeurls")) {[m
[31m- d->prefs.decodeUserVisibleURLs = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.sideicon.changed")) {[m
[32m+[m[32m d->prefs.sideIcon = arg_Command(cmd) != 0;[m
[32m+[m[32m postRefresh_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "imageloadscroll")) {[m
[31m- d->prefs.loadImageInsteadOfScrolling = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.centershort.changed")) {[m
[32m+[m[32m d->prefs.centerShortDocs = arg_Command(cmd) != 0;[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m invalidate_Window(d->window);[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "hidetoolbarscroll")) {[m
[31m- d->prefs.hideToolbarOnScroll = arg_Command(cmd);[m
[31m- if (!d->prefs.hideToolbarOnScroll) {[m
[31m- showToolbar_Root(get_Root(), iTrue);[m
[31m- }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.collapsepreonload.changed")) {[m
[32m+[m[32m d->prefs.collapsePreOnLoad = arg_Command(cmd) != 0;[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "returnkey.set")) {[m
[31m- d->prefs.returnKey = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.hoverlink.changed")) {[m
[32m+[m[32m d->prefs.hoverLink = arg_Command(cmd) != 0;[m
[32m+[m[32m postRefresh_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "pinsplit.set")) {[m
[31m- d->prefs.pinSplit = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.hoverlink.toggle")) {[m
[32m+[m[32m d->prefs.hoverLink = !d->prefs.hoverLink;[m
[32m+[m[32m postRefresh_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "theme.set")) {[m
[31m- const int isAuto = argLabel_Command(cmd, "auto");[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.dataurl.openimages.changed")) {[m
[32m+[m[32m d->prefs.openDataUrlImagesOnLoad = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.archive.openindex.changed")) {[m
[32m+[m[32m d->prefs.openArchiveIndexPages = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.bookmarks.addbottom.changed")) {[m
[32m+[m[32m d->prefs.addBookmarksToBottom = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.font.warnmissing.changed")) {[m
[32m+[m[32m d->prefs.warnAboutMissingGlyphs = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.animate.changed")) {[m
[32m+[m[32m d->prefs.uiAnimations = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.blink.changed")) {[m
[32m+[m[32m d->prefs.blinkingCursor = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "prefs.time.24h.changed")) {[m
[32m+[m[32m d->prefs.time24h = arg_Command(cmd) != 0;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "smoothscroll")) {[m
[32m+[m[32m d->prefs.smoothScrolling = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "scrollspeed")) {[m
[32m+[m[32m const int type = argLabel_Command(cmd, "type");[m
[32m+[m[32m if (type == keyboard_ScrollType || type == mouse_ScrollType) {[m
[32m+[m[32m d->prefs.smoothScrollSpeed[type] = iClamp(arg_Command(cmd), 1, 40);[m
[32m+[m[32m }[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "decodeurls")) {[m
[32m+[m[32m d->prefs.decodeUserVisibleURLs = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "imageloadscroll")) {[m
[32m+[m[32m d->prefs.loadImageInsteadOfScrolling = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "returnkey.set")) {[m
[32m+[m[32m d->prefs.returnKey = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "pinsplit.set")) {[m
[32m+[m[32m d->prefs.pinSplit = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "theme.set")) {[m
[32m+[m[32m const int isAuto = argLabel_Command(cmd, "auto");[m
d->prefs.theme = arg_Command(cmd);[m
if (!isAuto) {[m
if (isDark_ColorTheme(d->prefs.theme) && d->isDarkSystemTheme) {[m
[36m@@ -2923,246 +2870,426 @@[m [miBool handleCommand_App(const char *cmd) {[m
postCommand_App("document.layout.changed redo:1");[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.font.smooth.changed")) {[m
[32m+[m[32m else if (equal_Command(cmd, "ansiescape")) {[m
[32m+[m[32m d->prefs.gemtextAnsiEscapes = arg_Command(cmd);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "saturation.set")) {[m
[32m+[m[32m d->prefs.saturation = (float) arg_Command(cmd) / 100.0f;[m
if (!isFrozen) {[m
[31m- setFreezeDraw_MainWindow(get_MainWindow(), iTrue);[m
[32m+[m[32m invalidate_Window(d->window);[m
}[m
[31m- d->prefs.fontSmoothing = arg_Command(cmd) != 0;[m
[31m- if (!isFrozen) {[m
[31m- resetFontCache_Text(text_Window(get_MainWindow())); /* clear the glyph cache */[m
[31m- postCommand_App("font.changed");[m
[31m- postCommand_App("window.unfreeze");[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "cachesize.set")) {[m
[32m+[m[32m d->prefs.maxCacheSize = arg_Command(cmd);[m
[32m+[m[32m if (d->prefs.maxCacheSize <= 0) {[m
[32m+[m[32m d->prefs.maxCacheSize = 0;[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "ansiescape")) {[m
[31m- d->prefs.gemtextAnsiEscapes = arg_Command(cmd);[m
[32m+[m[32m else if (equal_Command(cmd, "memorysize.set")) {[m
[32m+[m[32m d->prefs.maxMemorySize = arg_Command(cmd);[m
[32m+[m[32m if (d->prefs.maxMemorySize <= 0) {[m
[32m+[m[32m d->prefs.maxMemorySize = 0;[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.gemtext.ansi.fg.changed")) {[m
[31m- iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFg_AnsiFlag, arg_Command(cmd));[m
[32m+[m[32m else if (equal_Command(cmd, "urlsize.set")) {[m
[32m+[m[32m d->prefs.maxUrlSize = arg_Command(cmd);[m
[32m+[m[32m if (d->prefs.maxUrlSize < 1024) {[m
[32m+[m[32m d->prefs.maxUrlSize = 1024; /* Gemini protocol requirement */[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.gemtext.ansi.bg.changed")) {[m
[31m- iChangeFlags(d->prefs.gemtextAnsiEscapes, allowBg_AnsiFlag, arg_Command(cmd));[m
[32m+[m[32m else if (equal_Command(cmd, "searchurl")) {[m
[32m+[m[32m iString *url = &d->prefs.strings[searchUrl_PrefsString];[m
[32m+[m[32m setCStr_String(url, suffixPtr_Command(cmd, "address"));[m
[32m+[m[32m if (startsWith_String(url, "//")) {[m
[32m+[m[32m prependCStr_String(url, "gemini:");[m
[32m+[m[32m }[m
[32m+[m[32m if (!isEmpty_String(url) && !startsWithCase_String(url, "gemini://")) {[m
[32m+[m[32m prependCStr_String(url, "gemini://");[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.gemtext.ansi.fontstyle.changed")) {[m
[31m- iChangeFlags(d->prefs.gemtextAnsiEscapes, allowFontStyle_AnsiFlag, arg_Command(cmd));[m
[32m+[m[32m else if (equal_Command(cmd, "proxy.gemini")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[geminiProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.mono.gemini.changed") ||[m
[31m- equal_Command(cmd, "prefs.mono.gopher.changed")) {[m
[31m- const iBool isSet = (arg_Command(cmd) != 0);[m
[31m- if (!isFrozen) {[m
[31m- setFreezeDraw_MainWindow(get_MainWindow(), iTrue);[m
[32m+[m[32m else if (equal_Command(cmd, "proxy.gopher")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[gopherProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "proxy.http")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[httpProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m#if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT)[m
[32m+[m[32m else if (equal_Command(cmd, "downloads")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[downloadDir_PrefsString], suffixPtr_Command(cmd, "path"));[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m#endif[m
[32m+[m[32m else if (equal_Command(cmd, "downloads.open")) {[m
[32m+[m[32m postCommandf_App("open newtab:%d url:%s",[m
[32m+[m[32m argLabel_Command(cmd, "newtab"),[m
[32m+[m[32m cstrCollect_String(makeFileUrl_String(downloadDir_App())));[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "ca.file")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[caFile_PrefsString], suffixPtr_Command(cmd, "path"));[m
[32m+[m[32m if (!argLabel_Command(cmd, "noset")) {[m
[32m+[m[32m setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]);[m
}[m
[31m- if (startsWith_CStr(cmd, "prefs.mono.gemini")) {[m
[31m- d->prefs.monospaceGemini = isSet;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "ca.path")) {[m
[32m+[m[32m setCStr_String(&d->prefs.strings[caPath_PrefsString], suffixPtr_Command(cmd, "path"));[m
[32m+[m[32m if (!argLabel_Command(cmd, "noset")) {[m
[32m+[m[32m setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]);[m
}[m
[31m- else {[m
[31m- d->prefs.monospaceGopher = isSet;[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "search")) {[m
[32m+[m[32m const int newTab = argLabel_Command(cmd, "newtab");[m
[32m+[m[32m const iString *query = collect_String(suffix_Command(cmd, "query"));[m
[32m+[m[32m if (!isLikelyUrl_String(query)) {[m
[32m+[m[32m const iString *url = searchQueryUrl_App(query);[m
[32m+[m[32m if (!isEmpty_String(url)) {[m
[32m+[m[32m postCommandf_App("open newtab:%d url:%s", newTab, cstr_String(url));[m
[32m+[m[32m }[m
}[m
[31m- if (!isFrozen) {[m
[31m- postCommand_App("font.changed");[m
[31m- postCommand_App("window.unfreeze");[m
[32m+[m[32m else {[m
[32m+[m[32m postCommandf_App("open newtab:%d url:%s", newTab, cstr_String(query));[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.boldlink.dark.changed") ||[m
[31m- equal_Command(cmd, "prefs.boldlink.light.changed") ||[m
[31m- equal_Command(cmd, "prefs.boldlink.visited.changed")) {[m
[31m- const iBool isSet = (arg_Command(cmd) != 0);[m
[31m- if (startsWith_CStr(cmd, "prefs.boldlink.visited")) {[m
[31m- d->prefs.boldLinkVisited = isSet;[m
[31m- }[m
[31m- else if (startsWith_CStr(cmd, "prefs.boldlink.dark")) {[m
[31m- d->prefs.boldLinkDark = isSet;[m
[32m+[m[32m else if (equal_Command(cmd, "reveal")) {[m
[32m+[m[32m const iString *path = NULL;[m
[32m+[m[32m if (hasLabel_Command(cmd, "path")) {[m
[32m+[m[32m path = suffix_Command(cmd, "path");[m
}[m
[31m- else {[m
[31m- d->prefs.boldLinkLight = isSet;[m
[32m+[m[32m else if (hasLabel_Command(cmd, "url")) {[m
[32m+[m[32m path = collect_String(localFilePathFromUrl_String(suffix_Command(cmd, "url")));[m
}[m
[31m- if (!d->isLoadingPrefs) {[m
[31m- postCommand_App("font.changed");[m
[32m+[m[32m if (path) {[m
[32m+[m[32m revealPath_App(path);[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.biglede.changed")) {[m
[31m- d->prefs.bigFirstParagraph = arg_Command(cmd) != 0;[m
[31m- if (!d->isLoadingPrefs) {[m
[31m- postCommand_App("document.layout.changed");[m
[32m+[m[32m else if (equal_Command(cmd, "window.new")) {[m
[32m+[m[32m iMainWindow *newWin = new_MainWindow(initialWindowRect_App_(d, numWindows_App()));[m
[32m+[m[32m addWindow_App(newWin); /* takes ownership */[m
[32m+[m[32m SDL_ShowWindow(newWin->base.win);[m
[32m+[m[32m setCurrent_Window(newWin);[m
[32m+[m[32m if (hasLabel_Command(cmd, "url")) {[m
[32m+[m[32m postCommandf_Root(newWin->base.roots[0], "~open %s", cmd + 11 /* all arguments passed on */);[m
}[m
[32m+[m[32m else {[m
[32m+[m[32m postCommand_Root(newWin->base.roots[0], "~navigate.home");[m
[32m+[m[32m }[m
[32m+[m[32m postCommand_Root(newWin->base.roots[0], "~window.unfreeze");[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.justify.changed")) {[m
[31m- d->prefs.justifyParagraph = arg_Command(cmd) != 0;[m
[31m- if (!d->isLoadingPrefs) {[m
[31m- postCommand_App("document.layout.changed");[m
[32m+[m[32m else if (equal_Command(cmd, "bookmarks.changed")) {[m
[32m+[m[32m save_Bookmarks(d->bookmarks, dataDir_App_());[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "bookmarks.sort")) {[m
[32m+[m[32m sort_Bookmarks(d->bookmarks, arg_Command(cmd), cmpTitleAscending_Bookmark);[m
[32m+[m[32m postCommand_App("bookmarks.changed");[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "bookmarks.reload.remote")) {[m
[32m+[m[32m fetchRemote_Bookmarks(bookmarks_App());[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "bookmarks.request.finished")) {[m
[32m+[m[32m requestFinished_Bookmarks(bookmarks_App(), pointerLabel_Command(cmd, "req"));[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "feeds.refresh")) {[m
[32m+[m[32m refresh_Feeds();[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "visited.changed")) {[m
[32m+[m[32m save_Visited(d->visited, dataDir_App_());[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "idents.changed")) {[m
[32m+[m[32m saveIdentities_GmCerts(d->certs);[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "ident.signin")) {[m
[32m+[m[32m const iString *url = collect_String(suffix_Command(cmd, "url"));[m
[32m+[m[32m signIn_GmCerts([m
[32m+[m[32m d->certs,[m
[32m+[m[32m findIdentity_GmCerts(d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident")))),[m
[32m+[m[32m url);[m
[32m+[m[32m postCommand_App("navigate.reload");[m
[32m+[m[32m postCommand_App("idents.changed");[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "ident.signout")) {[m
[32m+[m[32m iGmIdentity *ident = findIdentity_GmCerts([m
[32m+[m[32m d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident"))));[m
[32m+[m[32m if (arg_Command(cmd)) {[m
[32m+[m[32m clearUse_GmIdentity(ident);[m
[32m+[m[32m }[m
[32m+[m[32m else {[m
[32m+[m[32m setUse_GmIdentity(ident, collect_String(suffix_Command(cmd, "url")), iFalse);[m
}[m
[32m+[m[32m postCommand_App("navigate.reload");[m
[32m+[m[32m postCommand_App("idents.changed");[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.plaintext.wrap.changed")) {[m
[31m- d->prefs.plainTextWrap = arg_Command(cmd) != 0;[m
[31m- if (!d->isLoadingPrefs) {[m
[31m- postCommand_App("document.layout.changed");[m
[32m+[m[32m else if (equal_Command(cmd, "os.theme.changed")) {[m
[32m+[m[32m const int dark = argLabel_Command(cmd, "dark");[m
[32m+[m[32m d->isDarkSystemTheme = dark;[m
[32m+[m[32m if (d->prefs.useSystemTheme) {[m
[32m+[m[32m const int contrast = argLabel_Command(cmd, "contrast");[m
[32m+[m[32m const int preferred = d->prefs.systemPreferredColorTheme[dark ^ 1];[m
[32m+[m[32m postCommandf_App("theme.set arg:%d auto:1",[m
[32m+[m[32m preferred >= 0 ? preferred[m
[32m+[m[32m : dark ? (contrast ? pureBlack_ColorTheme : dark_ColorTheme)[m
[32m+[m[32m : (contrast ? pureWhite_ColorTheme : light_ColorTheme));[m
}[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m else if (equal_Command(cmd, "updater.check")) {[m
[32m+[m[32m checkNow_Updater();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.sideicon.changed")) {[m
[31m- d->prefs.sideIcon = arg_Command(cmd) != 0;[m
[31m- postRefresh_App();[m
[32m+[m[32m else if (equal_Command(cmd, "fontpack.enable")) {[m
[32m+[m[32m const iString *packId = collect_String(suffix_Command(cmd, "id"));[m
[32m+[m[32m enablePack_Fonts(packId, arg_Command(cmd));[m
[32m+[m[32m postCommand_App("navigate.reload");[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.centershort.changed")) {[m
[31m- d->prefs.centerShortDocs = arg_Command(cmd) != 0;[m
[31m- if (!isFrozen) {[m
[31m- invalidate_Window(d->window);[m
[32m+[m[32m#if defined (LAGRANGE_ENABLE_IPC)[m
[32m+[m[32m else if (equal_Command(cmd, "ipc.list.urls")) {[m
[32m+[m[32m iProcessId pid = argLabel_Command(cmd, "pid");[m
[32m+[m[32m if (pid) {[m
[32m+[m[32m iString *urls = collectNew_String();[m
[32m+[m[32m iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) {[m
[32m+[m[32m append_String(urls, url_DocumentWidget(i.object));[m
[32m+[m[32m appendCStr_String(urls, "\n");[m
[32m+[m[32m }[m
[32m+[m[32m write_Ipc(pid, urls, response_IpcWrite);[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.collapsepreonload.changed")) {[m
[31m- d->prefs.collapsePreOnLoad = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "ipc.active.url")) {[m
[32m+[m[32m write_Ipc(argLabel_Command(cmd, "pid"),[m
[32m+[m[32m collectNewFormat_String([m
[32m+[m[32m "%s\n", d->window ? cstr_String(url_DocumentWidget(document_App())) : ""),[m
[32m+[m[32m response_IpcWrite);[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.hoverlink.changed")) {[m
[31m- d->prefs.hoverLink = arg_Command(cmd) != 0;[m
[31m- postRefresh_App();[m
[32m+[m[32m else if (equal_Command(cmd, "ipc.signal")) {[m
[32m+[m[32m if (argLabel_Command(cmd, "raise")) {[m
[32m+[m[32m if (d->window && d->window->base.win) {[m
[32m+[m[32m SDL_RaiseWindow(d->window->base.win);[m
[32m+[m[32m }[m
[32m+[m[32m }[m
[32m+[m[32m signal_Ipc(arg_Command(cmd));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.hoverlink.toggle")) {[m
[31m- d->prefs.hoverLink = !d->prefs.hoverLink;[m
[31m- postRefresh_App();[m
[31m- return iTrue;[m
[32m+[m[32m#endif /* defined (LAGRANGE_ENABLE_IPC) */[m
[32m+[m[32m else if (equal_Command(cmd, "quit")) {[m
[32m+[m[32m SDL_Event ev;[m
[32m+[m[32m ev.type = SDL_QUIT;[m
[32m+[m[32m SDL_PushEvent(&ev);[m
}[m
[31m- else if (equal_Command(cmd, "prefs.dataurl.openimages.changed")) {[m
[31m- d->prefs.openDataUrlImagesOnLoad = arg_Command(cmd) != 0;[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m}[m
[32m+[m
[32m+[m[32miBool handleCommand_App(const char *cmd) {[m
[32m+[m[32m iApp *d = &app_;[m
[32m+[m[32m const iBool isFrozen = !d->window || d->window->isDrawFrozen;[m
[32m+[m[32m const iBool isHeadless = numWindows_App() == 0;[m
[32m+[m[32m if (handleNonWindowRelatedCommand_App_(d, cmd)) {[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.archive.openindex.changed")) {[m
[31m- d->prefs.openArchiveIndexPages = arg_Command(cmd) != 0;[m
[32m+[m[32m if (isHeadless) {[m
[32m+[m[32m /* All the subsequent commands assume that a window exists. */[m
[32m+[m[32m return iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m /* TODO: Maybe break this up a little bit? There's a very long list of ifs here. */[m
[32m+[m[32m if (equal_Command(cmd, "config.error")) {[m
[32m+[m[32m makeSimpleMessage_Widget(uiTextCaution_ColorEscape "CONFIG ERROR",[m
[32m+[m[32m format_CStr("Error in config file: %s\n"[m
[32m+[m[32m "See "about:debug" for details.",[m
[32m+[m[32m suffixPtr_Command(cmd, "where")));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.bookmarks.addbottom.changed")) {[m
[31m- d->prefs.addBookmarksToBottom = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "ui.split")) {[m
[32m+[m[32m if (argLabel_Command(cmd, "swap")) {[m
[32m+[m[32m swapRoots_MainWindow(d->window);[m
[32m+[m[32m return iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m if (argLabel_Command(cmd, "focusother")) {[m
[32m+[m[32m iWindow *baseWin = &d->window->base;[m
[32m+[m[32m if (baseWin->roots[1]) {[m
[32m+[m[32m baseWin->keyRoot =[m
[32m+[m[32m (baseWin->keyRoot == baseWin->roots[1] ? baseWin->roots[0] : baseWin->roots[1]);[m
[32m+[m[32m }[m
[32m+[m[32m }[m
[32m+[m[32m d->window->pendingSplitMode =[m
[32m+[m[32m (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1);[m
[32m+[m[32m const char *url = suffixPtr_Command(cmd, "url");[m
[32m+[m[32m setCStr_String(d->window->pendingSplitUrl, url ? url : "");[m
[32m+[m[32m if (hasLabel_Command(cmd, "origin")) {[m
[32m+[m[32m set_String(d->window->pendingSplitOrigin, string_Command(cmd, "origin"));[m
[32m+[m[32m }[m
[32m+[m[32m postRefresh_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.font.warnmissing.changed")) {[m
[31m- d->prefs.warnAboutMissingGlyphs = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "window.maximize")) {[m
[32m+[m[32m const size_t winIndex = argU32Label_Command(cmd, "index");[m
[32m+[m[32m if (winIndex < size_PtrArray(&d->mainWindows)) {[m
[32m+[m[32m iMainWindow *win = at_PtrArray(&d->mainWindows, winIndex);[m
[32m+[m[32m if (!argLabel_Command(cmd, "toggle")) {[m
[32m+[m[32m setSnap_MainWindow(win, maximized_WindowSnap);[m
[32m+[m[32m }[m
[32m+[m[32m else {[m
[32m+[m[32m setSnap_MainWindow([m
[32m+[m[32m win, snap_MainWindow(win) == maximized_WindowSnap ? 0 : maximized_WindowSnap);[m
[32m+[m[32m }[m
[32m+[m[32m }[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.animate.changed")) {[m
[31m- d->prefs.uiAnimations = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "window.fullscreen")) {[m
[32m+[m[32m const iBool wasFull = snap_MainWindow(d->window) == fullscreen_WindowSnap;[m
[32m+[m[32m setSnap_MainWindow(d->window, wasFull ? 0 : fullscreen_WindowSnap);[m
[32m+[m[32m postCommandf_App("window.fullscreen.changed arg:%d", !wasFull);[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.blink.changed")) {[m
[31m- d->prefs.blinkingCursor = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "font.reset")) {[m
[32m+[m[32m resetFonts_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "prefs.time.24h.changed")) {[m
[31m- d->prefs.time24h = arg_Command(cmd) != 0;[m
[32m+[m[32m else if (equal_Command(cmd, "font.reload")) {[m
[32m+[m[32m reload_Fonts(); /* also does font cache reset, window invalidation */[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "saturation.set")) {[m
[31m- d->prefs.saturation = (float) arg_Command(cmd) / 100.0f;[m
[31m- if (!isFrozen) {[m
[31m- invalidate_Window(d->window);[m
[31m- }[m
[32m+[m[32m else if (equal_Command(cmd, "font.find")) {[m
[32m+[m[32m searchOnlineLibraryForCharacters_Fonts(string_Command(cmd, "chars"));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "cachesize.set")) {[m
[31m- d->prefs.maxCacheSize = arg_Command(cmd);[m
[31m- if (d->prefs.maxCacheSize <= 0) {[m
[31m- d->prefs.maxCacheSize = 0;[m
[32m+[m[32m else if (equal_Command(cmd, "font.found")) {[m
[32m+[m[32m if (hasLabel_Command(cmd, "error")) {[m
[32m+[m[32m makeSimpleMessage_Widget("${heading.glyphfinder}",[m
[32m+[m[32m format_CStr("%d %s",[m
[32m+[m[32m argLabel_Command(cmd, "error"),[m
[32m+[m[32m suffixPtr_Command(cmd, "msg")));[m
[32m+[m[32m return iTrue;[m
}[m
[32m+[m[32m iString *src = collectNew_String();[m
[32m+[m[32m setCStr_String(src, "# ${heading.glyphfinder.results}\n\n");[m
[32m+[m[32m iRangecc path = iNullRange;[m
[32m+[m[32m iBool isFirst = iTrue;[m
[32m+[m[32m while (nextSplit_Rangecc(range_Command(cmd, "packs"), ",", &path)) {[m
[32m+[m[32m if (isFirst) {[m
[32m+[m[32m appendCStr_String(src, "${glyphfinder.results}\n\n");[m
[32m+[m[32m }[m
[32m+[m[32m iRangecc fpath = path;[m
[32m+[m[32m iRangecc fsize = path;[m
[32m+[m[32m fpath.end = strchr(fpath.start, ';');[m
[32m+[m[32m fsize.start = fpath.end + 1;[m
[32m+[m[32m const uint32_t size = strtoul(fsize.start, NULL, 10);[m
[32m+[m[32m appendFormat_String(src, "=> gemini://skyjake.fi/fonts/%s %s (%.1f MB)\n",[m
[32m+[m[32m cstr_Rangecc(fpath),[m
[32m+[m[32m cstr_Rangecc(fpath),[m
[32m+[m[32m (double) size / 1.0e6);[m
[32m+[m[32m isFirst = iFalse;[m
[32m+[m[32m }[m
[32m+[m[32m if (isFirst) {[m
[32m+[m[32m appendFormat_String(src, "${glyphfinder.results.empty}\n");[m
[32m+[m[32m }[m
[32m+[m[32m appendCStr_String(src, "\n=> about:fonts ${menu.fonts}");[m
[32m+[m[32m iDocumentWidget *page = newTab_App(NULL, iTrue);[m
[32m+[m[32m translate_Lang(src);[m
[32m+[m[32m setUrlAndSource_DocumentWidget(page,[m
[32m+[m[32m collectNewCStr_String(""),[m
[32m+[m[32m collectNewCStr_String("text/gemini"),[m
[32m+[m[32m utf8_String(src));[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "memorysize.set")) {[m
[31m- d->prefs.maxMemorySize = arg_Command(cmd);[m
[31m- if (d->prefs.maxMemorySize <= 0) {[m
[31m- d->prefs.maxMemorySize = 0;[m
[32m+[m[32m else if (equal_Command(cmd, "font.set")) {[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m setFreezeDraw_MainWindow(get_MainWindow(), iTrue);[m
}[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "urlsize.set")) {[m
[31m- d->prefs.maxUrlSize = arg_Command(cmd);[m
[31m- if (d->prefs.maxUrlSize < 1024) {[m
[31m- d->prefs.maxUrlSize = 1024; /* Gemini protocol requirement */[m
[32m+[m[32m struct {[m
[32m+[m[32m const char *label;[m
[32m+[m[32m enum iPrefsString ps;[m
[32m+[m[32m int fontId;[m
[32m+[m[32m } params[] = {[m
[32m+[m[32m { "ui", uiFont_PrefsString, default_FontId },[m
[32m+[m[32m { "mono", monospaceFont_PrefsString, monospace_FontId },[m
[32m+[m[32m { "heading", headingFont_PrefsString, documentHeading_FontId },[m
[32m+[m[32m { "body", bodyFont_PrefsString, documentBody_FontId },[m
[32m+[m[32m { "monodoc", monospaceDocumentFont_PrefsString, documentMonospace_FontId },[m
[32m+[m[32m };[m
[32m+[m[32m iBool wasChanged = iFalse;[m
[32m+[m[32m iForIndices(i, params) {[m
[32m+[m[32m if (hasLabel_Command(cmd, params[i].label)) {[m
[32m+[m[32m iString *ps = &d->prefs.strings[params[i].ps];[m
[32m+[m[32m const iString *newFont = string_Command(cmd, params[i].label);[m
[32m+[m[32m if (!equal_String(ps, newFont)) {[m
[32m+[m[32m set_String(ps, newFont);[m
[32m+[m[32m wasChanged = iTrue;[m
[32m+[m[32m }[m
[32m+[m[32m }[m
}[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "searchurl")) {[m
[31m- iString *url = &d->prefs.strings[searchUrl_PrefsString];[m
[31m- setCStr_String(url, suffixPtr_Command(cmd, "address"));[m
[31m- if (startsWith_String(url, "//")) {[m
[31m- prependCStr_String(url, "gemini:");[m
[32m+[m[32m if (wasChanged) {[m
[32m+[m[32m if (isFinishedLaunching_App()) { /* there's a reset when launch is finished */[m
[32m+[m[32m resetFonts_Text(text_Window(get_MainWindow()));[m
[32m+[m[32m }[m
[32m+[m[32m postCommand_App("font.changed");[m
}[m
[31m- if (!isEmpty_String(url) && !startsWithCase_String(url, "gemini://")) {[m
[31m- prependCStr_String(url, "gemini://");[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m postCommand_App("window.unfreeze");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "proxy.gemini")) {[m
[31m- setCStr_String(&d->prefs.strings[geminiProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "proxy.gopher")) {[m
[31m- setCStr_String(&d->prefs.strings[gopherProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "proxy.http")) {[m
[31m- setCStr_String(&d->prefs.strings[httpProxy_PrefsString], suffixPtr_Command(cmd, "address"));[m
[31m- return iTrue;[m
[31m- }[m
[31m-#if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT)[m
[31m- else if (equal_Command(cmd, "downloads")) {[m
[31m- setCStr_String(&d->prefs.strings[downloadDir_PrefsString], suffixPtr_Command(cmd, "path"));[m
[31m- return iTrue;[m
[31m- }[m
[31m-#endif[m
[31m- else if (equal_Command(cmd, "downloads.open")) {[m
[31m- postCommandf_App("open newtab:%d url:%s",[m
[31m- argLabel_Command(cmd, "newtab"),[m
[31m- cstrCollect_String(makeFileUrl_String(downloadDir_App())));[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "ca.file")) {[m
[31m- setCStr_String(&d->prefs.strings[caFile_PrefsString], suffixPtr_Command(cmd, "path"));[m
[31m- if (!argLabel_Command(cmd, "noset")) {[m
[31m- setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]);[m
[32m+[m[32m else if (equal_Command(cmd, "zoom.set")) {[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */[m
}[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "ca.path")) {[m
[31m- setCStr_String(&d->prefs.strings[caPath_PrefsString], suffixPtr_Command(cmd, "path"));[m
[31m- if (!argLabel_Command(cmd, "noset")) {[m
[31m- setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]);[m
[32m+[m[32m if (arg_Command(cmd) != d->prefs.zoomPercent) {[m
[32m+[m[32m d->prefs.zoomPercent = arg_Command(cmd);[m
[32m+[m[32m invalidateCachedDocuments_App_();[m
[32m+[m[32m }[m
[32m+[m[32m setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f);[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m postCommand_App("font.changed");[m
[32m+[m[32m postCommand_App("window.unfreeze");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "search")) {[m
[31m- const int newTab = argLabel_Command(cmd, "newtab");[m
[31m- const iString *query = collect_String(suffix_Command(cmd, "query"));[m
[31m- if (!isLikelyUrl_String(query)) {[m
[31m- const iString *url = searchQueryUrl_App(query);[m
[31m- if (!isEmpty_String(url)) {[m
[31m- postCommandf_App("open newtab:%d url:%s", newTab, cstr_String(url));[m
[31m- }[m
[32m+[m[32m else if (equal_Command(cmd, "zoom.delta")) {[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */[m
}[m
[31m- else {[m
[31m- postCommandf_App("open newtab:%d url:%s", newTab, cstr_String(query));[m
[32m+[m[32m int delta = arg_Command(cmd);[m
[32m+[m[32m if (d->prefs.zoomPercent < 100 || (delta < 0 && d->prefs.zoomPercent == 100)) {[m
[32m+[m[32m delta /= 2;[m
[32m+[m[32m }[m
[32m+[m[32m d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200);[m
[32m+[m[32m invalidateCachedDocuments_App_();[m
[32m+[m[32m setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f);[m
[32m+[m[32m if (!isFrozen) {[m
[32m+[m[32m postCommand_App("font.changed");[m
[32m+[m[32m postCommand_App("window.unfreeze");[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "reveal")) {[m
[31m- const iString *path = NULL;[m
[31m- if (hasLabel_Command(cmd, "path")) {[m
[31m- path = suffix_Command(cmd, "path");[m
[31m- }[m
[31m- else if (hasLabel_Command(cmd, "url")) {[m
[31m- path = collect_String(localFilePathFromUrl_String(suffix_Command(cmd, "url")));[m
[31m- }[m
[31m- if (path) {[m
[31m- revealPath_App(path);[m
[32m+[m[32m else if (equal_Command(cmd, "hidetoolbarscroll")) {[m
[32m+[m[32m d->prefs.hideToolbarOnScroll = arg_Command(cmd);[m
[32m+[m[32m if (!d->prefs.hideToolbarOnScroll) {[m
[32m+[m[32m showToolbar_Root(get_Root(), iTrue);[m
}[m
return iTrue;[m
}[m
[36m@@ -3337,20 +3464,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
#endif[m
return iFalse;[m
}[m
[31m- else if (equal_Command(cmd, "window.new")) {[m
[31m- iMainWindow *newWin = new_MainWindow(initialWindowRect_App_(d, numWindows_App()));[m
[31m- addWindow_App(newWin); /* takes ownership */[m
[31m- SDL_ShowWindow(newWin->base.win);[m
[31m- setCurrent_Window(newWin);[m
[31m- if (hasLabel_Command(cmd, "url")) {[m
[31m- postCommandf_Root(newWin->base.roots[0], "~open %s", cmd + 11 /* all arguments passed on */);[m
[31m- }[m
[31m- else {[m
[31m- postCommand_Root(newWin->base.roots[0], "~navigate.home");[m
[31m- }[m
[31m- postCommand_Root(newWin->base.roots[0], "~window.unfreeze");[m
[31m- return iTrue;[m
[31m- }[m
else if (equal_Command(cmd, "tabs.new")) {[m
const iBool isDuplicate = argLabel_Command(cmd, "duplicate") != 0;[m
newTab_App(isDuplicate ? document_App() : NULL, iTrue);[m
[36m@@ -3411,12 +3524,16 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
}[m
}[m
[32m+[m[32m#if defined (iPlatformAppleDesktop)[m
[32m+[m[32m closeWindow_App(d->window);[m
[32m+[m[32m#else[m
else if (numWindows_App() > 1) {[m
closeWindow_App(d->window);[m
}[m
else {[m
postCommand_App("quit");[m
}[m
[32m+[m[32m#endif[m
return iTrue;[m
}[m
else if (equal_Command(cmd, "keyroot.next")) {[m
[36m@@ -3426,11 +3543,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "quit")) {[m
[31m- SDL_Event ev;[m
[31m- ev.type = SDL_QUIT;[m
[31m- SDL_PushEvent(&ev);[m
[31m- }[m
else if (equal_Command(cmd, "preferences")) {[m
iWidget *dlg = makePreferences_Widget();[m
updatePrefsThemeButtons_(dlg);[m
[36m@@ -3618,27 +3730,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "bookmarks.sort")) {[m
[31m- sort_Bookmarks(d->bookmarks, arg_Command(cmd), cmpTitleAscending_Bookmark);[m
[31m- postCommand_App("bookmarks.changed");[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "bookmarks.reload.remote")) {[m
[31m- fetchRemote_Bookmarks(bookmarks_App());[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "bookmarks.request.finished")) {[m
[31m- requestFinished_Bookmarks(bookmarks_App(), pointerLabel_Command(cmd, "req"));[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "bookmarks.changed")) {[m
[31m- save_Bookmarks(d->bookmarks, dataDir_App_());[m
[31m- return iFalse;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "feeds.refresh")) {[m
[31m- refresh_Feeds();[m
[31m- return iTrue;[m
[31m- }[m
else if (startsWith_CStr(cmd, "feeds.update.")) {[m
const iWidget *navBar = findChild_Widget(get_Window()->roots[0]->widget, "navbar");[m
iAnyObject *prog = findChild_Widget(navBar, "feeds.progress");[m
[36m@@ -3663,10 +3754,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
return iFalse;[m
}[m
[31m- else if (equal_Command(cmd, "visited.changed")) {[m
[31m- save_Visited(d->visited, dataDir_App_());[m
[31m- return iFalse;[m
[31m- }[m
else if (equal_Command(cmd, "document.changed")) {[m
/* Set of open tabs has changed. */[m
postCommand_App("document.openurls.changed");[m
[36m@@ -3691,29 +3778,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
postRefresh_App();[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "ident.signin")) {[m
[31m- const iString *url = collect_String(suffix_Command(cmd, "url"));[m
[31m- signIn_GmCerts([m
[31m- d->certs,[m
[31m- findIdentity_GmCerts(d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident")))),[m
[31m- url);[m
[31m- postCommand_App("navigate.reload");[m
[31m- postCommand_App("idents.changed");[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "ident.signout")) {[m
[31m- iGmIdentity *ident = findIdentity_GmCerts([m
[31m- d->certs, collect_Block(hexDecode_Rangecc(range_Command(cmd, "ident"))));[m
[31m- if (arg_Command(cmd)) {[m
[31m- clearUse_GmIdentity(ident);[m
[31m- }[m
[31m- else {[m
[31m- setUse_GmIdentity(ident, collect_String(suffix_Command(cmd, "url")), iFalse);[m
[31m- }[m
[31m- postCommand_App("navigate.reload");[m
[31m- postCommand_App("idents.changed");[m
[31m- return iTrue;[m
[31m- }[m
else if (equal_Command(cmd, "ident.switch")) {[m
/* This is different than "ident.signin" in that the currently used identity's activation[m
URL is used instead of the current one. */[m
[36m@@ -3733,33 +3797,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
return iTrue;[m
}[m
[31m- else if (equal_Command(cmd, "idents.changed")) {[m
[31m- saveIdentities_GmCerts(d->certs);[m
[31m- return iFalse;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "os.theme.changed")) {[m
[31m- const int dark = argLabel_Command(cmd, "dark");[m
[31m- d->isDarkSystemTheme = dark;[m
[31m- if (d->prefs.useSystemTheme) {[m
[31m- const int contrast = argLabel_Command(cmd, "contrast");[m
[31m- const int preferred = d->prefs.systemPreferredColorTheme[dark ^ 1];[m
[31m- postCommandf_App("theme.set arg:%d auto:1",[m
[31m- preferred >= 0 ? preferred[m
[31m- : dark ? (contrast ? pureBlack_ColorTheme : dark_ColorTheme)[m
[31m- : (contrast ? pureWhite_ColorTheme : light_ColorTheme));[m
[31m- }[m
[31m- return iFalse;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "updater.check")) {[m
[31m- checkNow_Updater();[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "fontpack.enable")) {[m
[31m- const iString *packId = collect_String(suffix_Command(cmd, "id"));[m
[31m- enablePack_Fonts(packId, arg_Command(cmd));[m
[31m- postCommand_App("navigate.reload");[m
[31m- return iTrue;[m
[31m- }[m
else if (equal_Command(cmd, "fontpack.delete")) {[m
const iString *packId = collect_String(suffix_Command(cmd, "id"));[m
if (isEmpty_String(packId)) {[m
[36m@@ -3840,35 +3877,6 @@[m [miBool handleCommand_App(const char *cmd) {[m
}[m
return iTrue;[m
}[m
[31m-#if defined (LAGRANGE_ENABLE_IPC)[m
[31m- else if (equal_Command(cmd, "ipc.list.urls")) {[m
[31m- iProcessId pid = argLabel_Command(cmd, "pid");[m
[31m- if (pid) {[m
[31m- iString *urls = collectNew_String();[m
[31m- iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) {[m
[31m- append_String(urls, url_DocumentWidget(i.object));[m
[31m- appendCStr_String(urls, "\n");[m
[31m- }[m
[31m- write_Ipc(pid, urls, response_IpcWrite);[m
[31m- }[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "ipc.active.url")) {[m
[31m- write_Ipc(argLabel_Command(cmd, "pid"),[m
[31m- collectNewFormat_String("%s\n", cstr_String(url_DocumentWidget(document_App()))),[m
[31m- response_IpcWrite);[m
[31m- return iTrue;[m
[31m- }[m
[31m- else if (equal_Command(cmd, "ipc.signal")) {[m
[31m- if (argLabel_Command(cmd, "raise")) {[m
[31m- if (d->window && d->window->base.win) {[m
[31m- SDL_RaiseWindow(d->window->base.win);[m
[31m- }[m
[31m- }[m
[31m- signal_Ipc(arg_Command(cmd));[m
[31m- return iTrue;[m
[31m- }[m
[31m-#endif /* defined (LAGRANGE_ENABLE_IPC) */[m
else {[m
return iFalse;[m
}[m
[1mdiff --git a/src/ui/keys.c b/src/ui/keys.c[m
[1mindex 3428bcc8..40859f7c 100644[m
[1m--- a/src/ui/keys.c[m
[1m+++ b/src/ui/keys.c[m
[36m@@ -451,7 +451,7 @@[m [mvoid setLabel_Keys(int id, const char *label) {[m
[m
iBool processEvent_Keys(const SDL_Event *ev) {[m
iKeys *d = &keys_;[m
[31m- iRoot *root = get_Window()->keyRoot;[m
[32m+[m[32m iRoot *root = get_Window() ? get_Window()->keyRoot : NULL;[m
if (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) {[m
const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));[m
if (bind) {[m
[1mdiff --git a/src/ui/widget.c b/src/ui/widget.c[m
[1mindex cb373c43..138b219e 100644[m
[1m--- a/src/ui/widget.c[m
[1m+++ b/src/ui/widget.c[m
[36m@@ -2154,6 +2154,9 @@[m [mstatic const iWidget *findFocusRoot_Widget_(const iWidget *d) {[m
}[m
[m
iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir) {[m
[32m+[m[32m if (!get_Window()) {[m
[32m+[m[32m return NULL;[m
[32m+[m[32m }[m
iRoot *uiRoot = (startFrom ? startFrom->root : get_Window()->keyRoot);[m
const iWidget *focusRoot = findFocusRoot_Widget_(uiRoot->widget);[m
iAssert(focusRoot != NULL);[m
[1mdiff --git a/src/ui/window.c b/src/ui/window.c[m
[1mindex cbfd0f5c..2ec64f0e 100644[m
[1m--- a/src/ui/window.c[m
[1m+++ b/src/ui/window.c[m
[36m@@ -186,22 +186,32 @@[m [mconst iMenuItem topLevelMenus_Window[6] = {[m
[m
#if defined (LAGRANGE_MAC_MENUBAR)[m
[m
[32m+[m[32mstatic iBool macMenusInserted_;[m
[32m+[m
static void insertMacMenus_(void) {[m
[32m+[m[32m if (macMenusInserted_) {[m
[32m+[m[32m return;[m
[32m+[m[32m }[m
insertMenuItems_MacOS("${menu.title.file}", 1, fileMenuItems_, iElemCount(fileMenuItems_));[m
insertMenuItems_MacOS("${menu.title.edit}", 2, editMenuItems_, iElemCount(editMenuItems_));[m
insertMenuItems_MacOS("${menu.title.view}", 3, viewMenuItems_, iElemCount(viewMenuItems_));[m
insertMenuItems_MacOS("${menu.title.bookmarks}", 4, bookmarksMenuItems_, iElemCount(bookmarksMenuItems_));[m
insertMenuItems_MacOS("${menu.title.identity}", 5, identityMenuItems_, iElemCount(identityMenuItems_));[m
insertMenuItems_MacOS("${menu.title.help}", 7, helpMenuItems_, iElemCount(helpMenuItems_));[m
[32m+[m[32m macMenusInserted_ = iTrue;[m
}[m
[m
static void removeMacMenus_(void) {[m
[32m+[m[32m if (!macMenusInserted_) {[m
[32m+[m[32m return;[m
[32m+[m[32m }[m
removeMenu_MacOS(7);[m
removeMenu_MacOS(5);[m
removeMenu_MacOS(4);[m
removeMenu_MacOS(3);[m
removeMenu_MacOS(2);[m
removeMenu_MacOS(1);[m
[32m+[m[32m macMenusInserted_ = iFalse;[m
}[m
[m
#endif /* LAGRANGE_MAC_MENUBAR */[m
[36m@@ -246,9 +256,7 @@[m [mstatic void windowSizeChanged_MainWindow_(iMainWindow *d) {[m
[m
static void setupUserInterface_MainWindow(iMainWindow *d) {[m
#if defined (LAGRANGE_MAC_MENUBAR)[m
[31m- if (numWindows_App() == 0) {[m
[31m- insertMacMenus_(); /* TODO: Shouldn't this be in the App? */[m
[31m- }[m
[32m+[m[32m insertMacMenus_(); /* TODO: Shouldn't this be in the App? */[m
#endif[m
/* One root is created by default. */[m
d->base.roots[0] = new_Root();[m
[36m@@ -1652,6 +1660,9 @@[m [mvoid setKeyboardHeight_MainWindow(iMainWindow *d, int height) {[m
[m
iObjectList *listDocuments_MainWindow(iMainWindow *d, const iRoot *rootOrNull) {[m
iObjectList *docs = new_ObjectList();[m
[32m+[m[32m if (!d) {[m
[32m+[m[32m return docs;[m
[32m+[m[32m }[m
iForIndices(i, d->base.roots) {[m
iRoot *root = d->base.roots[i];[m
if (!root) continue;[m
text/plain
This content has been proxied by September (ba2dc).