summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/about/version.gmi5
-rw-r--r--src/main.c7
-rw-r--r--src/ui/inputwidget.c22
-rw-r--r--src/ui/sidebarwidget.c4
-rw-r--r--src/ui/text.c23
5 files changed, 34 insertions, 27 deletions
diff --git a/res/about/version.gmi b/res/about/version.gmi
index 5141a4b1..35c730c1 100644
--- a/res/about/version.gmi
+++ b/res/about/version.gmi
@@ -10,6 +10,11 @@
10* Added support for viewing WebP images. The libwebp library is an optional dependency and will be included in the build if found via pkg-config. 10* Added support for viewing WebP images. The libwebp library is an optional dependency and will be included in the build if found via pkg-config.
11* Added a footer action to view `application/octet-stream` content depending on recognized file extensions. 11* Added a footer action to view `application/octet-stream` content depending on recognized file extensions.
12 12
13## 1.6.5
14* Audio init errors are no longer fatal. SDL's error message will still be printed.
15* Fixed a cursor position regression in input fields related to handling of variation selectors (codepoint clusters). Moving the cursor to the start of a wrapped line segment put the cursor in the wrong place.
16* Fixed right-clicking on sidebar tab buttons. It was showing the wrong context menu when the list had been scrolled down.
17
13## 1.6.4 18## 1.6.4
14* Local files containing UTF-8 text can be viewed regardless of their file extension. 19* Local files containing UTF-8 text can be viewed regardless of their file extension.
15* Fixed input field cursor positioning and insertion problems around Emoji variation selectors. 20* Fixed input field cursor positioning and insertion problems around Emoji variation selectors.
diff --git a/src/main.c b/src/main.c
index b1850283..efe96ad9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -68,10 +68,13 @@ int main(int argc, char **argv) {
68 "DHE-RSA-AES256-GCM-SHA384"); 68 "DHE-RSA-AES256-GCM-SHA384");
69 SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); 69 SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1");
70 SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1"); 70 SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1");
71 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { 71 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
72 fprintf(stderr, "SDL init failed: %s\n", SDL_GetError()); 72 fprintf(stderr, "[SDL] init failed: %s\n", SDL_GetError());
73 return -1; 73 return -1;
74 } 74 }
75 if (SDL_Init(SDL_INIT_AUDIO)) {
76 fprintf(stderr, "[SDL] audio init failed: %s\n", SDL_GetError());
77 }
75 run_App(argc, argv); 78 run_App(argc, argv);
76 SDL_Quit(); 79 SDL_Quit();
77#if defined (LAGRANGE_ENABLE_MPG123) 80#if defined (LAGRANGE_ENABLE_MPG123)
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c
index e0272a5d..fa65cf3c 100644
--- a/src/ui/inputwidget.c
+++ b/src/ui/inputwidget.c
@@ -59,7 +59,7 @@ static void enableEditorKeysInMenus_(iBool enable) {
59/*----------------------------------------------------------------------------------------------*/ 59/*----------------------------------------------------------------------------------------------*/
60 60
61iDeclareType(InputLine) 61iDeclareType(InputLine)
62 62
63struct Impl_InputLine { 63struct Impl_InputLine {
64 iString text; 64 iString text;
65 iRanges range; /* byte offset inside the entire content; for marking */ 65 iRanges range; /* byte offset inside the entire content; for marking */
@@ -157,7 +157,7 @@ static void mergeLines_(const iArray *inputLines, iString *merged) {
157} 157}
158 158
159iDefineTypeConstruction(InputLine) 159iDefineTypeConstruction(InputLine)
160 160
161/*----------------------------------------------------------------------------------------------*/ 161/*----------------------------------------------------------------------------------------------*/
162 162
163iDeclareType(InputUndo) 163iDeclareType(InputUndo)
@@ -227,7 +227,7 @@ struct Impl_InputWidget {
227}; 227};
228 228
229iDefineObjectConstructionArgs(InputWidget, (size_t maxLen), maxLen) 229iDefineObjectConstructionArgs(InputWidget, (size_t maxLen), maxLen)
230 230
231static void updateMetrics_InputWidget_(iInputWidget *); 231static void updateMetrics_InputWidget_(iInputWidget *);
232 232
233static void restoreBackup_InputWidget_(iInputWidget *d) { 233static void restoreBackup_InputWidget_(iInputWidget *d) {
@@ -610,7 +610,7 @@ static uint32_t cursorTimer_(uint32_t interval, void *w) {
610 610
611static void startOrStopCursorTimer_InputWidget_(iInputWidget *d, iBool doStart) { 611static void startOrStopCursorTimer_InputWidget_(iInputWidget *d, iBool doStart) {
612 if (doStart && !d->timer) { 612 if (doStart && !d->timer) {
613 d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d); 613 d->timer = SDL_AddTimer(refreshInterval_InputWidget_, cursorTimer_, d);
614 } 614 }
615 else if (!doStart && d->timer) { 615 else if (!doStart && d->timer) {
616 SDL_RemoveTimer(d->timer); 616 SDL_RemoveTimer(d->timer);
@@ -679,7 +679,7 @@ void deinit_InputWidget(iInputWidget *d) {
679 delete_TextBuf(d->buffered); 679 delete_TextBuf(d->buffered);
680 clearUndo_InputWidget_(d); 680 clearUndo_InputWidget_(d);
681 deinit_Array(&d->undoStack); 681 deinit_Array(&d->undoStack);
682 startOrStopCursorTimer_InputWidget_(d, iFalse); 682 startOrStopCursorTimer_InputWidget_(d, iFalse);
683 deinit_String(&d->srcHint); 683 deinit_String(&d->srcHint);
684 deinit_String(&d->hint); 684 deinit_String(&d->hint);
685 deinit_String(&d->oldText); 685 deinit_String(&d->oldText);
@@ -708,7 +708,7 @@ static iBool popUndo_InputWidget_(iInputWidget *d) {
708 splitToLines_(&undo->text, &d->lines); 708 splitToLines_(&undo->text, &d->lines);
709 d->cursor = undo->cursor; 709 d->cursor = undo->cursor;
710 deinit_InputUndo_(undo); 710 deinit_InputUndo_(undo);
711 popBack_Array(&d->undoStack); 711 popBack_Array(&d->undoStack);
712 iZap(d->mark); 712 iZap(d->mark);
713 updateAllLinesAndResizeHeight_InputWidget_(d); 713 updateAllLinesAndResizeHeight_InputWidget_(d);
714 return iTrue; 714 return iTrue;
@@ -836,7 +836,7 @@ static iRangei visibleLineRange_InputWidget_(const iInputWidget *d) {
836static void updateBuffered_InputWidget_(iInputWidget *d) { 836static void updateBuffered_InputWidget_(iInputWidget *d) {
837 invalidateBuffered_InputWidget_(d); 837 invalidateBuffered_InputWidget_(d);
838 if (isHintVisible_InputWidget_(d)) { 838 if (isHintVisible_InputWidget_(d)) {
839 d->buffered = newRange_TextBuf(d->font, uiAnnotation_ColorId, range_String(&d->hint)); 839 d->buffered = newRange_TextBuf(d->font, uiAnnotation_ColorId, range_String(&d->hint));
840 } 840 }
841 else { 841 else {
842 /* Draw all the potentially visible lines to a buffer. */ 842 /* Draw all the potentially visible lines to a buffer. */
@@ -1073,7 +1073,7 @@ static void insertRange_InputWidget_(iInputWidget *d, iRangecc range) {
1073 } 1073 }
1074 textOfLinesWasChanged_InputWidget_(d, (iRangei){ firstModified, d->cursor.y + 1 }); 1074 textOfLinesWasChanged_InputWidget_(d, (iRangei){ firstModified, d->cursor.y + 1 });
1075 showCursor_InputWidget_(d); 1075 showCursor_InputWidget_(d);
1076 refresh_Widget(as_Widget(d)); 1076 refresh_Widget(as_Widget(d));
1077} 1077}
1078 1078
1079static void insertChar_InputWidget_(iInputWidget *d, iChar chr) { 1079static void insertChar_InputWidget_(iInputWidget *d, iChar chr) {
@@ -1110,7 +1110,7 @@ void setCursor_InputWidget(iInputWidget *d, iInt2 pos) {
1110static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) { 1110static iBool moveCursorByLine_InputWidget_(iInputWidget *d, int dir, int horiz) {
1111 const iInputLine *line = cursorLine_InputWidget_(d); 1111 const iInputLine *line = cursorLine_InputWidget_(d);
1112 iInt2 relCoord = relativeCursorCoord_InputWidget_(d); 1112 iInt2 relCoord = relativeCursorCoord_InputWidget_(d);
1113 int relLine = relCoord.y / lineHeight_Text(d->font); 1113 int relLine = relCoord.y / lineHeight_Text(d->font);
1114 if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) { 1114 if ((dir < 0 && relLine > 0) || (dir > 0 && relLine < numWrapLines_InputLine_(line) - 1)) {
1115 relCoord.y += dir * lineHeight_Text(d->font); 1115 relCoord.y += dir * lineHeight_Text(d->font);
1116 } 1116 }
@@ -1542,7 +1542,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) {
1542 else if (lineDelta > 0) { 1542 else if (lineDelta > 0) {
1543 lineDelta = iMin(lineDelta, 1543 lineDelta = iMin(lineDelta,
1544 lastLine_InputWidget_(d)->wrapLines.end - d->visWrapLines.end); 1544 lastLine_InputWidget_(d)->wrapLines.end - d->visWrapLines.end);
1545 if (!lineDelta) d->wheelAccum = 0; 1545 if (!lineDelta) d->wheelAccum = 0;
1546 } 1546 }
1547 d->wheelAccum -= lineDelta * lineHeight; 1547 d->wheelAccum -= lineDelta * lineHeight;
1548 d->visWrapLines.start += lineDelta; 1548 d->visWrapLines.start += lineDelta;
@@ -1925,7 +1925,7 @@ static void draw_InputWidget_(const iInputWidget *d) {
1925 } 1925 }
1926 iPaint p; 1926 iPaint p;
1927 init_Paint(&p); 1927 init_Paint(&p);
1928 /* `lines` is already up to date and ready for drawing. */ 1928 /* `lines` is already up to date and ready for drawing. */
1929 fillRect_Paint( 1929 fillRect_Paint(
1930 &p, bounds, isFocused ? uiInputBackgroundFocused_ColorId : uiInputBackground_ColorId); 1930 &p, bounds, isFocused ? uiInputBackgroundFocused_ColorId : uiInputBackground_ColorId);
1931 drawRectThickness_Paint(&p, 1931 drawRectThickness_Paint(&p,
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index ea76a835..b816b572 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -1523,7 +1523,9 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1523 return iTrue; 1523 return iTrue;
1524 } 1524 }
1525 } 1525 }
1526 if (hoverItem_ListWidget(d->list) || isVisible_Widget(d->menu)) { 1526 if (ev->type == SDL_MOUSEBUTTONDOWN &&
1527 contains_Widget(as_Widget(d->list), init_I2(ev->button.x, ev->button.y)) &&
1528 (hoverItem_ListWidget(d->list) || isVisible_Widget(d->menu))) {
1527 /* Update the menu before opening. */ 1529 /* Update the menu before opening. */
1528 if (d->mode == bookmarks_SidebarMode && !isVisible_Widget(d->menu)) { 1530 if (d->mode == bookmarks_SidebarMode && !isVisible_Widget(d->menu)) {
1529 /* Remote bookmarks have limitations. */ 1531 /* Remote bookmarks have limitations. */
diff --git a/src/ui/text.c b/src/ui/text.c
index c4596d1c..231281eb 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -195,7 +195,7 @@ static void init_Font(iFont *d, const iBlock *data, int height, float scale,
195 d->vertOffset = height * (1.0f - scale) / 2; 195 d->vertOffset = height * (1.0f - scale) / 2;
196 /* Custom tweaks. */ 196 /* Custom tweaks. */
197 if (data == &fontNotoSansSymbolsRegular_Embedded) { 197 if (data == &fontNotoSansSymbolsRegular_Embedded) {
198 d->vertOffset *= 1.2f; 198 d->vertOffset *= 1.2f;
199 } 199 }
200 else if (data == &fontNotoSansSymbols2Regular_Embedded) { 200 else if (data == &fontNotoSansSymbols2Regular_Embedded) {
201 d->vertOffset /= 2; 201 d->vertOffset /= 2;
@@ -1434,7 +1434,6 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1434 iBool isFirst = iTrue; 1434 iBool isFirst = iTrue;
1435 const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2()); 1435 const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2());
1436 const iBool checkHitChar = wrap && wrap->hitChar; 1436 const iBool checkHitChar = wrap && wrap->hitChar;
1437 iBool wasCharHit = iFalse;
1438 while (!isEmpty_Range(&wrapRuns)) { 1437 while (!isEmpty_Range(&wrapRuns)) {
1439 if (isFirst) { 1438 if (isFirst) {
1440 isFirst = iFalse; 1439 isFirst = iFalse;
@@ -1448,17 +1447,16 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1448 if (wrap && (wrap->maxWidth > 0 || checkHitPoint)) { 1447 if (wrap && (wrap->maxWidth > 0 || checkHitPoint)) {
1449 const iBool isHitPointOnThisLine = (checkHitPoint && wrap->hitPoint.y >= orig.y + yCursor && 1448 const iBool isHitPointOnThisLine = (checkHitPoint && wrap->hitPoint.y >= orig.y + yCursor &&
1450 wrap->hitPoint.y < orig.y + yCursor + d->height); 1449 wrap->hitPoint.y < orig.y + yCursor + d->height);
1450 iBool wasCharHit = iFalse; /* on this line */
1451 float breakAdvance = -1.0f; 1451 float breakAdvance = -1.0f;
1452 iAssert(wrapPosRange.end == textLen); 1452 iAssert(wrapPosRange.end == textLen);
1453 /* Determine ends of wrapRuns and wrapVisRange. */ 1453 /* Determine ends of wrapRuns and wrapVisRange. */
1454 for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) { 1454 for (size_t runIndex = wrapRuns.start; runIndex < wrapRuns.end; runIndex++) {
1455 const iAttributedRun *run = at_Array(&attrText.runs, runIndex); 1455 const iAttributedRun *run = at_Array(&attrText.runs, runIndex);
1456 if (run->flags.isLineBreak) { 1456 if (run->flags.isLineBreak) {
1457 if (checkHitChar && !wasCharHit) { 1457 if (checkHitChar &&
1458 if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) { 1458 wrap->hitChar == sourcePtr_AttributedText_(&attrText, run->logical.start)) {
1459 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); 1459 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor);
1460 wasCharHit = iTrue;
1461 }
1462 } 1460 }
1463 wrapPosRange.end = run->logical.start; 1461 wrapPosRange.end = run->logical.start;
1464 wrapResumePos = run->logical.end; 1462 wrapResumePos = run->logical.end;
@@ -1482,11 +1480,10 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1482 if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) { 1480 if (logPos < wrapPosRange.start || logPos >= wrapPosRange.end) {
1483 continue; 1481 continue;
1484 } 1482 }
1485 if (checkHitChar && !wasCharHit) { 1483 if (checkHitChar && !wasCharHit &&
1486 if (wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) { 1484 wrap->hitChar == sourcePtr_AttributedText_(&attrText, logPos)) {
1487 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor); 1485 wrap->hitAdvance_out = init_I2(wrapAdvance, yCursor);
1488 wasCharHit = iTrue; 1486 wasCharHit = iTrue; /* variation selectors etc. have matching cluster */
1489 }
1490 } 1487 }
1491 /* Check if the hit point is on the left side of this line. */ 1488 /* Check if the hit point is on the left side of this line. */
1492 if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) { 1489 if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) {
@@ -1873,7 +1870,7 @@ static void drawBoundedN_Text_(int fontId, iInt2 pos, int xposBound, int color,
1873 (color & fillBackground_ColorId ? fillBackground_RunMode : 0) | 1870 (color & fillBackground_ColorId ? fillBackground_RunMode : 0) |
1874 runFlagsFromId_(fontId), 1871 runFlagsFromId_(fontId),
1875 .text = text, 1872 .text = text,
1876 .maxLen = maxLen, 1873 .maxLen = maxLen,
1877 .pos = pos, 1874 .pos = pos,
1878// .xposLayoutBound = xposBound, 1875// .xposLayoutBound = xposBound,
1879 .color = color & mask_ColorId, 1876 .color = color & mask_ColorId,