summaryrefslogtreecommitdiff
path: root/src/app.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/app.c')
-rw-r--r--src/app.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/src/app.c b/src/app.c
index 9ef49f4f..39f399d1 100644
--- a/src/app.c
+++ b/src/app.c
@@ -168,6 +168,7 @@ const iString *dateStr_(const iDate *date) {
168 168
169static iString *serializePrefs_App_(const iApp *d) { 169static iString *serializePrefs_App_(const iApp *d) {
170 iString *str = new_String(); 170 iString *str = new_String();
171 setCurrent_Root(d->window->roots[0]); /* TODO: How about the other? */
171 const iSidebarWidget *sidebar = findWidget_App("sidebar"); 172 const iSidebarWidget *sidebar = findWidget_App("sidebar");
172 const iSidebarWidget *sidebar2 = findWidget_App("sidebar2"); 173 const iSidebarWidget *sidebar2 = findWidget_App("sidebar2");
173#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 174#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
@@ -374,6 +375,11 @@ static void savePrefs_App_(const iApp *d) {
374static const char *magicState_App_ = "lgL1"; 375static const char *magicState_App_ = "lgL1";
375static const char *magicTabDocument_App_ = "tabd"; 376static const char *magicTabDocument_App_ = "tabd";
376 377
378enum iDocumentStateFlag {
379 current_DocumentStateFlag = iBit(1),
380 rootIndex1_DocumentStateFlag = iBit(2)
381};
382
377static iBool loadState_App_(iApp *d) { 383static iBool loadState_App_(iApp *d) {
378 iUnused(d); 384 iUnused(d);
379 const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); 385 const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_);
@@ -392,17 +398,18 @@ static iBool loadState_App_(iApp *d) {
392 printf("%s: unsupported version\n", cstr_String(path_File(f))); 398 printf("%s: unsupported version\n", cstr_String(path_File(f)));
393 return iFalse; 399 return iFalse;
394 } 400 }
395 setCurrent_Root(&d->window->root);
396 setVersion_Stream(stream_File(f), version); 401 setVersion_Stream(stream_File(f), version);
397 iDocumentWidget *doc = document_App(); 402 iDocumentWidget *doc = document_App(); /* first one is always from root 0 */
398 iDocumentWidget *current = NULL; 403 iDocumentWidget *current = NULL;
399 while (!atEnd_File(f)) { 404 while (!atEnd_File(f)) {
400 readData_File(f, 4, magic); 405 readData_File(f, 4, magic);
401 if (!memcmp(magic, magicTabDocument_App_, 4)) { 406 if (!memcmp(magic, magicTabDocument_App_, 4)) {
407 const int8_t flags = read8_File(f);
402 if (!doc) { 408 if (!doc) {
409 setCurrent_Root(d->window->roots[flags & rootIndex1_DocumentStateFlag ? 1 : 0]);
403 doc = newTab_App(NULL, iFalse /* no switching */); 410 doc = newTab_App(NULL, iFalse /* no switching */);
404 } 411 }
405 if (read8_File(f)) { 412 if (flags & current_DocumentStateFlag) {
406 current = doc; 413 current = doc;
407 } 414 }
408 deserializeState_DocumentWidget(doc, stream_File(f)); 415 deserializeState_DocumentWidget(doc, stream_File(f));
@@ -421,17 +428,6 @@ static iBool loadState_App_(iApp *d) {
421 return iFalse; 428 return iFalse;
422} 429}
423 430
424iObjectList *listDocuments_App(void) {
425 iObjectList *docs = new_ObjectList();
426 const iWidget *tabs = findWidget_App("doctabs");
427 iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) {
428 if (isInstance_Object(i.object, &Class_DocumentWidget)) {
429 pushBack_ObjectList(docs, i.object);
430 }
431 }
432 return docs;
433}
434
435static void saveState_App_(const iApp *d) { 431static void saveState_App_(const iApp *d) {
436 iUnused(d); 432 iUnused(d);
437 trimCache_App(); 433 trimCache_App();
@@ -439,14 +435,17 @@ static void saveState_App_(const iApp *d) {
439 if (open_File(f, writeOnly_FileMode)) { 435 if (open_File(f, writeOnly_FileMode)) {
440 writeData_File(f, magicState_App_, 4); 436 writeData_File(f, magicState_App_, 4);
441 writeU32_File(f, latest_FileVersion); /* version */ 437 writeU32_File(f, latest_FileVersion); /* version */
442 setCurrent_Root(&d->window->root); 438 iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) {
443 iConstForEach(ObjectList, i, iClob(listDocuments_App())) {
444 iAssert(isInstance_Object(i.object, &Class_DocumentWidget)); 439 iAssert(isInstance_Object(i.object, &Class_DocumentWidget));
440 const iWidget *widget = constAs_Widget(i.object);
445 writeData_File(f, magicTabDocument_App_, 4); 441 writeData_File(f, magicTabDocument_App_, 4);
446 write8_File(f, document_App() == i.object ? 1 : 0); 442 int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0);
443 if (widget->root == d->window->roots[1]) {
444 flags |= rootIndex1_DocumentStateFlag;
445 }
446 write8_File(f, flags);
447 serializeState_DocumentWidget(i.object, stream_File(f)); 447 serializeState_DocumentWidget(i.object, stream_File(f));
448 } 448 }
449 setCurrent_Root(NULL);
450 } 449 }
451 else { 450 else {
452 fprintf(stderr, "[App] failed to save state: %s\n", strerror(errno)); 451 fprintf(stderr, "[App] failed to save state: %s\n", strerror(errno));
@@ -823,7 +822,7 @@ const iString *debugInfo_App(void) {
823 iString *msg = collectNew_String(); 822 iString *msg = collectNew_String();
824 format_String(msg, "# Debug information\n"); 823 format_String(msg, "# Debug information\n");
825 appendFormat_String(msg, "## Documents\n"); 824 appendFormat_String(msg, "## Documents\n");
826 iForEach(ObjectList, k, iClob(listDocuments_App())) { 825 iForEach(ObjectList, k, iClob(listDocuments_App(NULL))) {
827 iDocumentWidget *doc = k.object; 826 iDocumentWidget *doc = k.object;
828 appendFormat_String(msg, "### Tab %zu: %s\n", 827 appendFormat_String(msg, "### Tab %zu: %s\n",
829 childIndex_Widget(constAs_Widget(doc)->parent, k.object), 828 childIndex_Widget(constAs_Widget(doc)->parent, k.object),
@@ -849,7 +848,7 @@ const iString *debugInfo_App(void) {
849} 848}
850 849
851static void clearCache_App_(void) { 850static void clearCache_App_(void) {
852 iForEach(ObjectList, i, iClob(listDocuments_App())) { 851 iForEach(ObjectList, i, iClob(listDocuments_App(NULL))) {
853 clearCache_History(history_DocumentWidget(i.object)); 852 clearCache_History(history_DocumentWidget(i.object));
854 } 853 }
855} 854}
@@ -858,7 +857,7 @@ void trimCache_App(void) {
858 iApp *d = &app_; 857 iApp *d = &app_;
859 size_t cacheSize = 0; 858 size_t cacheSize = 0;
860 const size_t limit = d->prefs.maxCacheSize * 1000000; 859 const size_t limit = d->prefs.maxCacheSize * 1000000;
861 iObjectList *docs = listDocuments_App(); 860 iObjectList *docs = listDocuments_App(NULL);
862 iForEach(ObjectList, i, docs) { 861 iForEach(ObjectList, i, docs) {
863 cacheSize += cacheSize_History(history_DocumentWidget(i.object)); 862 cacheSize += cacheSize_History(history_DocumentWidget(i.object));
864 } 863 }
@@ -1051,7 +1050,12 @@ void processEvents_App(enum iAppEventMode eventMode) {
1051 handleCommand_MacOS(command_UserEvent(&ev)); 1050 handleCommand_MacOS(command_UserEvent(&ev));
1052#endif 1051#endif
1053 if (isMetricsChange_UserEvent(&ev)) { 1052 if (isMetricsChange_UserEvent(&ev)) {
1054 arrange_Widget(d->window->root.widget); 1053 iForIndices(i, d->window->roots) {
1054 iRoot *root = d->window->roots[i];
1055 if (root) {
1056 arrange_Widget(root->widget);
1057 }
1058 }
1055 } 1059 }
1056 if (!wasUsed) { 1060 if (!wasUsed) {
1057 /* No widget handled the command, so we'll do it. */ 1061 /* No widget handled the command, so we'll do it. */
@@ -1087,10 +1091,10 @@ static void runTickers_App_(iApp *d) {
1087 iSortedArray *pending = copy_SortedArray(&d->tickers); 1091 iSortedArray *pending = copy_SortedArray(&d->tickers);
1088 clear_SortedArray(&d->tickers); 1092 clear_SortedArray(&d->tickers);
1089 postRefresh_App(); 1093 postRefresh_App();
1090 setCurrent_Root(&d->window->root); /* TODO: Each ticker has its own root. */
1091 iConstForEach(Array, i, &pending->values) { 1094 iConstForEach(Array, i, &pending->values) {
1092 const iTicker *ticker = i.value; 1095 const iTicker *ticker = i.value;
1093 if (ticker->callback) { 1096 if (ticker->callback) {
1097 setCurrent_Root(findRoot_Window(d->window, ticker->context));
1094 ticker->callback(ticker->context); 1098 ticker->callback(ticker->context);
1095 } 1099 }
1096 } 1100 }
@@ -1120,7 +1124,11 @@ static int resizeWatcher_(void *user, SDL_Event *event) {
1120} 1124}
1121 1125
1122static int run_App_(iApp *d) { 1126static int run_App_(iApp *d) {
1123 arrange_Widget(findWidget_App("root")); 1127 iForIndices(i, d->window->roots) {
1128 if (d->window->roots[i]) {
1129 arrange_Widget(d->window->roots[i]->widget);
1130 }
1131 }
1124 d->isRunning = iTrue; 1132 d->isRunning = iTrue;
1125 SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ 1133 SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */
1126#if defined (iPlatformDesktop) 1134#if defined (iPlatformDesktop)
@@ -1139,7 +1147,12 @@ static int run_App_(iApp *d) {
1139 1147
1140void refresh_App(void) { 1148void refresh_App(void) {
1141 iApp *d = &app_; 1149 iApp *d = &app_;
1142 destroyPending_Root(&d->window->root); 1150 iForIndices(i, d->window->roots) {
1151 iRoot *root = d->window->roots[i];
1152 if (root) {
1153 destroyPending_Root(root);
1154 }
1155 }
1143#if defined (LAGRANGE_ENABLE_IDLE_SLEEP) 1156#if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
1144 if (d->warmupFrames == 0 && d->isIdling) { 1157 if (d->warmupFrames == 0 && d->isIdling) {
1145 return; 1158 return;
@@ -1270,7 +1283,16 @@ void postCommandf_App(const char *command, ...) {
1270 1283
1271iAny *findWidget_App(const char *id) { 1284iAny *findWidget_App(const char *id) {
1272 if (!*id) return NULL; 1285 if (!*id) return NULL;
1273 return findChild_Widget(app_.window->root.widget, id); 1286 iForIndices(i, app_.window->roots) {
1287 iRoot *root = app_.window->roots[i];
1288 if (root) {
1289 iAny *found = findChild_Widget(root->widget, id);
1290 if (found) {
1291 return found;
1292 }
1293 }
1294 }
1295 return NULL;
1274} 1296}
1275 1297
1276void addTicker_App(iTickerFunc ticker, iAny *context) { 1298void addTicker_App(iTickerFunc ticker, iAny *context) {
@@ -1438,8 +1460,12 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) {
1438 return iFalse; 1460 return iFalse;
1439} 1461}
1440 1462
1463iDocumentWidget *document_Root(iRoot *d) {
1464 return iConstCast(iDocumentWidget *, currentTabPage_Widget(findChild_Widget(d->widget, "doctabs")));
1465}
1466
1441iDocumentWidget *document_App(void) { 1467iDocumentWidget *document_App(void) {
1442 return iConstCast(iDocumentWidget *, currentTabPage_Widget(findWidget_App("doctabs"))); 1468 return document_Root(get_Root());
1443} 1469}
1444 1470
1445iDocumentWidget *document_Command(const char *cmd) { 1471iDocumentWidget *document_Command(const char *cmd) {
@@ -2128,7 +2154,7 @@ iBool handleCommand_App(const char *cmd) {
2128 else if (equal_Command(cmd, "ident.import")) { 2154 else if (equal_Command(cmd, "ident.import")) {
2129 iCertImportWidget *imp = new_CertImportWidget(); 2155 iCertImportWidget *imp = new_CertImportWidget();
2130 setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); 2156 setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App()));
2131 addChild_Widget(d->window->root.widget, iClob(imp)); 2157 addChild_Widget(get_Root()->widget, iClob(imp));
2132 finalizeSheet_Widget(as_Widget(imp)); 2158 finalizeSheet_Widget(as_Widget(imp));
2133 postRefresh_App(); 2159 postRefresh_App();
2134 return iTrue; 2160 return iTrue;
@@ -2173,7 +2199,7 @@ iBool handleCommand_App(const char *cmd) {
2173 iProcessId pid = argLabel_Command(cmd, "pid"); 2199 iProcessId pid = argLabel_Command(cmd, "pid");
2174 if (pid) { 2200 if (pid) {
2175 iString *urls = collectNew_String(); 2201 iString *urls = collectNew_String();
2176 iConstForEach(ObjectList, i, iClob(listDocuments_App())) { 2202 iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) {
2177 append_String(urls, url_DocumentWidget(i.object)); 2203 append_String(urls, url_DocumentWidget(i.object));
2178 appendCStr_String(urls, "\n"); 2204 appendCStr_String(urls, "\n");
2179 } 2205 }
@@ -2258,3 +2284,20 @@ void revealPath_App(const iString *path) {
2258 iAssert(0 /* File revealing not implemented on this platform */); 2284 iAssert(0 /* File revealing not implemented on this platform */);
2259#endif 2285#endif
2260} 2286}
2287
2288iObjectList *listDocuments_App(const iRoot *rootOrNull) {
2289 iWindow *win = get_Window();
2290 iObjectList *docs = new_ObjectList();
2291 iForIndices(i, win->roots) {
2292 iRoot *root = win->roots[i];
2293 if (!rootOrNull || root == rootOrNull) {
2294 const iWidget *tabs = findChild_Widget(root->widget, "doctabs");
2295 iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) {
2296 if (isInstance_Object(i.object, &Class_DocumentWidget)) {
2297 pushBack_ObjectList(docs, i.object);
2298 }
2299 }
2300 }
2301 }
2302 return docs;
2303}