diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-17 07:48:40 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-17 07:48:56 +0300 |
commit | a0f5bccc709866521fefeb34d6b97cafdbec6fad (patch) | |
tree | fefbc4c6cfec66bd84b85ede26a28eb1622a6940 /src/gmdocument.c | |
parent | 115602cf34dfb2f151846673468a41f16712eb49 (diff) |
Recognize and visualize "mailto:" links
"mailto:" links now have their own icon and when clicked they open the URL in the default web browser.
IssueID #5
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r-- | src/gmdocument.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index b2561ee0..f8d5c7cf 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -229,6 +229,9 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li | |||
229 | else if (equalCase_Rangecc(parts.scheme, "about")) { | 229 | else if (equalCase_Rangecc(parts.scheme, "about")) { |
230 | link->flags |= about_GmLinkFlag; | 230 | link->flags |= about_GmLinkFlag; |
231 | } | 231 | } |
232 | else if (equalCase_Rangecc(parts.scheme, "mailto")) { | ||
233 | link->flags |= mailto_GmLinkFlag; | ||
234 | } | ||
232 | /* Check the file name extension, if present. */ | 235 | /* Check the file name extension, if present. */ |
233 | if (!isEmpty_Range(&parts.path)) { | 236 | if (!isEmpty_Range(&parts.path)) { |
234 | iString *path = newRange_String(parts.path); | 237 | iString *path = newRange_String(parts.path); |
@@ -258,7 +261,7 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li | |||
258 | trim_Rangecc(&desc); | 261 | trim_Rangecc(&desc); |
259 | if (!isEmpty_Range(&desc)) { | 262 | if (!isEmpty_Range(&desc)) { |
260 | line = desc; /* Just show the description. */ | 263 | line = desc; /* Just show the description. */ |
261 | link->flags |= userFriendly_GmLinkFlag; | 264 | link->flags |= humanReadable_GmLinkFlag; |
262 | } | 265 | } |
263 | else { | 266 | else { |
264 | line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */ | 267 | line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */ |
@@ -321,10 +324,11 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
321 | static const float bottomMargin[max_GmLineType] = { | 324 | static const float bottomMargin[max_GmLineType] = { |
322 | 0.0f, 0.5f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f | 325 | 0.0f, 0.5f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f |
323 | }; | 326 | }; |
324 | static const char *arrow = "\u27a4"; // "\u2192"; | 327 | static const char *arrow = "\u27a4"; |
325 | static const char *bullet = "\u2022"; | 328 | static const char *envelope = "\U0001f4e7"; |
326 | static const char *folder = "\U0001f4c1"; | 329 | static const char *bullet = "\u2022"; |
327 | static const char *globe = "\U0001f310"; | 330 | static const char *folder = "\U0001f4c1"; |
331 | static const char *globe = "\U0001f310"; | ||
328 | const float midRunSkip = 0; /*0.120f;*/ /* extra space between wrapped text/quote lines */ | 332 | const float midRunSkip = 0; /*0.120f;*/ /* extra space between wrapped text/quote lines */ |
329 | clear_Array(&d->layout); | 333 | clear_Array(&d->layout); |
330 | clearLinks_GmDocument_(d); | 334 | clearLinks_GmDocument_(d); |
@@ -356,6 +360,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
356 | run.imageId = 0; | 360 | run.imageId = 0; |
357 | enum iGmLineType type; | 361 | enum iGmLineType type; |
358 | int indent = 0; | 362 | int indent = 0; |
363 | /* Detect the type of the line. */ | ||
359 | if (!isPreformat) { | 364 | if (!isPreformat) { |
360 | type = lineType_GmDocument_(d, line); | 365 | type = lineType_GmDocument_(d, line); |
361 | if (contentLine.start == content.start) { | 366 | if (contentLine.start == content.start) { |
@@ -479,7 +484,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
479 | const iGmLink *link = constAt_PtrArray(&d->links, run.linkId - 1); | 484 | const iGmLink *link = constAt_PtrArray(&d->links, run.linkId - 1); |
480 | icon.text = range_CStr(link->flags & file_GmLinkFlag | 485 | icon.text = range_CStr(link->flags & file_GmLinkFlag |
481 | ? folder | 486 | ? folder |
482 | : link->flags & remote_GmLinkFlag ? globe : arrow); | 487 | : link->flags & mailto_GmLinkFlag |
488 | ? envelope | ||
489 | : link->flags & remote_GmLinkFlag ? globe : arrow); | ||
483 | if (link->flags & remote_GmLinkFlag) { | 490 | if (link->flags & remote_GmLinkFlag) { |
484 | icon.visBounds.pos.x -= gap_Text / 2; | 491 | icon.visBounds.pos.x -= gap_Text / 2; |
485 | } | 492 | } |
@@ -1114,6 +1121,7 @@ uint16_t linkImage_GmDocument(const iGmDocument *d, iGmLinkId linkId) { | |||
1114 | 1121 | ||
1115 | enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum iGmLinkPart part) { | 1122 | enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum iGmLinkPart part) { |
1116 | const iGmLink *link = link_GmDocument_(d, linkId); | 1123 | const iGmLink *link = link_GmDocument_(d, linkId); |
1124 | const int www_GmLinkFlag = http_GmLinkFlag | mailto_GmLinkFlag; | ||
1117 | if (link) { | 1125 | if (link) { |
1118 | const iBool isBad = (link->flags & supportedProtocol_GmLinkFlag) == 0; | 1126 | const iBool isBad = (link->flags & supportedProtocol_GmLinkFlag) == 0; |
1119 | if (part == icon_GmLinkPart) { | 1127 | if (part == icon_GmLinkPart) { |
@@ -1121,24 +1129,24 @@ enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum | |||
1121 | return tmBadLink_ColorId; | 1129 | return tmBadLink_ColorId; |
1122 | } | 1130 | } |
1123 | if (link->flags & visited_GmLinkFlag) { | 1131 | if (link->flags & visited_GmLinkFlag) { |
1124 | return link->flags & http_GmLinkFlag | 1132 | return link->flags & www_GmLinkFlag |
1125 | ? tmHypertextLinkIconVisited_ColorId | 1133 | ? tmHypertextLinkIconVisited_ColorId |
1126 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkIconVisited_ColorId | 1134 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkIconVisited_ColorId |
1127 | : tmLinkIconVisited_ColorId; | 1135 | : tmLinkIconVisited_ColorId; |
1128 | } | 1136 | } |
1129 | return link->flags & http_GmLinkFlag | 1137 | return link->flags & www_GmLinkFlag |
1130 | ? tmHypertextLinkIcon_ColorId | 1138 | ? tmHypertextLinkIcon_ColorId |
1131 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkIcon_ColorId | 1139 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkIcon_ColorId |
1132 | : tmLinkIcon_ColorId; | 1140 | : tmLinkIcon_ColorId; |
1133 | } | 1141 | } |
1134 | if (part == text_GmLinkPart) { | 1142 | if (part == text_GmLinkPart) { |
1135 | return link->flags & http_GmLinkFlag | 1143 | return link->flags & www_GmLinkFlag |
1136 | ? tmHypertextLinkText_ColorId | 1144 | ? tmHypertextLinkText_ColorId |
1137 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkText_ColorId | 1145 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkText_ColorId |
1138 | : tmLinkText_ColorId; | 1146 | : tmLinkText_ColorId; |
1139 | } | 1147 | } |
1140 | if (part == textHover_GmLinkPart) { | 1148 | if (part == textHover_GmLinkPart) { |
1141 | return link->flags & http_GmLinkFlag | 1149 | return link->flags & www_GmLinkFlag |
1142 | ? tmHypertextLinkTextHover_ColorId | 1150 | ? tmHypertextLinkTextHover_ColorId |
1143 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkTextHover_ColorId | 1151 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkTextHover_ColorId |
1144 | : tmLinkTextHover_ColorId; | 1152 | : tmLinkTextHover_ColorId; |
@@ -1147,13 +1155,13 @@ enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum | |||
1147 | if (isBad) { | 1155 | if (isBad) { |
1148 | return tmBadLink_ColorId; | 1156 | return tmBadLink_ColorId; |
1149 | } | 1157 | } |
1150 | return link->flags & http_GmLinkFlag | 1158 | return link->flags & www_GmLinkFlag |
1151 | ? tmHypertextLinkDomain_ColorId | 1159 | ? tmHypertextLinkDomain_ColorId |
1152 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkDomain_ColorId | 1160 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkDomain_ColorId |
1153 | : tmLinkDomain_ColorId; | 1161 | : tmLinkDomain_ColorId; |
1154 | } | 1162 | } |
1155 | if (part == visited_GmLinkPart) { | 1163 | if (part == visited_GmLinkPart) { |
1156 | return link->flags & http_GmLinkFlag | 1164 | return link->flags & www_GmLinkFlag |
1157 | ? tmHypertextLinkLastVisitDate_ColorId | 1165 | ? tmHypertextLinkLastVisitDate_ColorId |
1158 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkLastVisitDate_ColorId | 1166 | : link->flags & gopher_GmLinkFlag ? tmGopherLinkLastVisitDate_ColorId |
1159 | : tmLinkLastVisitDate_ColorId; | 1167 | : tmLinkLastVisitDate_ColorId; |