summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-17 07:48:40 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-17 07:48:56 +0300
commita0f5bccc709866521fefeb34d6b97cafdbec6fad (patch)
treefefbc4c6cfec66bd84b85ede26a28eb1622a6940 /src/gmdocument.c
parent115602cf34dfb2f151846673468a41f16712eb49 (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.c32
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
1115enum iColorId linkColor_GmDocument(const iGmDocument *d, iGmLinkId linkId, enum iGmLinkPart part) { 1122enum 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;