summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-08 12:24:10 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-08 12:24:10 +0200
commit2fb1f5bed356520bc0b668f2a8ffef6c8d0318d2 (patch)
tree69f1511ff2e2baa2e45ba17ab6ed9372bc0b2077 /src
parent6f383d147fdcedd9626bfa3a80d4d5953eae398f (diff)
Local Gemini links can use Emoji/symbol from label text
Instead of the default link icon, if a label starts with an Emoji or symbol, use that as the icon. This only works with local Gemini links so important information about link destination is not hidden.
Diffstat (limited to 'src')
-rw-r--r--src/gmdocument.c24
-rw-r--r--src/gmdocument.h1
-rw-r--r--src/ui/text.h7
3 files changed, 32 insertions, 0 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 0d008181..54b7ad56 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -40,6 +40,7 @@ iDeclareType(GmLink)
40struct Impl_GmLink { 40struct Impl_GmLink {
41 iString url; 41 iString url;
42 iRangecc urlRange; /* URL in the source */ 42 iRangecc urlRange; /* URL in the source */
43 iRangecc labelIcon; /* special icon defined in the label text */
43 iTime when; 44 iTime when;
44 int flags; 45 int flags;
45}; 46};
@@ -227,9 +228,24 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li
227 *linkId = size_PtrArray(&d->links); /* index + 1 */ 228 *linkId = size_PtrArray(&d->links); /* index + 1 */
228 iRangecc desc = capturedRange_RegExpMatch(&m, 2); 229 iRangecc desc = capturedRange_RegExpMatch(&m, 2);
229 trim_Rangecc(&desc); 230 trim_Rangecc(&desc);
231 link->labelIcon = iNullRange;
230 if (!isEmpty_Range(&desc)) { 232 if (!isEmpty_Range(&desc)) {
231 line = desc; /* Just show the description. */ 233 line = desc; /* Just show the description. */
232 link->flags |= humanReadable_GmLinkFlag; 234 link->flags |= humanReadable_GmLinkFlag;
235 /* Check for a custom icon. */
236 if (link->flags & gemini_GmLinkFlag && ~link->flags & remote_GmLinkFlag) {
237 iChar icon = 0;
238 int len = 0;
239 if ((len = decodeBytes_MultibyteChar(desc.start, size_Range(&desc), &icon)) > 0) {
240 if (desc.start + len < desc.end && (isSymbol_Char(icon) || isEmoji_Char(icon)) &&
241 !isFitzpatrickType_Char(icon)) {
242 link->flags |= iconFromLabel_GmLinkFlag;
243 link->labelIcon = (iRangecc){ desc.start, desc.start + len };
244 line.start += len;
245 line.start = skipSpace_CStr(line.start);
246 }
247 }
248 }
233 } 249 }
234 else { 250 else {
235 line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */ 251 line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */
@@ -520,6 +536,10 @@ static void doLayout_GmDocument_(iGmDocument *d) {
520 : link->flags & mailto_GmLinkFlag ? envelope 536 : link->flags & mailto_GmLinkFlag ? envelope
521 : link->flags & remote_GmLinkFlag ? globe 537 : link->flags & remote_GmLinkFlag ? globe
522 : arrow); 538 : arrow);
539 /* Custom link icon is shown on local Gemini links only. */
540 if (!isEmpty_Range(&link->labelIcon)) {
541 icon.text = link->labelIcon;
542 }
523 icon.font = regular_FontId; 543 icon.font = regular_FontId;
524 if (link->flags & remote_GmLinkFlag) { 544 if (link->flags & remote_GmLinkFlag) {
525 icon.visBounds.pos.x -= gap_Text / 2; 545 icon.visBounds.pos.x -= gap_Text / 2;
@@ -1450,6 +1470,10 @@ enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum
1450 if (isUnsupported) { 1470 if (isUnsupported) {
1451 return tmBadLink_ColorId; 1471 return tmBadLink_ColorId;
1452 } 1472 }
1473 if (link->flags & iconFromLabel_GmLinkFlag) {
1474 return link->flags & visited_GmLinkFlag ? tmLinkTextHover_ColorId
1475 : tmLinkText_ColorId;
1476 }
1453 if (link->flags & visited_GmLinkFlag) { 1477 if (link->flags & visited_GmLinkFlag) {
1454 return link->flags & www_GmLinkFlag ? tmHypertextLinkIconVisited_ColorId 1478 return link->flags & www_GmLinkFlag ? tmHypertextLinkIconVisited_ColorId
1455 : link->flags & gopherOrFinger_GmLinkFlag ? tmGopherLinkIconVisited_ColorId 1479 : link->flags & gopherOrFinger_GmLinkFlag ? tmGopherLinkIconVisited_ColorId
diff --git a/src/gmdocument.h b/src/gmdocument.h
index 16127ea3..92f62ba4 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -69,6 +69,7 @@ enum iGmLinkFlags {
69 visited_GmLinkFlag = iBit(14), /* in the history */ 69 visited_GmLinkFlag = iBit(14), /* in the history */
70 permanent_GmLinkFlag = iBit(15), /* content cannot be dismissed; media link */ 70 permanent_GmLinkFlag = iBit(15), /* content cannot be dismissed; media link */
71 query_GmLinkFlag = iBit(16), /* Gopher query link */ 71 query_GmLinkFlag = iBit(16), /* Gopher query link */
72 iconFromLabel_GmLinkFlag = iBit(17), /* use an Emoji/special character from label */
72}; 73};
73 74
74struct Impl_GmHeading { 75struct Impl_GmHeading {
diff --git a/src/ui/text.h b/src/ui/text.h
index acce286b..d57c2c62 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -140,6 +140,13 @@ iLocalDef iBool isEmoji_Char(iChar c) {
140 return (c >= 0x1f300 && c < 0x1f700) || (c >= 0x1f7e0 && c <= 0x1f7eb) || 140 return (c >= 0x1f300 && c < 0x1f700) || (c >= 0x1f7e0 && c <= 0x1f7eb) ||
141 (c >= 0x1f900 && c <= 0x1f9ff); 141 (c >= 0x1f900 && c <= 0x1f9ff);
142} 142}
143iLocalDef iBool isDingbats_Char(iChar c) {
144 return c >= 0x2702 && c <= 0x27b0;
145}
146iLocalDef iBool isSymbol_Char(iChar c) {
147 return (c == 0x2218 || c == 0x2219) || (c >= 0x1f680 && c <= 0x1f6c0) ||
148 (c >= 0x2300 && c <= 0x26ff);
149}
143 150
144#define emojiVariationSelector_Char ((iChar) 0xfe0f) 151#define emojiVariationSelector_Char ((iChar) 0xfe0f)
145 152