diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/banner.c | 3 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 39 | ||||
-rw-r--r-- | src/ui/linkinfo.c | 4 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 54 | ||||
-rw-r--r-- | src/ui/text.c | 40 | ||||
-rw-r--r-- | src/ui/text.h | 2 | ||||
-rw-r--r-- | src/ui/util.c | 111 | ||||
-rw-r--r-- | src/ui/util.h | 14 |
8 files changed, 207 insertions, 60 deletions
diff --git a/src/ui/banner.c b/src/ui/banner.c index 11ae1574..79d70039 100644 --- a/src/ui/banner.c +++ b/src/ui/banner.c | |||
@@ -327,7 +327,8 @@ iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) { | |||
327 | else { | 327 | else { |
328 | switch (item->code) { | 328 | switch (item->code) { |
329 | case missingGlyphs_GmStatusCode: | 329 | case missingGlyphs_GmStatusCode: |
330 | postCommandf_App("open newtab:1 url:about:fonts"); | 330 | //postCommandf_App("open newtab:1 url:about:fonts"); |
331 | makeGlyphFinder_Widget(); | ||
331 | break; | 332 | break; |
332 | case ansiEscapes_GmStatusCode: | 333 | case ansiEscapes_GmStatusCode: |
333 | makeQuestion_Widget( | 334 | makeQuestion_Widget( |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index a52e99af..7d9ac154 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -358,6 +358,7 @@ static void updateSideIconBuf_DocumentWidget_ (const iDocumentWidget *d); | |||
358 | static void prerender_DocumentWidget_ (iAny *); | 358 | static void prerender_DocumentWidget_ (iAny *); |
359 | static void scrollBegan_DocumentWidget_ (iAnyObject *, int, uint32_t); | 359 | static void scrollBegan_DocumentWidget_ (iAnyObject *, int, uint32_t); |
360 | static void refreshWhileScrolling_DocumentWidget_ (iAny *); | 360 | static void refreshWhileScrolling_DocumentWidget_ (iAny *); |
361 | static iBool requestMedia_DocumentWidget_ (iDocumentWidget *d, iGmLinkId linkId, iBool enableFilters); | ||
361 | 362 | ||
362 | /* TODO: The following methods are called from DocumentView, which goes the wrong way. */ | 363 | /* TODO: The following methods are called from DocumentView, which goes the wrong way. */ |
363 | 364 | ||
@@ -1824,7 +1825,7 @@ static void draw_DocumentView_(const iDocumentView *d) { | |||
1824 | } | 1825 | } |
1825 | if (d->drawBufs->flags & updateSideBuf_DrawBufsFlag) { | 1826 | if (d->drawBufs->flags & updateSideBuf_DrawBufsFlag) { |
1826 | updateSideIconBuf_DocumentView_(d); | 1827 | updateSideIconBuf_DocumentView_(d); |
1827 | } | 1828 | } |
1828 | const iRect docBounds = documentBounds_DocumentView_(d); | 1829 | const iRect docBounds = documentBounds_DocumentView_(d); |
1829 | const iRangei vis = visibleRange_DocumentView_(d); | 1830 | const iRangei vis = visibleRange_DocumentView_(d); |
1830 | iDrawContext ctx = { | 1831 | iDrawContext ctx = { |
@@ -2410,6 +2411,20 @@ static const char *zipPageHeading_(const iRangecc mime) { | |||
2410 | 2411 | ||
2411 | static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool isCached) { | 2412 | static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool isCached) { |
2412 | iWidget *w = as_Widget(d); | 2413 | iWidget *w = as_Widget(d); |
2414 | /* Embedded images in data links can be shown immediately as they are already fetched | ||
2415 | data that is part of the document. */ | ||
2416 | if (prefs_App()->openDataUrlImagesOnLoad) { | ||
2417 | iGmDocument *doc = d->view.doc; | ||
2418 | for (size_t linkId = 1; ; linkId++) { | ||
2419 | const int linkFlags = linkFlags_GmDocument(doc, linkId); | ||
2420 | const iString *linkUrl = linkUrl_GmDocument(doc, linkId); | ||
2421 | if (!linkUrl) break; | ||
2422 | if (scheme_GmLinkFlag(linkFlags) == data_GmLinkScheme && | ||
2423 | (linkFlags & imageFileExtension_GmLinkFlag)) { | ||
2424 | requestMedia_DocumentWidget_(d, linkId, 0); | ||
2425 | } | ||
2426 | } | ||
2427 | } | ||
2413 | /* Gempub page behavior and footer actions. */ { | 2428 | /* Gempub page behavior and footer actions. */ { |
2414 | /* TODO: move this to gempub.c */ | 2429 | /* TODO: move this to gempub.c */ |
2415 | delete_Gempub(d->sourceGempub); | 2430 | delete_Gempub(d->sourceGempub); |
@@ -2681,7 +2696,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
2681 | if (loadArchive_FontPack(fp, zip)) { | 2696 | if (loadArchive_FontPack(fp, zip)) { |
2682 | appendFormat_String(&str, "# " fontpack_Icon "%s\n%s", | 2697 | appendFormat_String(&str, "# " fontpack_Icon "%s\n%s", |
2683 | cstr_String(id_FontPack(fp).id), | 2698 | cstr_String(id_FontPack(fp).id), |
2684 | cstrCollect_String(infoText_FontPack(fp))); | 2699 | cstrCollect_String(infoText_FontPack(fp, iTrue))); |
2685 | } | 2700 | } |
2686 | appendCStr_String(&str, "\n"); | 2701 | appendCStr_String(&str, "\n"); |
2687 | appendCStr_String(&str, cstr_Lang("fontpack.help")); | 2702 | appendCStr_String(&str, cstr_Lang("fontpack.help")); |
@@ -3921,12 +3936,12 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
3921 | const char *unchecked = red_ColorEscape "\u2610"; | 3936 | const char *unchecked = red_ColorEscape "\u2610"; |
3922 | const char *checked = green_ColorEscape "\u2611"; | 3937 | const char *checked = green_ColorEscape "\u2611"; |
3923 | const iBool haveFingerprint = (d->certFlags & haveFingerprint_GmCertFlag) != 0; | 3938 | const iBool haveFingerprint = (d->certFlags & haveFingerprint_GmCertFlag) != 0; |
3924 | const int requiredForTrust = (available_GmCertFlag | haveFingerprint_GmCertFlag | | 3939 | const int requiredForTrust = |
3925 | timeVerified_GmCertFlag); | 3940 | (available_GmCertFlag | haveFingerprint_GmCertFlag | timeVerified_GmCertFlag); |
3926 | const iBool canTrust = ~d->certFlags & trusted_GmCertFlag && | 3941 | const iBool canTrust = ~d->certFlags & trusted_GmCertFlag && |
3927 | ((d->certFlags & requiredForTrust) == requiredForTrust); | 3942 | ((d->certFlags & requiredForTrust) == requiredForTrust); |
3928 | const iRecentUrl *recent = constMostRecentUrl_History(d->mod.history); | 3943 | const iRecentUrl *recent = constMostRecentUrl_History(d->mod.history); |
3929 | const iString *meta = &d->sourceMime; | 3944 | const iString *meta = &d->sourceMime; |
3930 | if (recent && recent->cachedResponse) { | 3945 | if (recent && recent->cachedResponse) { |
3931 | meta = &recent->cachedResponse->meta; | 3946 | meta = &recent->cachedResponse->meta; |
3932 | } | 3947 | } |
@@ -3991,6 +4006,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
3991 | if (haveFingerprint) { | 4006 | if (haveFingerprint) { |
3992 | pushBack_Array(items, &(iMenuItem){ "${dlg.cert.fingerprint}", 0, 0, "server.copycert" }); | 4007 | pushBack_Array(items, &(iMenuItem){ "${dlg.cert.fingerprint}", 0, 0, "server.copycert" }); |
3993 | } | 4008 | } |
4009 | const iRangecc root = urlRoot_String(d->mod.url); | ||
4010 | if (!isEmpty_Range(&root)) { | ||
4011 | pushBack_Array(items, &(iMenuItem){ "${pageinfo.settings}", 0, 0, "document.sitespec" }); | ||
4012 | } | ||
3994 | if (!isEmpty_Array(items)) { | 4013 | if (!isEmpty_Array(items)) { |
3995 | pushBack_Array(items, &(iMenuItem){ "---", 0, 0, 0 }); | 4014 | pushBack_Array(items, &(iMenuItem){ "---", 0, 0, 0 }); |
3996 | } | 4015 | } |
@@ -4922,7 +4941,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
4922 | for (size_t i = 0; i < 64; ++i) { | 4941 | for (size_t i = 0; i < 64; ++i) { |
4923 | setByte_Block(seed, i, iRandom(0, 256)); | 4942 | setByte_Block(seed, i, iRandom(0, 256)); |
4924 | } | 4943 | } |
4925 | setThemeSeed_GmDocument(view->doc, seed); | 4944 | setThemeSeed_GmDocument(view->doc, seed, NULL); |
4926 | delete_Block(seed); | 4945 | delete_Block(seed); |
4927 | invalidate_DocumentWidget_(d); | 4946 | invalidate_DocumentWidget_(d); |
4928 | refresh_Widget(w); | 4947 | refresh_Widget(w); |
@@ -5545,10 +5564,10 @@ static void prerender_DocumentWidget_(iAny *context) { | |||
5545 | } | 5564 | } |
5546 | const iDocumentWidget *d = context; | 5565 | const iDocumentWidget *d = context; |
5547 | iDrawContext ctx = { | 5566 | iDrawContext ctx = { |
5548 | .view = &d->view, | 5567 | .view = &d->view, |
5549 | .docBounds = documentBounds_DocumentView_(&d->view), | 5568 | .docBounds = documentBounds_DocumentView_(&d->view), |
5550 | .vis = visibleRange_DocumentView_(&d->view), | 5569 | .vis = visibleRange_DocumentView_(&d->view), |
5551 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0 | 5570 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0 |
5552 | }; | 5571 | }; |
5553 | // printf("%u prerendering\n", SDL_GetTicks()); | 5572 | // printf("%u prerendering\n", SDL_GetTicks()); |
5554 | if (d->view.visBuf->buffers[0].texture) { | 5573 | if (d->view.visBuf->buffers[0].texture) { |
diff --git a/src/ui/linkinfo.c b/src/ui/linkinfo.c index 36ab00c8..15aea16e 100644 --- a/src/ui/linkinfo.c +++ b/src/ui/linkinfo.c | |||
@@ -91,6 +91,10 @@ void infoText_LinkInfo(const iGmDocument *doc, iGmLinkId linkId, iString *text_o | |||
91 | appendCStr_String(text_out, "\x1b[0m"); | 91 | appendCStr_String(text_out, "\x1b[0m"); |
92 | appendRange_String(text_out, (iRangecc){ parts.path.start, constEnd_String(url) }); | 92 | appendRange_String(text_out, (iRangecc){ parts.path.start, constEnd_String(url) }); |
93 | } | 93 | } |
94 | else if (scheme == data_GmLinkScheme) { | ||
95 | appendCStr_String(text_out, paperclip_Icon " "); | ||
96 | append_String(text_out, prettyDataUrl_String(url, none_ColorId)); | ||
97 | } | ||
94 | else if (scheme != gemini_GmLinkScheme) { | 98 | else if (scheme != gemini_GmLinkScheme) { |
95 | const size_t maxDispLen = 300; | 99 | const size_t maxDispLen = 300; |
96 | appendCStr_String(text_out, scheme == file_GmLinkScheme ? "" : globe_Icon " "); | 100 | appendCStr_String(text_out, scheme == file_GmLinkScheme ? "" : globe_Icon " "); |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index da377ac2..73023a4f 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -2156,28 +2156,38 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect, | |||
2156 | : uiTextDim_ColorId; | 2156 | : uiTextDim_ColorId; |
2157 | iUrl parts; | 2157 | iUrl parts; |
2158 | init_Url(&parts, &d->label); | 2158 | init_Url(&parts, &d->label); |
2159 | const iBool isAbout = equalCase_Rangecc(parts.scheme, "about"); | 2159 | const iBool isAbout = equalCase_Rangecc(parts.scheme, "about"); |
2160 | const iBool isGemini = equalCase_Rangecc(parts.scheme, "gemini"); | 2160 | const iBool isGemini = equalCase_Rangecc(parts.scheme, "gemini"); |
2161 | draw_Text(font, | 2161 | const iBool isData = equalCase_Rangecc(parts.scheme, "data"); |
2162 | add_I2(topLeft_Rect(itemRect), | 2162 | const int queryColor = isPressing ? uiTextPressed_ColorId |
2163 | init_I2(3 * gap_UI, (itemHeight - lineHeight_Text(font)) / 2)), | 2163 | : isHover ? uiText_ColorId |
2164 | fg, | 2164 | : uiAnnotation_ColorId; |
2165 | "%s%s%s%s%s%s%s%s", | 2165 | const iInt2 textPos = |
2166 | isGemini ? "" : cstr_Rangecc(parts.scheme), | 2166 | add_I2(topLeft_Rect(itemRect), |
2167 | isGemini ? "" | 2167 | init_I2(3 * gap_UI, (itemHeight - lineHeight_Text(font)) / 2)); |
2168 | : isAbout ? ":" | 2168 | if (isData) { |
2169 | : "://", | 2169 | drawRange_Text( |
2170 | escape_Color(isHover ? (isPressing ? uiTextPressed_ColorId | 2170 | font, textPos, fg, range_String(prettyDataUrl_String(&d->label, queryColor))); |
2171 | : uiTextFramelessHover_ColorId) | 2171 | } |
2172 | : uiTextStrong_ColorId), | 2172 | else { |
2173 | cstr_Rangecc(parts.host), | 2173 | draw_Text( |
2174 | escape_Color(fg), | 2174 | font, |
2175 | cstr_Rangecc(parts.path), | 2175 | textPos, |
2176 | !isEmpty_Range(&parts.query) ? escape_Color(isPressing ? uiTextPressed_ColorId | 2176 | fg, |
2177 | : isHover ? uiText_ColorId | 2177 | "%s%s%s%s%s%s%s%s", |
2178 | : uiAnnotation_ColorId) | 2178 | isGemini ? "" : cstr_Rangecc(parts.scheme), |
2179 | : "", | 2179 | isGemini ? "" |
2180 | !isEmpty_Range(&parts.query) ? cstr_Rangecc(parts.query) : ""); | 2180 | : isAbout ? ":" |
2181 | : "://", | ||
2182 | escape_Color(isHover ? (isPressing ? uiTextPressed_ColorId | ||
2183 | : uiTextFramelessHover_ColorId) | ||
2184 | : uiTextStrong_ColorId), | ||
2185 | cstr_Rangecc(parts.host), | ||
2186 | escape_Color(fg), | ||
2187 | cstr_Rangecc(parts.path), | ||
2188 | !isEmpty_Range(&parts.query) ? escape_Color(queryColor) : "", | ||
2189 | !isEmpty_Range(&parts.query) ? cstr_Rangecc(parts.query) : ""); | ||
2190 | } | ||
2181 | } | 2191 | } |
2182 | iEndCollect(); | 2192 | iEndCollect(); |
2183 | } | 2193 | } |
diff --git a/src/ui/text.c b/src/ui/text.c index c19aed2f..51531057 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -258,8 +258,6 @@ static int cmp_PrioMapItem_(const void *a, const void *b) { | |||
258 | } | 258 | } |
259 | 259 | ||
260 | struct Impl_Text { | 260 | struct Impl_Text { |
261 | // enum iTextFont contentFont; | ||
262 | // enum iTextFont headingFont; | ||
263 | float contentFontSize; | 261 | float contentFontSize; |
264 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ | 262 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ |
265 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ | 263 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ |
@@ -276,7 +274,8 @@ struct Impl_Text { | |||
276 | int ansiFlags; | 274 | int ansiFlags; |
277 | int baseFontId; /* base attributes (for restoring via escapes) */ | 275 | int baseFontId; /* base attributes (for restoring via escapes) */ |
278 | int baseFgColorId; | 276 | int baseFgColorId; |
279 | iBool missingGlyphs; /* true if a glyph couldn't be found */ | 277 | iBool missingGlyphs; /* true if a glyph couldn't be found */ |
278 | iChar missingChars[20]; /* rotating buffer of the latest missing characters */ | ||
280 | }; | 279 | }; |
281 | 280 | ||
282 | iDefineTypeConstructionArgs(Text, (SDL_Renderer *render), render) | 281 | iDefineTypeConstructionArgs(Text, (SDL_Renderer *render), render) |
@@ -357,6 +356,8 @@ static void initFonts_Text_(iText *d) { | |||
357 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); | 356 | printf("[Text] %zu font variants ready\n", size_Array(&d->fonts)); |
358 | #endif | 357 | #endif |
359 | gap_Text = iRound(gap_UI * d->contentFontSize); | 358 | gap_Text = iRound(gap_UI * d->contentFontSize); |
359 | // d->missingGlyphs = iFalse; | ||
360 | // iZap(d->missingChars); | ||
360 | } | 361 | } |
361 | 362 | ||
362 | static void deinitFonts_Text_(iText *d) { | 363 | static void deinitFonts_Text_(iText *d) { |
@@ -424,6 +425,7 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
424 | d->baseFontId = -1; | 425 | d->baseFontId = -1; |
425 | d->baseFgColorId = -1; | 426 | d->baseFgColorId = -1; |
426 | d->missingGlyphs = iFalse; | 427 | d->missingGlyphs = iFalse; |
428 | iZap(d->missingChars); | ||
427 | d->render = render; | 429 | d->render = render; |
428 | /* A grayscale palette for rasterized glyphs. */ { | 430 | /* A grayscale palette for rasterized glyphs. */ { |
429 | SDL_Color colors[256]; | 431 | SDL_Color colors[256]; |
@@ -610,8 +612,23 @@ iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { | |||
610 | } | 612 | } |
611 | } | 613 | } |
612 | if (!*glyphIndex) { | 614 | if (!*glyphIndex) { |
613 | activeText_->missingGlyphs = iTrue; | 615 | fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int) ch); fflush(stderr); |
614 | fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int)ch); fflush(stderr); | 616 | iText *tx = activeText_; |
617 | tx->missingGlyphs = iTrue; | ||
618 | /* Remember a few of the latest missing characters. */ | ||
619 | iBool gotIt = iFalse; | ||
620 | for (size_t i = 0; i < iElemCount(tx->missingChars); i++) { | ||
621 | if (tx->missingChars[i] == ch) { | ||
622 | gotIt = iTrue; | ||
623 | break; | ||
624 | } | ||
625 | } | ||
626 | if (!gotIt) { | ||
627 | memmove(tx->missingChars + 1, | ||
628 | tx->missingChars, | ||
629 | sizeof(tx->missingChars) - sizeof(tx->missingChars[0])); | ||
630 | tx->missingChars[0] = ch; | ||
631 | } | ||
615 | } | 632 | } |
616 | return d; | 633 | return d; |
617 | } | 634 | } |
@@ -2250,6 +2267,19 @@ iBool checkMissing_Text(void) { | |||
2250 | return missing; | 2267 | return missing; |
2251 | } | 2268 | } |
2252 | 2269 | ||
2270 | iChar missing_Text(size_t index) { | ||
2271 | const iText *d = activeText_; | ||
2272 | if (index >= iElemCount(d->missingChars)) { | ||
2273 | return 0; | ||
2274 | } | ||
2275 | return d->missingChars[index]; | ||
2276 | } | ||
2277 | |||
2278 | void resetMissing_Text(iText *d) { | ||
2279 | d->missingGlyphs = iFalse; | ||
2280 | iZap(d->missingChars); | ||
2281 | } | ||
2282 | |||
2253 | SDL_Texture *glyphCache_Text(void) { | 2283 | SDL_Texture *glyphCache_Text(void) { |
2254 | return activeText_->cache; | 2284 | return activeText_->cache; |
2255 | } | 2285 | } |
diff --git a/src/ui/text.h b/src/ui/text.h index b952df84..e741880d 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -227,6 +227,8 @@ struct Impl_WrapText { | |||
227 | iTextMetrics measure_WrapText (iWrapText *, int fontId); | 227 | iTextMetrics measure_WrapText (iWrapText *, int fontId); |
228 | iTextMetrics draw_WrapText (iWrapText *, int fontId, iInt2 pos, int color); | 228 | iTextMetrics draw_WrapText (iWrapText *, int fontId, iInt2 pos, int color); |
229 | 229 | ||
230 | iChar missing_Text (size_t index); | ||
231 | void resetMissing_Text (iText *); | ||
230 | iBool checkMissing_Text (void); /* returns the flag, and clears it */ | 232 | iBool checkMissing_Text (void); /* returns the flag, and clears it */ |
231 | SDL_Texture * glyphCache_Text (void); | 233 | SDL_Texture * glyphCache_Text (void); |
232 | 234 | ||
diff --git a/src/ui/util.c b/src/ui/util.c index 5dd8a0bd..54715121 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -903,6 +903,7 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | |||
903 | #else | 903 | #else |
904 | /* Non-native custom popup menu. This may still be displayed inside a separate window. */ | 904 | /* Non-native custom popup menu. This may still be displayed inside a separate window. */ |
905 | setDrawBufferEnabled_Widget(menu, iTrue); | 905 | setDrawBufferEnabled_Widget(menu, iTrue); |
906 | setFrameColor_Widget(menu, uiSeparator_ColorId); | ||
906 | setBackgroundColor_Widget(menu, uiBackgroundMenu_ColorId); | 907 | setBackgroundColor_Widget(menu, uiBackgroundMenu_ColorId); |
907 | if (deviceType_App() != desktop_AppDeviceType) { | 908 | if (deviceType_App() != desktop_AppDeviceType) { |
908 | setPadding1_Widget(menu, 2 * gap_UI); | 909 | setPadding1_Widget(menu, 2 * gap_UI); |
@@ -1084,12 +1085,12 @@ void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, int menuOpenFlags) { | |||
1084 | setFlags_Widget(d, hidden_WidgetFlag, iFalse); | 1085 | setFlags_Widget(d, hidden_WidgetFlag, iFalse); |
1085 | setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); | 1086 | setFlags_Widget(d, commandOnMouseMiss_WidgetFlag, iTrue); |
1086 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); | 1087 | setFlags_Widget(findChild_Widget(d, "menu.cancel"), disabled_WidgetFlag, iFalse); |
1087 | if (!isPortraitPhone) { | 1088 | // if (!isPortraitPhone) { |
1088 | setFrameColor_Widget(d, uiBackgroundSelected_ColorId); | 1089 | // setFrameColor_Widget(d, uiSeparator_ColorId); |
1089 | } | 1090 | // } |
1090 | else { | 1091 | // else { |
1091 | setFrameColor_Widget(d, none_ColorId); | 1092 | // setFrameColor_Widget(d, none_ColorId); |
1092 | } | 1093 | // } |
1093 | arrange_Widget(d); /* need to know the height */ | 1094 | arrange_Widget(d); /* need to know the height */ |
1094 | iBool allowOverflow = iFalse; | 1095 | iBool allowOverflow = iFalse; |
1095 | /* A vertical offset determined by a possible selected label in the menu. */ | 1096 | /* A vertical offset determined by a possible selected label in the menu. */ |
@@ -1327,6 +1328,7 @@ int checkContextMenu_Widget(iWidget *menu, const SDL_Event *ev) { | |||
1327 | iLabelWidget *makeMenuButton_LabelWidget(const char *label, const iMenuItem *items, size_t n) { | 1328 | iLabelWidget *makeMenuButton_LabelWidget(const char *label, const iMenuItem *items, size_t n) { |
1328 | iLabelWidget *button = new_LabelWidget(label, "menu.open"); | 1329 | iLabelWidget *button = new_LabelWidget(label, "menu.open"); |
1329 | iWidget *menu = makeMenu_Widget(as_Widget(button), items, n); | 1330 | iWidget *menu = makeMenu_Widget(as_Widget(button), items, n); |
1331 | setFrameColor_Widget(menu, uiBackgroundSelected_ColorId); | ||
1330 | setId_Widget(menu, "menu"); | 1332 | setId_Widget(menu, "menu"); |
1331 | return button; | 1333 | return button; |
1332 | } | 1334 | } |
@@ -2495,6 +2497,7 @@ iWidget *makePreferences_Widget(void) { | |||
2495 | { "input id:prefs.searchurl url:1 noheading:1" }, | 2497 | { "input id:prefs.searchurl url:1 noheading:1" }, |
2496 | { "padding" }, | 2498 | { "padding" }, |
2497 | { "toggle id:prefs.bookmarks.addbottom" }, | 2499 | { "toggle id:prefs.bookmarks.addbottom" }, |
2500 | { "toggle id:prefs.dataurl.openimages" }, | ||
2498 | { "toggle id:prefs.archive.openindex" }, | 2501 | { "toggle id:prefs.archive.openindex" }, |
2499 | { "radio device:1 id:prefs.pinsplit", 0, 0, (const void *) pinSplitItems }, | 2502 | { "radio device:1 id:prefs.pinsplit", 0, 0, (const void *) pinSplitItems }, |
2500 | { "padding" }, | 2503 | { "padding" }, |
@@ -2567,6 +2570,7 @@ iWidget *makePreferences_Widget(void) { | |||
2567 | const iMenuItem networkPanelItems[] = { | 2570 | const iMenuItem networkPanelItems[] = { |
2568 | { "title id:heading.prefs.network" }, | 2571 | { "title id:heading.prefs.network" }, |
2569 | { "toggle id:prefs.decodeurls" }, | 2572 | { "toggle id:prefs.decodeurls" }, |
2573 | { "input id:prefs.urlsize maxlen:10 selectall:1" }, | ||
2570 | { "padding" }, | 2574 | { "padding" }, |
2571 | { "input id:prefs.cachesize maxlen:4 selectall:1 unit:mb" }, | 2575 | { "input id:prefs.cachesize maxlen:4 selectall:1 unit:mb" }, |
2572 | { "input id:prefs.memorysize maxlen:4 selectall:1 unit:mb" }, | 2576 | { "input id:prefs.memorysize maxlen:4 selectall:1 unit:mb" }, |
@@ -2640,8 +2644,9 @@ iWidget *makePreferences_Widget(void) { | |||
2640 | setUrlContent_InputWidget(searchUrl, iTrue); | 2644 | setUrlContent_InputWidget(searchUrl, iTrue); |
2641 | addDialogPadding_(headings, values); | 2645 | addDialogPadding_(headings, values); |
2642 | addDialogToggle_(headings, values, "${prefs.hoverlink}", "prefs.hoverlink"); | 2646 | addDialogToggle_(headings, values, "${prefs.hoverlink}", "prefs.hoverlink"); |
2643 | addDialogToggle_(headings, values, "${prefs.bookmarks.addbottom}", "prefs.bookmarks.addbottom"); | 2647 | addDialogToggle_(headings, values, "${prefs.dataurl.openimages}", "prefs.dataurl.openimages"); |
2644 | addDialogToggle_(headings, values, "${prefs.archive.openindex}", "prefs.archive.openindex"); | 2648 | addDialogToggle_(headings, values, "${prefs.archive.openindex}", "prefs.archive.openindex"); |
2649 | addDialogToggle_(headings, values, "${prefs.bookmarks.addbottom}", "prefs.bookmarks.addbottom"); | ||
2645 | if (deviceType_App() != phone_AppDeviceType) { | 2650 | if (deviceType_App() != phone_AppDeviceType) { |
2646 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}"))); | 2651 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.pinsplit}"))); |
2647 | iWidget *pinSplit = new_Widget(); | 2652 | iWidget *pinSplit = new_Widget(); |
@@ -2900,6 +2905,7 @@ iWidget *makePreferences_Widget(void) { | |||
2900 | appendTwoColumnTabPage_Widget(tabs, "${heading.prefs.network}", '6', &headings, &values); | 2905 | appendTwoColumnTabPage_Widget(tabs, "${heading.prefs.network}", '6', &headings, &values); |
2901 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.decodeurls}"))); | 2906 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.decodeurls}"))); |
2902 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.decodeurls"))); | 2907 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.decodeurls"))); |
2908 | addPrefsInputWithHeading_(headings, values, "prefs.urlsize", iClob(new_InputWidget(10))); | ||
2903 | /* Cache size. */ { | 2909 | /* Cache size. */ { |
2904 | iInputWidget *cache = new_InputWidget(4); | 2910 | iInputWidget *cache = new_InputWidget(4); |
2905 | setSelectAllOnFocus_InputWidget(cache, iTrue); | 2911 | setSelectAllOnFocus_InputWidget(cache, iTrue); |
@@ -3163,15 +3169,14 @@ static iBool handleFeedSettingCommands_(iWidget *dlg, const char *cmd) { | |||
3163 | } | 3169 | } |
3164 | 3170 | ||
3165 | iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { | 3171 | iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { |
3166 | const char *headingText = bookmarkId ? uiHeading_ColorEscape "${heading.feedcfg}" | 3172 | iWidget *dlg; |
3167 | : uiHeading_ColorEscape "${heading.subscribe}"; | 3173 | const char *headingText = bookmarkId ? "${heading.feedcfg}" : "${heading.subscribe}"; |
3168 | const iMenuItem actions[] = { { "${cancel}" }, | 3174 | const iMenuItem actions[] = { { "${cancel}" }, |
3169 | { bookmarkId ? uiTextCaution_ColorEscape "${dlg.feed.save}" | 3175 | { bookmarkId ? uiTextCaution_ColorEscape "${dlg.feed.save}" |
3170 | : uiTextCaution_ColorEscape "${dlg.feed.sub}", | 3176 | : uiTextCaution_ColorEscape "${dlg.feed.sub}", |
3171 | SDLK_RETURN, | 3177 | SDLK_RETURN, |
3172 | KMOD_PRIMARY, | 3178 | KMOD_PRIMARY, |
3173 | format_CStr("feedcfg.accept bmid:%d", bookmarkId) } }; | 3179 | format_CStr("feedcfg.accept bmid:%d", bookmarkId) } }; |
3174 | iWidget *dlg; | ||
3175 | if (isUsingPanelLayout_Mobile()) { | 3180 | if (isUsingPanelLayout_Mobile()) { |
3176 | const iMenuItem typeItems[] = { | 3181 | const iMenuItem typeItems[] = { |
3177 | { "button id:feedcfg.type.gemini label:dlg.feed.type.gemini", 0, 0, "feedcfg.type arg:0" }, | 3182 | { "button id:feedcfg.type.gemini label:dlg.feed.type.gemini", 0, 0, "feedcfg.type arg:0" }, |
@@ -3228,6 +3233,32 @@ iWidget *makeFeedSettings_Widget(uint32_t bookmarkId) { | |||
3228 | return dlg; | 3233 | return dlg; |
3229 | } | 3234 | } |
3230 | 3235 | ||
3236 | iWidget *makeSiteSpecificSettings_Widget(const iString *url) { | ||
3237 | iWidget *dlg; | ||
3238 | const iMenuItem actions[] = { | ||
3239 | { "${cancel}" }, { "${sitespec.accept}", SDLK_RETURN, KMOD_PRIMARY, "sitespec.accept" } | ||
3240 | }; | ||
3241 | if (isUsingPanelLayout_Mobile()) { | ||
3242 | iAssert(iFalse); | ||
3243 | } | ||
3244 | else { | ||
3245 | iWidget *headings, *values; | ||
3246 | dlg = makeSheet_Widget("sitespec"); | ||
3247 | addDialogTitle_(dlg, "${heading.sitespec}", "heading.sitespec"); | ||
3248 | addChild_Widget(dlg, iClob(makeTwoColumns_Widget(&headings, &values))); | ||
3249 | addDialogToggle_(headings, values, "${sitespec.ansi}", "sitespec.ansi"); | ||
3250 | iInputWidget *palInput = new_InputWidget(0); | ||
3251 | addPrefsInputWithHeading_(headings, values, "sitespec.palette", iClob(palInput)); | ||
3252 | as_Widget(palInput)->rect.size.x = 80 * gap_UI; | ||
3253 | addChild_Widget(dlg, iClob(makeDialogButtons_Widget(actions, iElemCount(actions)))); | ||
3254 | } | ||
3255 | /* Initialize. */ { | ||
3256 | const iRangecc root = urlRoot_String(url); | ||
3257 | |||
3258 | } | ||
3259 | return dlg; | ||
3260 | } | ||
3261 | |||
3231 | iWidget *makeIdentityCreation_Widget(void) { | 3262 | iWidget *makeIdentityCreation_Widget(void) { |
3232 | const iMenuItem actions[] = { { "${dlg.newident.more}", 0, 0, "ident.showmore" }, | 3263 | const iMenuItem actions[] = { { "${dlg.newident.more}", 0, 0, "ident.showmore" }, |
3233 | { "---" }, | 3264 | { "---" }, |
@@ -3451,6 +3482,54 @@ iWidget *makeTranslation_Widget(iWidget *parent) { | |||
3451 | return dlg; | 3482 | return dlg; |
3452 | } | 3483 | } |
3453 | 3484 | ||
3485 | iWidget *makeGlyphFinder_Widget(void) { | ||
3486 | iString msg; | ||
3487 | iString command; | ||
3488 | init_String(&msg); | ||
3489 | initCStr_String(&command, "!font.find chars:"); | ||
3490 | for (size_t i = 0; ; i++) { | ||
3491 | iChar ch = missing_Text(i); | ||
3492 | if (!ch) break; | ||
3493 | appendFormat_String(&msg, " U+%04X", ch); | ||
3494 | appendChar_String(&command, ch); | ||
3495 | } | ||
3496 | iArray items; | ||
3497 | init_Array(&items, sizeof(iMenuItem)); | ||
3498 | if (!isEmpty_String(&msg)) { | ||
3499 | prependCStr_String(&msg, "${dlg.glyphfinder.missing} "); | ||
3500 | appendCStr_String(&msg, "\n\n${dlg.glyphfinder.help}"); | ||
3501 | pushBackN_Array( | ||
3502 | &items, | ||
3503 | (iMenuItem[]){ | ||
3504 | { "${menu.fonts}", 0, 0, "!open newtab:1 url:about:fonts" }, | ||
3505 | { "${dlg.glyphfinder.disable}", 0, 0, "prefs.font.warnmissing.changed arg:0" }, | ||
3506 | { "---" }, | ||
3507 | { uiTextCaution_ColorEscape magnifyingGlass_Icon " ${dlg.glyphfinder.search}", | ||
3508 | 0, | ||
3509 | 0, | ||
3510 | cstr_String(&command) }, | ||
3511 | { "${close}", 0, 0, "cancel" } }, | ||
3512 | 5); | ||
3513 | } | ||
3514 | else { | ||
3515 | setCStr_String(&msg, "${dlg.glyphfinder.help.empty}"); | ||
3516 | pushBackN_Array(&items, | ||
3517 | (iMenuItem[]){ { "${menu.reload}", 0, 0, "navigate.reload" }, | ||
3518 | { "${close}", 0, 0, "cancel" } }, | ||
3519 | 2); | ||
3520 | } | ||
3521 | iWidget *dlg = makeQuestion_Widget("${heading.glyphfinder}", cstr_String(&msg), | ||
3522 | constData_Array(&items), | ||
3523 | size_Array(&items)); | ||
3524 | arrange_Widget(dlg); | ||
3525 | deinit_Array(&items); | ||
3526 | deinit_String(&command); | ||
3527 | deinit_String(&msg); | ||
3528 | return dlg; | ||
3529 | } | ||
3530 | |||
3531 | /*----------------------------------------------------------------------------------------------*/ | ||
3532 | |||
3454 | void init_PerfTimer(iPerfTimer *d) { | 3533 | void init_PerfTimer(iPerfTimer *d) { |
3455 | d->ticks = SDL_GetPerformanceCounter(); | 3534 | d->ticks = SDL_GetPerformanceCounter(); |
3456 | } | 3535 | } |
diff --git a/src/ui/util.h b/src/ui/util.h index 98ce784c..31c8cedc 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -336,12 +336,14 @@ iWidget * makeQuestion_Widget (const char *title, const char *msg, | |||
336 | iWidget * makePreferences_Widget (void); | 336 | iWidget * makePreferences_Widget (void); |
337 | void updatePreferencesLayout_Widget (iWidget *prefs); | 337 | void updatePreferencesLayout_Widget (iWidget *prefs); |
338 | 338 | ||
339 | iWidget * makeBookmarkEditor_Widget (void); | 339 | iWidget * makeBookmarkEditor_Widget (void); |
340 | void setBookmarkEditorFolder_Widget(iWidget *editor, uint32_t folderId); | 340 | void setBookmarkEditorFolder_Widget (iWidget *editor, uint32_t folderId); |
341 | iWidget * makeBookmarkCreation_Widget (const iString *url, const iString *title, iChar icon); | 341 | iWidget * makeBookmarkCreation_Widget (const iString *url, const iString *title, iChar icon); |
342 | iWidget * makeIdentityCreation_Widget (void); | 342 | iWidget * makeIdentityCreation_Widget (void); |
343 | iWidget * makeFeedSettings_Widget (uint32_t bookmarkId); | 343 | iWidget * makeFeedSettings_Widget (uint32_t bookmarkId); |
344 | iWidget * makeTranslation_Widget (iWidget *parent); | 344 | iWidget * makeSiteSpecificSettings_Widget (const iString *url); |
345 | iWidget * makeTranslation_Widget (iWidget *parent); | ||
346 | iWidget * makeGlyphFinder_Widget (void); | ||
345 | 347 | ||
346 | const char * languageId_String (const iString *menuItemLabel); | 348 | const char * languageId_String (const iString *menuItemLabel); |
347 | int languageIndex_CStr (const char *langId); | 349 | int languageIndex_CStr (const char *langId); |