diff options
-rw-r--r-- | src/app.c | 106 | ||||
-rw-r--r-- | src/gmdocument.c | 34 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 2 | ||||
-rw-r--r-- | src/ui/scrollwidget.c | 2 | ||||
-rw-r--r-- | src/ui/widget.c | 2 | ||||
-rw-r--r-- | src/ui/window.c | 2 |
6 files changed, 125 insertions, 23 deletions
@@ -28,6 +28,21 @@ | |||
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | iDeclareType(App) | 30 | iDeclareType(App) |
31 | iDeclareType(HistoryItem) | ||
32 | |||
33 | struct Impl_HistoryItem { | ||
34 | iTime when; | ||
35 | iString url; | ||
36 | }; | ||
37 | |||
38 | void init_HistoryItem(iHistoryItem *d) { | ||
39 | initCurrent_Time(&d->when); | ||
40 | init_String(&d->url); | ||
41 | } | ||
42 | |||
43 | void deinit_HistoryItem(iHistoryItem *d) { | ||
44 | deinit_String(&d->url); | ||
45 | } | ||
31 | 46 | ||
32 | #if defined (iPlatformApple) | 47 | #if defined (iPlatformApple) |
33 | static const char *dataDir_App_ = "~/Library/Application Support/fi.skyjake.Lagrange"; | 48 | static const char *dataDir_App_ = "~/Library/Application Support/fi.skyjake.Lagrange"; |
@@ -40,12 +55,16 @@ static const char *dataDir_App_ = "~/.config/lagrange"; | |||
40 | #endif | 55 | #endif |
41 | static const char *prefsFileName_App_ = "prefs.cfg"; | 56 | static const char *prefsFileName_App_ = "prefs.cfg"; |
42 | 57 | ||
58 | static const int HISTORY_MAX = 100; | ||
59 | |||
43 | struct Impl_App { | 60 | struct Impl_App { |
44 | iCommandLine args; | 61 | iCommandLine args; |
45 | iBool running; | 62 | iBool running; |
46 | iWindow * window; | 63 | iWindow * window; |
47 | iSortedArray tickers; | 64 | iSortedArray tickers; |
48 | iBool pendingRefresh; | 65 | iBool pendingRefresh; |
66 | iArray history; | ||
67 | size_t historyPos; /* zero at the latest item */ | ||
49 | /* Preferences: */ | 68 | /* Preferences: */ |
50 | iBool retainWindowSize; | 69 | iBool retainWindowSize; |
51 | float uiScale; | 70 | float uiScale; |
@@ -131,9 +150,18 @@ static void savePrefs_App_(const iApp *d) { | |||
131 | delete_String(cfg); | 150 | delete_String(cfg); |
132 | } | 151 | } |
133 | 152 | ||
153 | static void clearHistory_App_(iApp *d) { | ||
154 | iForEach(Array, i, &d->history) { | ||
155 | deinit_HistoryItem(i.value); | ||
156 | } | ||
157 | clear_Array(&d->history); | ||
158 | } | ||
159 | |||
134 | static void init_App_(iApp *d, int argc, char **argv) { | 160 | static void init_App_(iApp *d, int argc, char **argv) { |
135 | init_CommandLine(&d->args, argc, argv); | 161 | init_CommandLine(&d->args, argc, argv); |
136 | init_SortedArray(&d->tickers, sizeof(iTicker), cmp_Ticker_); | 162 | init_SortedArray(&d->tickers, sizeof(iTicker), cmp_Ticker_); |
163 | init_Array(&d->history, sizeof(iHistoryItem)); | ||
164 | d->historyPos = 0; | ||
137 | d->running = iFalse; | 165 | d->running = iFalse; |
138 | d->window = NULL; | 166 | d->window = NULL; |
139 | d->retainWindowSize = iTrue; | 167 | d->retainWindowSize = iTrue; |
@@ -152,10 +180,12 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
152 | 180 | ||
153 | static void deinit_App(iApp *d) { | 181 | static void deinit_App(iApp *d) { |
154 | savePrefs_App_(d); | 182 | savePrefs_App_(d); |
183 | clearHistory_App_(d); | ||
184 | deinit_Array(&d->history); | ||
155 | deinit_SortedArray(&d->tickers); | 185 | deinit_SortedArray(&d->tickers); |
156 | delete_Window(d->window); | 186 | delete_Window(d->window); |
157 | d->window = NULL; | 187 | d->window = NULL; |
158 | deinit_CommandLine(&d->args); | 188 | deinit_CommandLine(&d->args); |
159 | } | 189 | } |
160 | 190 | ||
161 | const iString *execPath_App(void) { | 191 | const iString *execPath_App(void) { |
@@ -302,12 +332,62 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
302 | return iFalse; | 332 | return iFalse; |
303 | } | 333 | } |
304 | 334 | ||
335 | static iHistoryItem *historyItem_App_(iApp *d, size_t pos) { | ||
336 | if (isEmpty_Array(&d->history)) return NULL; | ||
337 | return &value_Array(&d->history, size_Array(&d->history) - 1 - pos, iHistoryItem); | ||
338 | } | ||
339 | |||
340 | static const iString *historyUrl_App_(iApp *d, size_t pos) { | ||
341 | const iHistoryItem *item = historyItem_App_(d, pos); | ||
342 | if (item) { | ||
343 | return &item->url; | ||
344 | } | ||
345 | return collectNew_String(); | ||
346 | } | ||
347 | |||
348 | static void printHistory_App_(const iApp *d) { | ||
349 | iConstForEach(Array, i, &d->history) { | ||
350 | const size_t idx = index_ArrayConstIterator(&i); | ||
351 | printf("%s[%zu]: %s\n", | ||
352 | d->historyPos == size_Array(&d->history) - idx - 1 ? "->" : " ", | ||
353 | idx, | ||
354 | cstr_String(&((const iHistoryItem *) i.value)->url)); | ||
355 | } | ||
356 | fflush(stdout); | ||
357 | } | ||
358 | |||
305 | iBool handleCommand_App(const char *cmd) { | 359 | iBool handleCommand_App(const char *cmd) { |
306 | iApp *d = &app_; | 360 | iApp *d = &app_; |
307 | iWidget *root = d->window->root; | 361 | iWidget *root = d->window->root; |
308 | if (equal_Command(cmd, "open")) { | 362 | if (equal_Command(cmd, "open")) { |
309 | setUrl_DocumentWidget(findChild_Widget(root, "document"), | 363 | const iString *url = collect_String(newCStr_String(valuePtr_Command(cmd, "url"))); |
310 | collect_String(newCStr_String(valuePtr_Command(cmd, "url")))); | 364 | if (!argLabel_Command(cmd, "history")) { |
365 | if (argLabel_Command(cmd, "redirect")) { | ||
366 | /* Update in the history. */ | ||
367 | iHistoryItem *item = historyItem_App_(d, d->historyPos); | ||
368 | if (item) { | ||
369 | set_String(&item->url, url); | ||
370 | } | ||
371 | } | ||
372 | else { | ||
373 | /* Cut the trailing history items. */ | ||
374 | if (d->historyPos > 0) { | ||
375 | for (size_t i = 0; i < d->historyPos - 1; i++) { | ||
376 | deinit_HistoryItem(historyItem_App_(d, i)); | ||
377 | } | ||
378 | removeN_Array( | ||
379 | &d->history, size_Array(&d->history) - d->historyPos, iInvalidSize); | ||
380 | d->historyPos = 0; | ||
381 | } | ||
382 | /* Insert new item. */ | ||
383 | iHistoryItem item; | ||
384 | init_HistoryItem(&item); | ||
385 | set_String(&item.url, url); | ||
386 | pushBack_Array(&d->history, &item); | ||
387 | } | ||
388 | } | ||
389 | printHistory_App_(d); | ||
390 | setUrl_DocumentWidget(findChild_Widget(root, "document"), url); | ||
311 | } | 391 | } |
312 | else if (equal_Command(cmd, "quit")) { | 392 | else if (equal_Command(cmd, "quit")) { |
313 | SDL_Event ev; | 393 | SDL_Event ev; |
@@ -328,6 +408,26 @@ iBool handleCommand_App(const char *cmd) { | |||
328 | const iInt2 pos = coord_Command(cmd); | 408 | const iInt2 pos = coord_Command(cmd); |
329 | SDL_SetWindowPosition(d->window->win, pos.x, pos.y); | 409 | SDL_SetWindowPosition(d->window->win, pos.x, pos.y); |
330 | } | 410 | } |
411 | else if (equal_Command(cmd, "document.changed")) { | ||
412 | /* TODO: Update current history item with this actual/redirected URL. */ | ||
413 | return iFalse; | ||
414 | } | ||
415 | else if (equal_Command(cmd, "navigate.back")) { | ||
416 | if (d->historyPos < size_Array(&d->history) - 1) { | ||
417 | d->historyPos++; | ||
418 | postCommandf_App("open history:1 url:%s", | ||
419 | cstr_String(historyUrl_App_(d, d->historyPos))); | ||
420 | } | ||
421 | return iTrue; | ||
422 | } | ||
423 | else if (equal_Command(cmd, "navigate.forward")) { | ||
424 | if (d->historyPos > 0) { | ||
425 | d->historyPos--; | ||
426 | postCommandf_App("open history:1 url:%s", | ||
427 | cstr_String(historyUrl_App_(d, d->historyPos))); | ||
428 | } | ||
429 | return iTrue; | ||
430 | } | ||
331 | else { | 431 | else { |
332 | return iFalse; | 432 | return iFalse; |
333 | } | 433 | } |
diff --git a/src/gmdocument.c b/src/gmdocument.c index 6fde864a..eb147925 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -133,15 +133,6 @@ static void clearLinks_GmDocument_(iGmDocument *d) { | |||
133 | } | 133 | } |
134 | 134 | ||
135 | static void doLayout_GmDocument_(iGmDocument *d) { | 135 | static void doLayout_GmDocument_(iGmDocument *d) { |
136 | clear_Array(&d->layout); | ||
137 | clearLinks_GmDocument_(d); | ||
138 | if (d->size.x <= 0 || isEmpty_String(&d->source)) { | ||
139 | return; | ||
140 | } | ||
141 | iBool isPreformat = iFalse; | ||
142 | iInt2 pos = zero_I2(); | ||
143 | const iRangecc content = range_String(&d->source); | ||
144 | iRangecc line = iNullRange; | ||
145 | /* TODO: Collect these parameters into a GmTheme. */ | 136 | /* TODO: Collect these parameters into a GmTheme. */ |
146 | static const int fonts[max_GmLineType] = { | 137 | static const int fonts[max_GmLineType] = { |
147 | paragraph_FontId, | 138 | paragraph_FontId, |
@@ -152,17 +143,17 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
152 | header2_FontId, | 143 | header2_FontId, |
153 | header3_FontId, | 144 | header3_FontId, |
154 | regular_FontId, | 145 | regular_FontId, |
155 | }; | 146 | }; |
156 | static const int colors[max_GmLineType] = { | 147 | static const int colors[max_GmLineType] = { |
157 | gray75_ColorId, | 148 | gray75_ColorId, |
158 | gray75_ColorId, | 149 | gray75_ColorId, |
159 | orange_ColorId, | 150 | cyan_ColorId, |
160 | orange_ColorId, | 151 | gray75_ColorId, |
161 | white_ColorId, | 152 | white_ColorId, |
162 | white_ColorId, | 153 | white_ColorId, |
163 | white_ColorId, | 154 | white_ColorId, |
164 | white_ColorId, | 155 | white_ColorId, |
165 | }; | 156 | }; |
166 | static const int indents[max_GmLineType] = { | 157 | static const int indents[max_GmLineType] = { |
167 | 4, 10, 4, 10, 0, 0, 0, 0 | 158 | 4, 10, 4, 10, 0, 0, 0, 0 |
168 | }; | 159 | }; |
@@ -173,10 +164,19 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
173 | 0.0f, 0.5f, 1.0f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f | 164 | 0.0f, 0.5f, 1.0f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f |
174 | }; | 165 | }; |
175 | static const char *bullet = "\u2022"; | 166 | static const char *bullet = "\u2022"; |
176 | iRangecc preAltText = iNullRange; | 167 | clear_Array(&d->layout); |
177 | enum iGmLineType prevType = text_GmLineType; | 168 | clearLinks_GmDocument_(d); |
178 | iBool isFirstText = iTrue; | 169 | if (d->size.x <= 0 || isEmpty_String(&d->source)) { |
179 | int preFont = preformatted_FontId; | 170 | return; |
171 | } | ||
172 | const iRangecc content = range_String(&d->source); | ||
173 | iInt2 pos = zero_I2(); | ||
174 | iRangecc line = iNullRange; | ||
175 | iRangecc preAltText = iNullRange; | ||
176 | enum iGmLineType prevType = text_GmLineType; | ||
177 | iBool isPreformat = iFalse; | ||
178 | iBool isFirstText = iTrue; | ||
179 | int preFont = preformatted_FontId; | ||
180 | while (nextSplit_Rangecc(&content, "\n", &line)) { | 180 | while (nextSplit_Rangecc(&content, "\n", &line)) { |
181 | iGmRun run; | 181 | iGmRun run; |
182 | run.color = white_ColorId; | 182 | run.color = white_ColorId; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 3bb66be6..4cd0ac18 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -247,7 +247,7 @@ static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { | |||
247 | switch (status_GmRequest(d->request)) { | 247 | switch (status_GmRequest(d->request)) { |
248 | case redirectTemporary_GmStatusCode: | 248 | case redirectTemporary_GmStatusCode: |
249 | case redirectPermanent_GmStatusCode: | 249 | case redirectPermanent_GmStatusCode: |
250 | postCommandf_App("open url:%s", cstr_String(meta_GmRequest(d->request))); | 250 | postCommandf_App("open redirect:1 url:%s", cstr_String(meta_GmRequest(d->request))); |
251 | iReleasePtr(&d->request); | 251 | iReleasePtr(&d->request); |
252 | break; | 252 | break; |
253 | default: | 253 | default: |
diff --git a/src/ui/scrollwidget.c b/src/ui/scrollwidget.c index 1961677b..65b20a28 100644 --- a/src/ui/scrollwidget.c +++ b/src/ui/scrollwidget.c | |||
@@ -115,7 +115,7 @@ static void draw_ScrollWidget_(const iScrollWidget *d) { | |||
115 | iPaint p; | 115 | iPaint p; |
116 | init_Paint(&p); | 116 | init_Paint(&p); |
117 | drawRect_Paint(&p, bounds, black_ColorId); | 117 | drawRect_Paint(&p, bounds, black_ColorId); |
118 | fillRect_Paint(&p, shrunk_Rect(thumbRect_ScrollWidget_(d), one_I2()), | 118 | fillRect_Paint(&p, shrunk_Rect(thumbRect_ScrollWidget_(d), init1_I2(gap_UI / 2)), |
119 | isPressed ? orange_ColorId : gray50_ColorId); | 119 | isPressed ? orange_ColorId : gray50_ColorId); |
120 | } | 120 | } |
121 | } | 121 | } |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 86d2e195..69509e33 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -74,6 +74,7 @@ void destroy_Widget(iWidget *d) { | |||
74 | rootData_.pendingDestruction = new_PtrSet(); | 74 | rootData_.pendingDestruction = new_PtrSet(); |
75 | } | 75 | } |
76 | insert_PtrSet(rootData_.pendingDestruction, d); | 76 | insert_PtrSet(rootData_.pendingDestruction, d); |
77 | postRefresh_App(); | ||
77 | } | 78 | } |
78 | 79 | ||
79 | void setId_Widget(iWidget *d, const char *id) { | 80 | void setId_Widget(iWidget *d, const char *id) { |
@@ -449,6 +450,7 @@ iAny *removeChild_Widget(iWidget *d, iAnyObject *child) { | |||
449 | } | 450 | } |
450 | iAssert(found); | 451 | iAssert(found); |
451 | ((iWidget *) child)->parent = NULL; | 452 | ((iWidget *) child)->parent = NULL; |
453 | postRefresh_App(); | ||
452 | return child; | 454 | return child; |
453 | } | 455 | } |
454 | 456 | ||
diff --git a/src/ui/window.c b/src/ui/window.c index 2d030dcc..896b1e66 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -86,7 +86,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { | |||
86 | iInputWidget *url = findWidget_App("url"); | 86 | iInputWidget *url = findWidget_App("url"); |
87 | setTextCStr_InputWidget(url, valuePtr_Command(cmd, "url")); | 87 | setTextCStr_InputWidget(url, valuePtr_Command(cmd, "url")); |
88 | setTitle_Window(get_Window(), text_InputWidget(url)); | 88 | setTitle_Window(get_Window(), text_InputWidget(url)); |
89 | return iTrue; | 89 | return iFalse; |
90 | } | 90 | } |
91 | return iFalse; | 91 | return iFalse; |
92 | } | 92 | } |