diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/documentwidget.c | 11 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 87 | ||||
-rw-r--r-- | src/ui/text.c | 7 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 2 | ||||
-rw-r--r-- | src/ui/window.c | 34 |
5 files changed, 83 insertions, 58 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index a89eb0eb..3f655db5 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1863,7 +1863,12 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
1863 | updateTrust_DocumentWidget_(d, resp); | 1863 | updateTrust_DocumentWidget_(d, resp); |
1864 | init_Anim(&d->sideOpacity, 0); | 1864 | init_Anim(&d->sideOpacity, 0); |
1865 | init_Anim(&d->altTextOpacity, 0); | 1865 | init_Anim(&d->altTextOpacity, 0); |
1866 | format_String(&d->sourceHeader, "%d %s", statusCode, get_GmError(statusCode)->title); | 1866 | format_String(&d->sourceHeader, |
1867 | "%d %s", | ||
1868 | statusCode, | ||
1869 | isEmpty_String(&resp->meta) && !isSuccess_GmStatusCode(statusCode) | ||
1870 | ? get_GmError(statusCode)->title | ||
1871 | : cstr_String(&resp->meta)); | ||
1867 | d->sourceStatus = statusCode; | 1872 | d->sourceStatus = statusCode; |
1868 | switch (category_GmStatusCode(statusCode)) { | 1873 | switch (category_GmStatusCode(statusCode)) { |
1869 | case categoryInput_GmStatusCode: { | 1874 | case categoryInput_GmStatusCode: { |
@@ -2773,14 +2778,12 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2773 | id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) { | 2778 | id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) { |
2774 | set_Block(&d->sourceContent, body_GmRequest(d->request)); | 2779 | set_Block(&d->sourceContent, body_GmRequest(d->request)); |
2775 | if (!isSuccess_GmStatusCode(status_GmRequest(d->request))) { | 2780 | if (!isSuccess_GmStatusCode(status_GmRequest(d->request))) { |
2781 | /* TODO: Why is this here? Can it be removed? */ | ||
2776 | format_String(&d->sourceHeader, | 2782 | format_String(&d->sourceHeader, |
2777 | "%d %s", | 2783 | "%d %s", |
2778 | status_GmRequest(d->request), | 2784 | status_GmRequest(d->request), |
2779 | cstr_String(meta_GmRequest(d->request))); | 2785 | cstr_String(meta_GmRequest(d->request))); |
2780 | } | 2786 | } |
2781 | else { | ||
2782 | clear_String(&d->sourceHeader); | ||
2783 | } | ||
2784 | updateFetchProgress_DocumentWidget_(d); | 2787 | updateFetchProgress_DocumentWidget_(d); |
2785 | checkResponse_DocumentWidget_(d); | 2788 | checkResponse_DocumentWidget_(d); |
2786 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { | 2789 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 9f233345..2f0cabbb 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -360,35 +360,64 @@ static int endX_InputWidget_(const iInputWidget *d, int y) { | |||
360 | return line->range.end - (isLastLine_InputWidget_(d, line) ? 0 : 1) - line->range.start; | 360 | return line->range.end - (isLastLine_InputWidget_(d, line) ? 0 : 1) - line->range.start; |
361 | } | 361 | } |
362 | 362 | ||
363 | static iBool isCursorFocusable_Char_(iChar c) { | ||
364 | return !isDefaultIgnorable_Char(c) && | ||
365 | !isVariationSelector_Char(c) && | ||
366 | !isFitzpatrickType_Char(c); | ||
367 | } | ||
368 | |||
369 | static iChar at_InputWidget_(const iInputWidget *d, iInt2 pos) { | ||
370 | if (pos.y >= 0 && pos.y < size_Array(&d->lines) && | ||
371 | pos.x >= 0 && pos.x <= endX_InputWidget_(d, pos.y)) { | ||
372 | iChar ch = 0; | ||
373 | decodeBytes_MultibyteChar(charPos_InputWidget_(d, pos), | ||
374 | constEnd_String(lineString_InputWidget_(d, pos.y)), | ||
375 | &ch); | ||
376 | return ch; | ||
377 | } | ||
378 | return ' '; | ||
379 | } | ||
380 | |||
363 | static iInt2 movedCursor_InputWidget_(const iInputWidget *d, iInt2 pos, int xDir, int yDir) { | 381 | static iInt2 movedCursor_InputWidget_(const iInputWidget *d, iInt2 pos, int xDir, int yDir) { |
364 | iChar ch; | 382 | iChar ch = 0; |
365 | if (xDir < 0) { | 383 | int n = 0; |
366 | if (pos.x == 0) { | 384 | /* TODO: The cursor should never land on any combining codepoints either. */ |
367 | if (pos.y > 0) { | 385 | for (;;) { |
368 | pos.x = endX_InputWidget_(d, --pos.y); | 386 | if (xDir < 0) { |
387 | if (pos.x == 0) { | ||
388 | if (pos.y > 0) { | ||
389 | pos.x = endX_InputWidget_(d, --pos.y); | ||
390 | } | ||
369 | } | 391 | } |
370 | } | 392 | else { |
371 | else { | 393 | iAssert(pos.x > 0); |
372 | iAssert(pos.x > 0); | 394 | n = decodePrecedingBytes_MultibyteChar(charPos_InputWidget_(d, pos), |
373 | int n = decodePrecedingBytes_MultibyteChar(charPos_InputWidget_(d, pos), | ||
374 | cstr_String(lineString_InputWidget_(d, pos.y)), | 395 | cstr_String(lineString_InputWidget_(d, pos.y)), |
375 | &ch); | 396 | &ch); |
376 | pos.x -= n; | 397 | pos.x -= n; |
377 | } | 398 | if (!isCursorFocusable_Char_(at_InputWidget_(d, pos))) { |
378 | } | 399 | continue; |
379 | else if (xDir > 0) { | 400 | } |
380 | if (pos.x == endX_InputWidget_(d, pos.y)) { | ||
381 | if (pos.y < size_Array(&d->lines) - 1) { | ||
382 | pos.y++; | ||
383 | pos.x = 0; | ||
384 | } | 401 | } |
385 | } | 402 | } |
386 | else { | 403 | else if (xDir > 0) { |
387 | int n = decodeBytes_MultibyteChar(charPos_InputWidget_(d, pos), | 404 | if (pos.x == endX_InputWidget_(d, pos.y)) { |
405 | if (pos.y < size_Array(&d->lines) - 1) { | ||
406 | pos.y++; | ||
407 | pos.x = 0; | ||
408 | } | ||
409 | } | ||
410 | else { | ||
411 | n = decodeBytes_MultibyteChar(charPos_InputWidget_(d, pos), | ||
388 | constEnd_String(lineString_InputWidget_(d, pos.y)), | 412 | constEnd_String(lineString_InputWidget_(d, pos.y)), |
389 | &ch); | 413 | &ch); |
390 | pos.x += n; | 414 | pos.x += n; |
415 | if (!isCursorFocusable_Char_(at_InputWidget_(d, pos))) { | ||
416 | continue; | ||
417 | } | ||
418 | } | ||
391 | } | 419 | } |
420 | break; | ||
392 | } | 421 | } |
393 | return pos; | 422 | return pos; |
394 | } | 423 | } |
@@ -1026,7 +1055,9 @@ static void insertRange_InputWidget_(iInputWidget *d, iRangecc range) { | |||
1026 | cstr_String(&line->text) + d->cursor.x, constEnd_String(&line->text) | 1055 | cstr_String(&line->text) + d->cursor.x, constEnd_String(&line->text) |
1027 | }); | 1056 | }); |
1028 | truncate_String(&line->text, d->cursor.x); | 1057 | truncate_String(&line->text, d->cursor.x); |
1029 | appendCStr_String(&line->text, "\n"); | 1058 | if (!endsWith_String(&line->text, "\n")) { |
1059 | appendCStr_String(&line->text, "\n"); | ||
1060 | } | ||
1030 | insert_Array(&d->lines, ++d->cursor.y, &split); | 1061 | insert_Array(&d->lines, ++d->cursor.y, &split); |
1031 | d->cursor.x = 0; | 1062 | d->cursor.x = 0; |
1032 | } | 1063 | } |
@@ -1059,6 +1090,8 @@ void setCursor_InputWidget(iInputWidget *d, iInt2 pos) { | |||
1059 | iAssert(!isEmpty_Array(&d->lines)); | 1090 | iAssert(!isEmpty_Array(&d->lines)); |
1060 | pos.x = iClamp(pos.x, 0, endX_InputWidget_(d, pos.y)); | 1091 | pos.x = iClamp(pos.x, 0, endX_InputWidget_(d, pos.y)); |
1061 | d->cursor = pos; | 1092 | d->cursor = pos; |
1093 | iChar ch = at_InputWidget_(d, pos); | ||
1094 | printf("cursor x:%d ch:%08x (%lc)\n", pos.x, ch, (int)ch); | ||
1062 | /* Update selection. */ | 1095 | /* Update selection. */ |
1063 | if (isMarking_()) { | 1096 | if (isMarking_()) { |
1064 | if (isEmpty_Range(&d->mark)) { | 1097 | if (isEmpty_Range(&d->mark)) { |
@@ -1221,18 +1254,6 @@ static iBool deleteMarked_InputWidget_(iInputWidget *d) { | |||
1221 | return iFalse; | 1254 | return iFalse; |
1222 | } | 1255 | } |
1223 | 1256 | ||
1224 | static iChar at_InputWidget_(const iInputWidget *d, iInt2 pos) { | ||
1225 | if (pos.y >= 0 && pos.y < size_Array(&d->lines) && | ||
1226 | pos.x >= 0 && pos.x <= endX_InputWidget_(d, pos.y)) { | ||
1227 | iChar ch = 0; | ||
1228 | decodeBytes_MultibyteChar(charPos_InputWidget_(d, pos), | ||
1229 | constEnd_String(lineString_InputWidget_(d, pos.y)), | ||
1230 | &ch); | ||
1231 | return ch; | ||
1232 | } | ||
1233 | return ' '; | ||
1234 | } | ||
1235 | |||
1236 | static iBool isWordChar_InputWidget_(const iInputWidget *d, iInt2 pos) { | 1257 | static iBool isWordChar_InputWidget_(const iInputWidget *d, iInt2 pos) { |
1237 | return isAlphaNumeric_Char(at_InputWidget_(d, pos)); | 1258 | return isAlphaNumeric_Char(at_InputWidget_(d, pos)); |
1238 | } | 1259 | } |
diff --git a/src/ui/text.c b/src/ui/text.c index 0a8386e4..639d8f13 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -1433,6 +1433,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1433 | iBool isFirst = iTrue; | 1433 | iBool isFirst = iTrue; |
1434 | const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); | 1434 | const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); |
1435 | const iBool checkHitChar = wrap && wrap->hitChar; | 1435 | const iBool checkHitChar = wrap && wrap->hitChar; |
1436 | iBool wasCharHit = iFalse; | ||
1436 | while (!isEmpty_Range(&wrapRuns)) { | 1437 | while (!isEmpty_Range(&wrapRuns)) { |
1437 | if (isFirst) { | 1438 | if (isFirst) { |
1438 | isFirst = iFalse; | 1439 | isFirst = iFalse; |
@@ -1452,9 +1453,10 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1452 | for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { | 1453 | for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { |
1453 | const iAttributedRun *run = at_Array(&attrText.runs, runIndex); | 1454 | const iAttributedRun *run = at_Array(&attrText.runs, runIndex); |
1454 | if (run->flags.isLineBreak) { | 1455 | if (run->flags.isLineBreak) { |
1455 | if (checkHitChar) { | 1456 | if (checkHitChar && !wasCharHit) { |
1456 | if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) { | 1457 | if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) { |
1457 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); | 1458 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); |
1459 | wasCharHit = iTrue; | ||
1458 | } | 1460 | } |
1459 | } | 1461 | } |
1460 | wrapPosRange.end = run->logical.start; | 1462 | wrapPosRange.end = run->logical.start; |
@@ -1479,9 +1481,10 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1479 | if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { | 1481 | if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { |
1480 | continue; | 1482 | continue; |
1481 | } | 1483 | } |
1482 | if (checkHitChar) { | 1484 | if (checkHitChar && !wasCharHit) { |
1483 | if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) { | 1485 | if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) { |
1484 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); | 1486 | wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); |
1487 | wasCharHit = iTrue; | ||
1485 | } | 1488 | } |
1486 | } | 1489 | } |
1487 | /* Check if the hit point is on the left side of this line. */ | 1490 | /* Check if the hit point is on the left side of this line. */ |
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index 57b6b6b7..5e1ee493 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c | |||
@@ -149,7 +149,7 @@ void init_UploadWidget(iUploadWidget *d) { | |||
149 | iWidget *buttons = | 149 | iWidget *buttons = |
150 | makeDialogButtons_Widget((iMenuItem[]){ { "${upload.port}", 0, 0, "upload.setport" }, | 150 | makeDialogButtons_Widget((iMenuItem[]){ { "${upload.port}", 0, 0, "upload.setport" }, |
151 | { "---", 0, 0, NULL }, | 151 | { "---", 0, 0, NULL }, |
152 | { "${cancel}", SDLK_ESCAPE, 0, "upload.cancel" }, | 152 | { "${close}", SDLK_ESCAPE, 0, "upload.cancel" }, |
153 | { uiTextAction_ColorEscape "${dlg.upload.send}", | 153 | { uiTextAction_ColorEscape "${dlg.upload.send}", |
154 | SDLK_RETURN, | 154 | SDLK_RETURN, |
155 | KMOD_PRIMARY, | 155 | KMOD_PRIMARY, |
diff --git a/src/ui/window.c b/src/ui/window.c index 86d22b1c..1727b988 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -219,25 +219,23 @@ static void updateSize_Window_(iWindow *d, iBool notifyAlways) { | |||
219 | size->y -= d->keyboardHeight; | 219 | size->y -= d->keyboardHeight; |
220 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { | 220 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { |
221 | windowSizeChanged_Window_(d); | 221 | windowSizeChanged_Window_(d); |
222 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); | 222 | if (!isEqual_I2(*size, d->place.lastNotifiedSize)) { |
223 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); | 223 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); |
224 | postCommandf_App("window.resized width:%d height:%d horiz:%d vert:%d", | 224 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); |
225 | size->x, | 225 | postCommandf_App("window.resized width:%d height:%d horiz:%d vert:%d", |
226 | size->y, | 226 | size->x, |
227 | isHoriz, | 227 | size->y, |
228 | isVert); | 228 | isHoriz, |
229 | postCommand_App("widget.overflow"); /* check bounds with updated sizes */ | 229 | isVert); |
230 | postCommand_App("widget.overflow"); /* check bounds with updated sizes */ | ||
231 | } | ||
230 | postRefresh_App(); | 232 | postRefresh_App(); |
231 | d->place.lastNotifiedSize = *size; | 233 | d->place.lastNotifiedSize = *size; |
232 | } | 234 | } |
233 | } | 235 | } |
234 | 236 | ||
235 | void drawWhileResizing_Window(iWindow *d, int w, int h) { | 237 | void drawWhileResizing_Window(iWindow *d, int w, int h) { |
236 | /* This is called while a window resize is in progress, so we can be pretty confident | 238 | draw_Window(d); |
237 | the size has actually changed. */ | ||
238 | d->size = coord_Window(d, w, h); | ||
239 | windowSizeChanged_Window_(d); | ||
240 | draw_Window(d); | ||
241 | } | 239 | } |
242 | 240 | ||
243 | static float pixelRatio_Window_(const iWindow *d) { | 241 | static float pixelRatio_Window_(const iWindow *d) { |
@@ -489,7 +487,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
489 | SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y); | 487 | SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y); |
490 | setupUserInterface_Window(d); | 488 | setupUserInterface_Window(d); |
491 | postCommand_App("~bindings.changed"); /* update from bindings */ | 489 | postCommand_App("~bindings.changed"); /* update from bindings */ |
492 | updateSize_Window_(d, iFalse); | 490 | //updateSize_Window_(d, iFalse); |
493 | /* Load the border shadow texture. */ { | 491 | /* Load the border shadow texture. */ { |
494 | SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0); | 492 | SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0); |
495 | d->borderShadow = SDL_CreateTextureFromSurface(d->render, surf); | 493 | d->borderShadow = SDL_CreateTextureFromSurface(d->render, surf); |
@@ -728,7 +726,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
728 | } | 726 | } |
729 | case SDL_WINDOWEVENT_RESIZED: | 727 | case SDL_WINDOWEVENT_RESIZED: |
730 | if (d->isMinimized) { | 728 | if (d->isMinimized) { |
731 | updateSize_Window_(d, iTrue); | 729 | //updateSize_Window_(d, iTrue); |
732 | return iTrue; | 730 | return iTrue; |
733 | } | 731 | } |
734 | if (unsnap_Window_(d, NULL)) { | 732 | if (unsnap_Window_(d, NULL)) { |
@@ -739,7 +737,7 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
739 | //printf("normal rect set (resize)\n"); fflush(stdout); | 737 | //printf("normal rect set (resize)\n"); fflush(stdout); |
740 | } | 738 | } |
741 | checkPixelRatioChange_Window_(d); | 739 | checkPixelRatioChange_Window_(d); |
742 | updateSize_Window_(d, iTrue /* we were already redrawing during the resize */); | 740 | //updateSize_Window_(d, iTrue /* we were already redrawing during the resize */); |
743 | postRefresh_App(); | 741 | postRefresh_App(); |
744 | return iTrue; | 742 | return iTrue; |
745 | case SDL_WINDOWEVENT_RESTORED: | 743 | case SDL_WINDOWEVENT_RESTORED: |
@@ -1014,7 +1012,7 @@ void draw_Window(iWindow *d) { | |||
1014 | if (d->isDrawFrozen) { | 1012 | if (d->isDrawFrozen) { |
1015 | return; | 1013 | return; |
1016 | } | 1014 | } |
1017 | #if defined (iPlatformMobile) | 1015 | //#if defined (iPlatformMobile) |
1018 | /* Check if root needs resizing. */ { | 1016 | /* Check if root needs resizing. */ { |
1019 | iInt2 renderSize; | 1017 | iInt2 renderSize; |
1020 | SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); | 1018 | SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); |
@@ -1023,7 +1021,7 @@ void draw_Window(iWindow *d) { | |||
1023 | processEvents_App(postedEventsOnly_AppEventMode); | 1021 | processEvents_App(postedEventsOnly_AppEventMode); |
1024 | } | 1022 | } |
1025 | } | 1023 | } |
1026 | #endif | 1024 | //#endif |
1027 | const int winFlags = SDL_GetWindowFlags(d->win); | 1025 | const int winFlags = SDL_GetWindowFlags(d->win); |
1028 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; | 1026 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; |
1029 | iPaint p; | 1027 | iPaint p; |