summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.c106
-rw-r--r--src/gmdocument.c34
-rw-r--r--src/ui/documentwidget.c2
-rw-r--r--src/ui/scrollwidget.c2
-rw-r--r--src/ui/widget.c2
-rw-r--r--src/ui/window.c2
6 files changed, 125 insertions, 23 deletions
diff --git a/src/app.c b/src/app.c
index 05038a4b..4c9a3477 100644
--- a/src/app.c
+++ b/src/app.c
@@ -28,6 +28,21 @@
28#endif 28#endif
29 29
30iDeclareType(App) 30iDeclareType(App)
31iDeclareType(HistoryItem)
32
33struct Impl_HistoryItem {
34 iTime when;
35 iString url;
36};
37
38void init_HistoryItem(iHistoryItem *d) {
39 initCurrent_Time(&d->when);
40 init_String(&d->url);
41}
42
43void deinit_HistoryItem(iHistoryItem *d) {
44 deinit_String(&d->url);
45}
31 46
32#if defined (iPlatformApple) 47#if defined (iPlatformApple)
33static const char *dataDir_App_ = "~/Library/Application Support/fi.skyjake.Lagrange"; 48static 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
41static const char *prefsFileName_App_ = "prefs.cfg"; 56static const char *prefsFileName_App_ = "prefs.cfg";
42 57
58static const int HISTORY_MAX = 100;
59
43struct Impl_App { 60struct 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
153static void clearHistory_App_(iApp *d) {
154 iForEach(Array, i, &d->history) {
155 deinit_HistoryItem(i.value);
156 }
157 clear_Array(&d->history);
158}
159
134static void init_App_(iApp *d, int argc, char **argv) { 160static 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
153static void deinit_App(iApp *d) { 181static 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
161const iString *execPath_App(void) { 191const 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
335static 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
340static 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
348static 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
305iBool handleCommand_App(const char *cmd) { 359iBool 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
135static void doLayout_GmDocument_(iGmDocument *d) { 135static 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
79void setId_Widget(iWidget *d, const char *id) { 80void 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}