diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/app.c | 78 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 1 | ||||
-rw-r--r-- | src/ui/util.c | 3 |
4 files changed, 62 insertions, 24 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 100794d8..ce07c2de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -31,6 +31,7 @@ option (ENABLE_KERNING "Enable kerning in font renderer (slower)" ON) | |||
31 | option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF) | 31 | option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF) |
32 | option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF) | 32 | option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF) |
33 | option (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON) | 33 | option (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON) |
34 | option (ENABLE_DOWNLOAD_EDIT "Allow changing the Downloads directory" ON) | ||
34 | 35 | ||
35 | include (BuildType.cmake) | 36 | include (BuildType.cmake) |
36 | include (res/Embed.cmake) | 37 | include (res/Embed.cmake) |
@@ -226,6 +227,9 @@ endif () | |||
226 | if (ENABLE_IDLE_SLEEP) | 227 | if (ENABLE_IDLE_SLEEP) |
227 | target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1) | 228 | target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1) |
228 | endif () | 229 | endif () |
230 | if (ENABLE_DOWNLOAD_EDIT) | ||
231 | target_compile_definitions (app PUBLIC LAGRANGE_DOWNLOAD_EDIT=1) | ||
232 | endif () | ||
229 | target_link_libraries (app PUBLIC the_Foundation::the_Foundation) | 233 | target_link_libraries (app PUBLIC the_Foundation::the_Foundation) |
230 | target_link_libraries (app PUBLIC ${SDL2_LDFLAGS}) | 234 | target_link_libraries (app PUBLIC ${SDL2_LDFLAGS}) |
231 | if (APPLE) | 235 | if (APPLE) |
@@ -83,17 +83,17 @@ static const char *dataDir_App_ = "~/AppData/Roaming/fi.skyjake.Lagrange"; | |||
83 | #endif | 83 | #endif |
84 | #if defined (iPlatformLinux) || defined (iPlatformOther) | 84 | #if defined (iPlatformLinux) || defined (iPlatformOther) |
85 | #define EMB_BIN "../../share/lagrange/resources.lgr" | 85 | #define EMB_BIN "../../share/lagrange/resources.lgr" |
86 | static const char *dataDir_App_ = "~/.config/lagrange"; | 86 | static const char *defaultDataDir_App_ = "~/.config/lagrange"; |
87 | #endif | 87 | #endif |
88 | #if defined (LAGRANGE_EMB_BIN) /* specified in build config */ | 88 | #if defined (LAGRANGE_EMB_BIN) /* specified in build config */ |
89 | # undef EMB_BIN | 89 | # undef EMB_BIN |
90 | # define EMB_BIN LAGRANGE_EMB_BIN | 90 | # define EMB_BIN LAGRANGE_EMB_BIN |
91 | #endif | 91 | #endif |
92 | #define EMB_BIN2 "../resources.lgr" /* fallback from build/executable dir */ | 92 | #define EMB_BIN2 "../resources.lgr" /* fallback from build/executable dir */ |
93 | static const char *prefsFileName_App_ = "prefs.cfg"; | 93 | static const char *prefsFileName_App_ = "prefs.cfg"; |
94 | static const char *oldStateFileName_App_ = "state.binary"; | 94 | static const char *oldStateFileName_App_ = "state.binary"; |
95 | static const char *stateFileName_App_ = "state.lgr"; | 95 | static const char *stateFileName_App_ = "state.lgr"; |
96 | static const char *downloadDir_App_ = "~/Downloads"; | 96 | static const char *defaultDownloadDir_App_ = "~/Downloads"; |
97 | 97 | ||
98 | static const int idleThreshold_App_ = 1000; /* ms */ | 98 | static const int idleThreshold_App_ = 1000; /* ms */ |
99 | 99 | ||
@@ -213,14 +213,42 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
213 | return str; | 213 | return str; |
214 | } | 214 | } |
215 | 215 | ||
216 | static const char *dataDir_App_(void) { | ||
217 | #if defined (iPlatformLinux) || defined (iPlatformOther) | ||
218 | const char *configHome = getenv("XDG_CONFIG_HOME"); | ||
219 | if (configHome) { | ||
220 | return concatPath_CStr(configHome, "lagrange"); | ||
221 | } | ||
222 | #endif | ||
223 | return defaultDataDir_App_; | ||
224 | } | ||
225 | |||
226 | static const char *downloadDir_App_(void) { | ||
227 | #if defined (iPlatformLinux) || defined (iPlatformOther) | ||
228 | /* Parse user-dirs.dirs using the `xdg-user-dir` tool. */ | ||
229 | iProcess *proc = iClob(new_Process()); | ||
230 | setArguments_Process( | ||
231 | proc, iClob(newStringsCStr_StringList("/usr/bin/env", "xdg-user-dir", "DOWNLOAD", NULL))); | ||
232 | if (start_Process(proc)) { | ||
233 | iString *path = collect_String(newLocal_String(collect_Block( | ||
234 | readOutputUntilClosed_Process(proc)))); | ||
235 | trim_String(path); | ||
236 | if (!isEmpty_String(path)) { | ||
237 | return cstr_String(path); | ||
238 | } | ||
239 | } | ||
240 | #endif | ||
241 | return defaultDownloadDir_App_; | ||
242 | } | ||
243 | |||
216 | static const iString *prefsFileName_(void) { | 244 | static const iString *prefsFileName_(void) { |
217 | return collect_String(concatCStr_Path(&iStringLiteral(dataDir_App_), prefsFileName_App_)); | 245 | return collectNewCStr_String(concatPath_CStr(dataDir_App_(), prefsFileName_App_)); |
218 | } | 246 | } |
219 | 247 | ||
220 | static void loadPrefs_App_(iApp *d) { | 248 | static void loadPrefs_App_(iApp *d) { |
221 | iUnused(d); | 249 | iUnused(d); |
222 | /* Create the data dir if it doesn't exist yet. */ | 250 | /* Create the data dir if it doesn't exist yet. */ |
223 | makeDirs_Path(collectNewCStr_String(dataDir_App_)); | 251 | makeDirs_Path(collectNewCStr_String(dataDir_App_())); |
224 | iFile *f = new_File(prefsFileName_()); | 252 | iFile *f = new_File(prefsFileName_()); |
225 | if (open_File(f, readOnly_FileMode | text_FileMode)) { | 253 | if (open_File(f, readOnly_FileMode | text_FileMode)) { |
226 | iString *str = readString_File(f); | 254 | iString *str = readString_File(f); |
@@ -267,8 +295,8 @@ static const char *magicTabDocument_App_ = "tabd"; | |||
267 | 295 | ||
268 | static iBool loadState_App_(iApp *d) { | 296 | static iBool loadState_App_(iApp *d) { |
269 | iUnused(d); | 297 | iUnused(d); |
270 | const char *oldPath = concatPath_CStr(dataDir_App_, oldStateFileName_App_); | 298 | const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); |
271 | const char *path = concatPath_CStr(dataDir_App_, stateFileName_App_); | 299 | const char *path = concatPath_CStr(dataDir_App_(), stateFileName_App_); |
272 | iFile *f = iClob(newCStr_File(fileExistsCStr_FileInfo(path) ? path : oldPath)); | 300 | iFile *f = iClob(newCStr_File(fileExistsCStr_FileInfo(path) ? path : oldPath)); |
273 | if (open_File(f, readOnly_FileMode)) { | 301 | if (open_File(f, readOnly_FileMode)) { |
274 | char magic[4]; | 302 | char magic[4]; |
@@ -323,7 +351,7 @@ iObjectList *listDocuments_App(void) { | |||
323 | static void saveState_App_(const iApp *d) { | 351 | static void saveState_App_(const iApp *d) { |
324 | iUnused(d); | 352 | iUnused(d); |
325 | trimCache_App(); | 353 | trimCache_App(); |
326 | iFile *f = newCStr_File(concatPath_CStr(dataDir_App_, stateFileName_App_)); | 354 | iFile *f = newCStr_File(concatPath_CStr(dataDir_App_(), stateFileName_App_)); |
327 | if (open_File(f, writeOnly_FileMode)) { | 355 | if (open_File(f, writeOnly_FileMode)) { |
328 | writeData_File(f, magicState_App_, 4); | 356 | writeData_File(f, magicState_App_, 4); |
329 | writeU32_File(f, latest_FileVersion); /* version */ | 357 | writeU32_File(f, latest_FileVersion); /* version */ |
@@ -349,7 +377,7 @@ static uint32_t checkAsleep_App_(uint32_t interval, void *param) { | |||
349 | #endif | 377 | #endif |
350 | 378 | ||
351 | static void init_App_(iApp *d, int argc, char **argv) { | 379 | static void init_App_(iApp *d, int argc, char **argv) { |
352 | const iBool isFirstRun = !fileExistsCStr_FileInfo(cleanedPath_CStr(dataDir_App_)); | 380 | const iBool isFirstRun = !fileExistsCStr_FileInfo(cleanedPath_CStr(dataDir_App_())); |
353 | d->isFinishedLaunching = iFalse; | 381 | d->isFinishedLaunching = iFalse; |
354 | d->launchCommands = new_StringList(); | 382 | d->launchCommands = new_StringList(); |
355 | iZap(d->lastDropTime); | 383 | iZap(d->lastDropTime); |
@@ -386,12 +414,12 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
386 | } | 414 | } |
387 | #endif | 415 | #endif |
388 | init_Prefs(&d->prefs); | 416 | init_Prefs(&d->prefs); |
389 | setCStr_String(&d->prefs.downloadDir, downloadDir_App_); | 417 | setCStr_String(&d->prefs.downloadDir, downloadDir_App_()); |
390 | d->isRunning = iFalse; | 418 | d->isRunning = iFalse; |
391 | d->window = NULL; | 419 | d->window = NULL; |
392 | set_Atomic(&d->pendingRefresh, iFalse); | 420 | set_Atomic(&d->pendingRefresh, iFalse); |
393 | d->mimehooks = new_MimeHooks(); | 421 | d->mimehooks = new_MimeHooks(); |
394 | d->certs = new_GmCerts(dataDir_App_); | 422 | d->certs = new_GmCerts(dataDir_App_()); |
395 | d->visited = new_Visited(); | 423 | d->visited = new_Visited(); |
396 | d->bookmarks = new_Bookmarks(); | 424 | d->bookmarks = new_Bookmarks(); |
397 | d->tabEnum = 0; /* generates unique IDs for tab pages */ | 425 | d->tabEnum = 0; /* generates unique IDs for tab pages */ |
@@ -406,10 +434,10 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
406 | #endif | 434 | #endif |
407 | init_Keys(); | 435 | init_Keys(); |
408 | loadPrefs_App_(d); | 436 | loadPrefs_App_(d); |
409 | load_Keys(dataDir_App_); | 437 | load_Keys(dataDir_App_()); |
410 | load_Visited(d->visited, dataDir_App_); | 438 | load_Visited(d->visited, dataDir_App_()); |
411 | load_Bookmarks(d->bookmarks, dataDir_App_); | 439 | load_Bookmarks(d->bookmarks, dataDir_App_()); |
412 | load_MimeHooks(d->mimehooks, dataDir_App_); | 440 | load_MimeHooks(d->mimehooks, dataDir_App_()); |
413 | if (isFirstRun) { | 441 | if (isFirstRun) { |
414 | /* Create the default bookmarks for a quick start. */ | 442 | /* Create the default bookmarks for a quick start. */ |
415 | add_Bookmarks(d->bookmarks, | 443 | add_Bookmarks(d->bookmarks, |
@@ -435,7 +463,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
435 | } | 463 | } |
436 | #endif | 464 | #endif |
437 | d->window = new_Window(d->initialWindowRect); | 465 | d->window = new_Window(d->initialWindowRect); |
438 | init_Feeds(dataDir_App_); | 466 | init_Feeds(dataDir_App_()); |
439 | /* Widget state init. */ | 467 | /* Widget state init. */ |
440 | processEvents_App(postedEventsOnly_AppEventMode); | 468 | processEvents_App(postedEventsOnly_AppEventMode); |
441 | if (!loadState_App_(d)) { | 469 | if (!loadState_App_(d)) { |
@@ -470,13 +498,13 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
470 | static void deinit_App(iApp *d) { | 498 | static void deinit_App(iApp *d) { |
471 | saveState_App_(d); | 499 | saveState_App_(d); |
472 | deinit_Feeds(); | 500 | deinit_Feeds(); |
473 | save_Keys(dataDir_App_); | 501 | save_Keys(dataDir_App_()); |
474 | deinit_Keys(); | 502 | deinit_Keys(); |
475 | savePrefs_App_(d); | 503 | savePrefs_App_(d); |
476 | deinit_Prefs(&d->prefs); | 504 | deinit_Prefs(&d->prefs); |
477 | save_Bookmarks(d->bookmarks, dataDir_App_); | 505 | save_Bookmarks(d->bookmarks, dataDir_App_()); |
478 | delete_Bookmarks(d->bookmarks); | 506 | delete_Bookmarks(d->bookmarks); |
479 | save_Visited(d->visited, dataDir_App_); | 507 | save_Visited(d->visited, dataDir_App_()); |
480 | delete_Visited(d->visited); | 508 | delete_Visited(d->visited); |
481 | delete_GmCerts(d->certs); | 509 | delete_GmCerts(d->certs); |
482 | save_MimeHooks(d->mimehooks); | 510 | save_MimeHooks(d->mimehooks); |
@@ -495,7 +523,7 @@ const iString *execPath_App(void) { | |||
495 | } | 523 | } |
496 | 524 | ||
497 | const iString *dataDir_App(void) { | 525 | const iString *dataDir_App(void) { |
498 | return collect_String(cleanedCStr_Path(dataDir_App_)); | 526 | return collect_String(cleanedCStr_Path(dataDir_App_())); |
499 | } | 527 | } |
500 | 528 | ||
501 | const iString *downloadDir_App(void) { | 529 | const iString *downloadDir_App(void) { |
@@ -855,8 +883,10 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
855 | if (equal_Command(cmd, "prefs.dismiss") || equal_Command(cmd, "preferences")) { | 883 | if (equal_Command(cmd, "prefs.dismiss") || equal_Command(cmd, "preferences")) { |
856 | setUiScale_Window(get_Window(), | 884 | setUiScale_Window(get_Window(), |
857 | toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale")))); | 885 | toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale")))); |
886 | #if defined (LAGRANGE_DOWNLOAD_EDIT) | ||
858 | postCommandf_App("downloads path:%s", | 887 | postCommandf_App("downloads path:%s", |
859 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.downloads")))); | 888 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.downloads")))); |
889 | #endif | ||
860 | postCommandf_App("window.retain arg:%d", | 890 | postCommandf_App("window.retain arg:%d", |
861 | isSelected_Widget(findChild_Widget(d, "prefs.retainwindow"))); | 891 | isSelected_Widget(findChild_Widget(d, "prefs.retainwindow"))); |
862 | postCommandf_App("smoothscroll arg:%d", | 892 | postCommandf_App("smoothscroll arg:%d", |
@@ -1457,7 +1487,7 @@ iBool handleCommand_App(const char *cmd) { | |||
1457 | return iTrue; | 1487 | return iTrue; |
1458 | } | 1488 | } |
1459 | else if (equal_Command(cmd, "bookmarks.changed")) { | 1489 | else if (equal_Command(cmd, "bookmarks.changed")) { |
1460 | save_Bookmarks(d->bookmarks, dataDir_App_); | 1490 | save_Bookmarks(d->bookmarks, dataDir_App_()); |
1461 | return iFalse; | 1491 | return iFalse; |
1462 | } | 1492 | } |
1463 | else if (equal_Command(cmd, "feeds.refresh")) { | 1493 | else if (equal_Command(cmd, "feeds.refresh")) { |
@@ -1476,7 +1506,7 @@ iBool handleCommand_App(const char *cmd) { | |||
1476 | return iFalse; | 1506 | return iFalse; |
1477 | } | 1507 | } |
1478 | else if (equal_Command(cmd, "visited.changed")) { | 1508 | else if (equal_Command(cmd, "visited.changed")) { |
1479 | save_Visited(d->visited, dataDir_App_); | 1509 | save_Visited(d->visited, dataDir_App_()); |
1480 | return iFalse; | 1510 | return iFalse; |
1481 | } | 1511 | } |
1482 | else if (equal_Command(cmd, "ident.new")) { | 1512 | else if (equal_Command(cmd, "ident.new")) { |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 3f799e3c..1674040b 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -223,6 +223,7 @@ static void updateBuffered_InputWidget_(iInputWidget *d) { | |||
223 | } | 223 | } |
224 | 224 | ||
225 | void setText_InputWidget(iInputWidget *d, const iString *text) { | 225 | void setText_InputWidget(iInputWidget *d, const iString *text) { |
226 | if (!d) return; | ||
226 | if (d->inFlags & isUrl_InputWidgetFlag) { | 227 | if (d->inFlags & isUrl_InputWidgetFlag) { |
227 | /* If user wants URLs encoded, also Punycode the domain. */ | 228 | /* If user wants URLs encoded, also Punycode the domain. */ |
228 | if (!prefs_App()->decodeUserVisibleURLs) { | 229 | if (!prefs_App()->decodeUserVisibleURLs) { |
diff --git a/src/ui/util.c b/src/ui/util.c index 4d5ed916..d64a93b6 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1023,6 +1023,7 @@ static void makeTwoColumnHeading_(const char *title, iWidget *headings, iWidget | |||
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | static void expandInputFieldWidth_(iInputWidget *input) { | 1025 | static void expandInputFieldWidth_(iInputWidget *input) { |
1026 | if (!input) return; | ||
1026 | iWidget *page = as_Widget(input)->parent->parent->parent->parent; /* tabs > page > values > input */ | 1027 | iWidget *page = as_Widget(input)->parent->parent->parent->parent; /* tabs > page > values > input */ |
1027 | as_Widget(input)->rect.size.x = | 1028 | as_Widget(input)->rect.size.x = |
1028 | right_Rect(bounds_Widget(page)) - left_Rect(bounds_Widget(constAs_Widget(input))); | 1029 | right_Rect(bounds_Widget(page)) - left_Rect(bounds_Widget(constAs_Widget(input))); |
@@ -1056,8 +1057,10 @@ iWidget *makePreferences_Widget(void) { | |||
1056 | iWidget *headings, *values; | 1057 | iWidget *headings, *values; |
1057 | /* General preferences. */ { | 1058 | /* General preferences. */ { |
1058 | appendTwoColumnPage_(tabs, "General", '1', &headings, &values); | 1059 | appendTwoColumnPage_(tabs, "General", '1', &headings, &values); |
1060 | #if defined (LAGRANGE_DOWNLOAD_EDIT) | ||
1059 | addChild_Widget(headings, iClob(makeHeading_Widget("Downloads folder:"))); | 1061 | addChild_Widget(headings, iClob(makeHeading_Widget("Downloads folder:"))); |
1060 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(0))), "prefs.downloads"); | 1062 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(0))), "prefs.downloads"); |
1063 | #endif | ||
1061 | addChild_Widget(headings, iClob(makeHeading_Widget("Show URL on hover:"))); | 1064 | addChild_Widget(headings, iClob(makeHeading_Widget("Show URL on hover:"))); |
1062 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); | 1065 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.hoverlink"))); |
1063 | addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:"))); | 1066 | addChild_Widget(headings, iClob(makeHeading_Widget("Smooth scrolling:"))); |