summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/app.c78
-rw-r--r--src/ui/inputwidget.c1
-rw-r--r--src/ui/util.c3
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)
31option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF) 31option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF)
32option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF) 32option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF)
33option (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON) 33option (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON)
34option (ENABLE_DOWNLOAD_EDIT "Allow changing the Downloads directory" ON)
34 35
35include (BuildType.cmake) 36include (BuildType.cmake)
36include (res/Embed.cmake) 37include (res/Embed.cmake)
@@ -226,6 +227,9 @@ endif ()
226if (ENABLE_IDLE_SLEEP) 227if (ENABLE_IDLE_SLEEP)
227 target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1) 228 target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1)
228endif () 229endif ()
230if (ENABLE_DOWNLOAD_EDIT)
231 target_compile_definitions (app PUBLIC LAGRANGE_DOWNLOAD_EDIT=1)
232endif ()
229target_link_libraries (app PUBLIC the_Foundation::the_Foundation) 233target_link_libraries (app PUBLIC the_Foundation::the_Foundation)
230target_link_libraries (app PUBLIC ${SDL2_LDFLAGS}) 234target_link_libraries (app PUBLIC ${SDL2_LDFLAGS})
231if (APPLE) 235if (APPLE)
diff --git a/src/app.c b/src/app.c
index 3fc1da34..d8508f70 100644
--- a/src/app.c
+++ b/src/app.c
@@ -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"
86static const char *dataDir_App_ = "~/.config/lagrange"; 86static 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 */
93static const char *prefsFileName_App_ = "prefs.cfg"; 93static const char *prefsFileName_App_ = "prefs.cfg";
94static const char *oldStateFileName_App_ = "state.binary"; 94static const char *oldStateFileName_App_ = "state.binary";
95static const char *stateFileName_App_ = "state.lgr"; 95static const char *stateFileName_App_ = "state.lgr";
96static const char *downloadDir_App_ = "~/Downloads"; 96static const char *defaultDownloadDir_App_ = "~/Downloads";
97 97
98static const int idleThreshold_App_ = 1000; /* ms */ 98static 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
216static 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
226static 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
216static const iString *prefsFileName_(void) { 244static 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
220static void loadPrefs_App_(iApp *d) { 248static 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
268static iBool loadState_App_(iApp *d) { 296static 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) {
323static void saveState_App_(const iApp *d) { 351static 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
351static void init_App_(iApp *d, int argc, char **argv) { 379static 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) {
470static void deinit_App(iApp *d) { 498static 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
497const iString *dataDir_App(void) { 525const iString *dataDir_App(void) {
498 return collect_String(cleanedCStr_Path(dataDir_App_)); 526 return collect_String(cleanedCStr_Path(dataDir_App_()));
499} 527}
500 528
501const iString *downloadDir_App(void) { 529const 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
225void setText_InputWidget(iInputWidget *d, const iString *text) { 225void 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
1025static void expandInputFieldWidth_(iInputWidget *input) { 1025static 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:")));