diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 119 |
1 files changed, 108 insertions, 11 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 2a3a2509..9fdadc4c 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -38,6 +38,7 @@ struct Impl_DocumentWidget { | |||
38 | iClick click; | 38 | iClick click; |
39 | iScrollWidget *scroll; | 39 | iScrollWidget *scroll; |
40 | iWidget *menu; | 40 | iWidget *menu; |
41 | // iWidget *userInput; | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | iDefineObjectConstruction(DocumentWidget) | 44 | iDefineObjectConstruction(DocumentWidget) |
@@ -64,6 +65,7 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
64 | { "---", 0, 0, NULL }, | 65 | { "---", 0, 0, NULL }, |
65 | { "Reload", 'r', KMOD_PRIMARY, "navigate.reload" } }, | 66 | { "Reload", 'r', KMOD_PRIMARY, "navigate.reload" } }, |
66 | 4); | 67 | 4); |
68 | // setFlags_Widget(d->userInput, hidden_WidgetFlag | disabled_WidgetFlag, iTrue); | ||
67 | } | 69 | } |
68 | 70 | ||
69 | void deinit_DocumentWidget(iDocumentWidget *d) { | 71 | void deinit_DocumentWidget(iDocumentWidget *d) { |
@@ -139,20 +141,27 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) { | |||
139 | render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d); | 141 | render_GmDocument(d->doc, visRange, addVisibleLink_DocumentWidget_, d); |
140 | } | 142 | } |
141 | 143 | ||
142 | static void updateSource_DocumentWidget_(iDocumentWidget *d) { | 144 | static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { |
143 | /* TODO: Do this in the background. However, that requires a text metrics calculator | ||
144 | that does not try to cache the glyph bitmaps. */ | ||
145 | iString str; | ||
146 | initBlock_String(&str, body_GmRequest(d->request)); | ||
147 | setSource_GmDocument(d->doc, &str, documentWidth_DocumentWidget_(d)); | ||
148 | deinit_String(&str); | ||
149 | updateVisible_DocumentWidget_(d); | ||
150 | refresh_Widget(as_Widget(d)); | ||
151 | setTitle_Window(get_Window(), | 145 | setTitle_Window(get_Window(), |
152 | !isEmpty_String(title_GmDocument(d->doc)) ? title_GmDocument(d->doc) | 146 | !isEmpty_String(title_GmDocument(d->doc)) ? title_GmDocument(d->doc) |
153 | : collectNewCStr_String("Lagrange")); | 147 | : collectNewCStr_String("Lagrange")); |
154 | } | 148 | } |
155 | 149 | ||
150 | static void updateSource_DocumentWidget_(iDocumentWidget *d) { | ||
151 | /* TODO: Do this in the background. However, that requires a text metrics calculator | ||
152 | that does not try to cache the glyph bitmaps. */ | ||
153 | if (status_GmRequest(d->request) != input_GmStatusCode && | ||
154 | status_GmRequest(d->request) != sensitiveInput_GmStatusCode) { | ||
155 | iString str; | ||
156 | initBlock_String(&str, body_GmRequest(d->request)); | ||
157 | setSource_GmDocument(d->doc, &str, documentWidth_DocumentWidget_(d)); | ||
158 | updateWindowTitle_DocumentWidget_(d); | ||
159 | updateVisible_DocumentWidget_(d); | ||
160 | refresh_Widget(as_Widget(d)); | ||
161 | deinit_String(&str); | ||
162 | } | ||
163 | } | ||
164 | |||
156 | static void fetch_DocumentWidget_(iDocumentWidget *d) { | 165 | static void fetch_DocumentWidget_(iDocumentWidget *d) { |
157 | /* Forget the previous request. */ | 166 | /* Forget the previous request. */ |
158 | if (d->request) { | 167 | if (d->request) { |
@@ -256,22 +265,80 @@ static const iString *absoluteUrl_DocumentWidget_(const iDocumentWidget *d, cons | |||
256 | return collect_String(absolute); | 265 | return collect_String(absolute); |
257 | } | 266 | } |
258 | 267 | ||
268 | static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode code) { | ||
269 | iWidget *w = as_Widget(d); | ||
270 | iString *src = collectNew_String(); | ||
271 | const iGmError *msg = get_GmError(code); | ||
272 | format_String(src, | ||
273 | "# %lc %s\n%s", | ||
274 | msg->icon ? msg->icon : 0x2327, /* X in a box */ | ||
275 | msg->title, | ||
276 | msg->info); | ||
277 | switch (code) { | ||
278 | case failedToOpenFile_GmStatusCode: | ||
279 | case certificateNotValid_GmStatusCode: | ||
280 | appendFormat_String(src, "\n\n%s", cstr_String(meta_GmRequest(d->request))); | ||
281 | break; | ||
282 | case slowDown_GmStatusCode: | ||
283 | appendFormat_String(src, "\n\nWait %s seconds before your next request.", | ||
284 | cstr_String(meta_GmRequest(d->request))); | ||
285 | break; | ||
286 | default: | ||
287 | break; | ||
288 | } | ||
289 | setSource_GmDocument(d->doc, src, documentWidth_DocumentWidget_(d)); | ||
290 | updateWindowTitle_DocumentWidget_(d); | ||
291 | updateVisible_DocumentWidget_(d); | ||
292 | refresh_Widget(w); | ||
293 | } | ||
294 | |||
259 | static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { | 295 | static void checkResponseCode_DocumentWidget_(iDocumentWidget *d) { |
260 | if (d->state == fetching_DocumentState) { | 296 | if (d->state == fetching_DocumentState) { |
261 | d->state = receivedPartialResponse_DocumentState; | 297 | d->state = receivedPartialResponse_DocumentState; |
262 | d->scrollY = 0; | 298 | d->scrollY = 0; |
263 | switch (status_GmRequest(d->request)) { | 299 | switch (status_GmRequest(d->request)) { |
300 | case none_GmStatusCode: | ||
301 | case success_GmStatusCode: | ||
302 | break; | ||
303 | case input_GmStatusCode: | ||
304 | case sensitiveInput_GmStatusCode: { | ||
305 | iUrl parts; | ||
306 | init_Url(&parts, d->url); | ||
307 | makeValueInput_Widget( | ||
308 | as_Widget(d), | ||
309 | NULL, | ||
310 | cstrFormat_String(cyan_ColorEscape "%s", | ||
311 | cstr_String(collect_String(newRange_String(parts.host)))), | ||
312 | isEmpty_String(meta_GmRequest(d->request)) | ||
313 | ? cstrFormat_String( | ||
314 | "Please enter input for %s:", | ||
315 | cstr_String(collect_String(newRange_String(parts.path)))) | ||
316 | : cstr_String(meta_GmRequest(d->request)), | ||
317 | orange_ColorEscape "Send \u21d2", | ||
318 | "document.input.submit"); | ||
319 | break; | ||
320 | } | ||
264 | case redirectTemporary_GmStatusCode: | 321 | case redirectTemporary_GmStatusCode: |
265 | case redirectPermanent_GmStatusCode: | 322 | case redirectPermanent_GmStatusCode: |
266 | postCommandf_App("open redirect:1 url:%s", cstr_String(meta_GmRequest(d->request))); | 323 | if (isEmpty_String(meta_GmRequest(d->request))) { |
267 | iReleasePtr(&d->request); | 324 | showErrorPage_DocumentWidget_(d, invalidRedirect_GmStatusCode); |
325 | } | ||
326 | else { | ||
327 | postCommandf_App("open redirect:1 url:%s", cstr_String(meta_GmRequest(d->request))); | ||
328 | iReleasePtr(&d->request); | ||
329 | } | ||
268 | break; | 330 | break; |
269 | default: | 331 | default: |
332 | showErrorPage_DocumentWidget_(d, status_GmRequest(d->request)); | ||
270 | break; | 333 | break; |
271 | } | 334 | } |
272 | } | 335 | } |
273 | } | 336 | } |
274 | 337 | ||
338 | const iString *valueString_Command(const char *cmd, const char *label) { | ||
339 | return collect_String(newCStr_String(suffixPtr_Command(cmd, label))); | ||
340 | } | ||
341 | |||
275 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { | 342 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { |
276 | iWidget *w = as_Widget(d); | 343 | iWidget *w = as_Widget(d); |
277 | if (isResize_UserEvent(ev)) { | 344 | if (isResize_UserEvent(ev)) { |
@@ -279,6 +346,25 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
279 | updateVisible_DocumentWidget_(d); | 346 | updateVisible_DocumentWidget_(d); |
280 | refresh_Widget(w); | 347 | refresh_Widget(w); |
281 | } | 348 | } |
349 | else if (isCommand_UserEvent(ev, "document.input.submit")) { | ||
350 | iString *value = collect_String(suffix_Command(command_UserEvent(ev), "value")); | ||
351 | urlEncode_String(value); | ||
352 | iString *url = collect_String(copy_String(d->url)); | ||
353 | const size_t qPos = indexOfCStr_String(url, "?"); | ||
354 | if (qPos != iInvalidPos) { | ||
355 | remove_Block(&url->chars, qPos, iInvalidSize); | ||
356 | } | ||
357 | appendCStr_String(url, "?"); | ||
358 | append_String(url, value); | ||
359 | postCommandf_App("open url:%s", cstr_String(url)); | ||
360 | return iTrue; | ||
361 | } | ||
362 | else if (isCommand_UserEvent(ev, "valueinput.cancelled") && | ||
363 | cmp_String(string_Command(command_UserEvent(ev), "id"), "document.input.submit") == | ||
364 | 0) { | ||
365 | postCommand_App("navigate.back"); | ||
366 | return iTrue; | ||
367 | } | ||
282 | else if (isCommand_Widget(w, ev, "document.request.updated") && | 368 | else if (isCommand_Widget(w, ev, "document.request.updated") && |
283 | pointerLabel_Command(command_UserEvent(ev), "request") == d->request) { | 369 | pointerLabel_Command(command_UserEvent(ev), "request") == d->request) { |
284 | updateSource_DocumentWidget_(d); | 370 | updateSource_DocumentWidget_(d); |
@@ -325,6 +411,17 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
325 | updateVisible_DocumentWidget_(d); | 411 | updateVisible_DocumentWidget_(d); |
326 | refresh_Widget(w); | 412 | refresh_Widget(w); |
327 | return iTrue; | 413 | return iTrue; |
414 | #if 0 | ||
415 | case 't': | ||
416 | if (mods == KMOD_PRIMARY) { | ||
417 | makeValueInput_Widget(get_Window()->root, | ||
418 | NULL, | ||
419 | cyan_ColorEscape "Input Needed", | ||
420 | "Give it!", | ||
421 | "document.input.submit"); | ||
422 | } | ||
423 | return iTrue; | ||
424 | #endif | ||
328 | case SDLK_END: | 425 | case SDLK_END: |
329 | d->scrollY = scrollMax_DocumentWidget_(d); | 426 | d->scrollY = scrollMax_DocumentWidget_(d); |
330 | updateVisible_DocumentWidget_(d); | 427 | updateVisible_DocumentWidget_(d); |