diff options
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r-- | src/gmdocument.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index cb9e2acb..e23d5836 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -86,6 +86,8 @@ struct Impl_GmDocument { | |||
86 | iPtrArray links; | 86 | iPtrArray links; |
87 | iString title; /* the first top-level title */ | 87 | iString title; /* the first top-level title */ |
88 | iPtrArray images; /* persistent across layouts, references links by ID */ | 88 | iPtrArray images; /* persistent across layouts, references links by ID */ |
89 | uint32_t themeSeed; | ||
90 | iChar siteIcon; | ||
89 | }; | 91 | }; |
90 | 92 | ||
91 | iDefineObjectConstruction(GmDocument) | 93 | iDefineObjectConstruction(GmDocument) |
@@ -299,11 +301,12 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
299 | enum iGmLineType prevType = text_GmLineType; | 301 | enum iGmLineType prevType = text_GmLineType; |
300 | iBool isPreformat = iFalse; | 302 | iBool isPreformat = iFalse; |
301 | iBool isFirstText = iTrue; | 303 | iBool isFirstText = iTrue; |
304 | iBool addSiteBanner = iTrue; | ||
302 | int preFont = preformatted_FontId; | 305 | int preFont = preformatted_FontId; |
303 | if (d->format == plainText_GmDocumentFormat) { | 306 | if (d->format == plainText_GmDocumentFormat) { |
304 | isPreformat = iTrue; | 307 | isPreformat = iTrue; |
305 | isFirstText = iFalse; | 308 | isFirstText = iFalse; |
306 | } | 309 | } |
307 | while (nextSplit_Rangecc(&content, "\n", &line)) { | 310 | while (nextSplit_Rangecc(&content, "\n", &line)) { |
308 | iGmRun run; | 311 | iGmRun run; |
309 | run.flags = 0; | 312 | run.flags = 0; |
@@ -345,11 +348,26 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
345 | startsWithSc_Rangecc(&line, "```", &iCaseSensitive)) { | 348 | startsWithSc_Rangecc(&line, "```", &iCaseSensitive)) { |
346 | isPreformat = iFalse; | 349 | isPreformat = iFalse; |
347 | preAltText = iNullRange; | 350 | preAltText = iNullRange; |
351 | addSiteBanner = iFalse; /* overrides the banner */ | ||
348 | continue; | 352 | continue; |
349 | } | 353 | } |
350 | run.font = preFont; | 354 | run.font = preFont; |
351 | indent = indents[type]; | 355 | indent = indents[type]; |
352 | } | 356 | } |
357 | if (addSiteBanner) { | ||
358 | addSiteBanner = iFalse; | ||
359 | const iRangecc bannerText = urlHost_String(&d->url); | ||
360 | if (!isEmpty_Range(&bannerText)) { | ||
361 | iGmRun banner = { .flags = siteBanner_GmRunFlag }; | ||
362 | banner.bounds = zero_Rect(); | ||
363 | banner.visBounds = init_Rect(0, 0, d->size.x, lineHeight_Text(banner_FontId) * 2); | ||
364 | banner.font = banner_FontId; | ||
365 | banner.text = bannerText; | ||
366 | banner.color = gray50_ColorId; | ||
367 | pushBack_Array(&d->layout, &banner); | ||
368 | pos.y += height_Rect(banner.visBounds) + lineHeight_Text(paragraph_FontId); | ||
369 | } | ||
370 | } | ||
353 | /* Empty lines don't produce text runs. */ | 371 | /* Empty lines don't produce text runs. */ |
354 | if (isEmpty_Range(&line)) { | 372 | if (isEmpty_Range(&line)) { |
355 | pos.y += lineHeight_Text(run.font); | 373 | pos.y += lineHeight_Text(run.font); |
@@ -415,7 +433,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
415 | int bigCount = 0; | 433 | int bigCount = 0; |
416 | if (type == text_GmLineType && isFirstText) { | 434 | if (type == text_GmLineType && isFirstText) { |
417 | run.font = firstParagraph_FontId; | 435 | run.font = firstParagraph_FontId; |
418 | run.color = gray88_ColorId; | 436 | run.color = white_ColorId; |
419 | bigCount = 15; /* max lines -- what if the whole document is one paragraph? */ | 437 | bigCount = 15; /* max lines -- what if the whole document is one paragraph? */ |
420 | isFirstText = iFalse; | 438 | isFirstText = iFalse; |
421 | } | 439 | } |
@@ -505,6 +523,7 @@ void init_GmDocument(iGmDocument *d) { | |||
505 | init_PtrArray(&d->links); | 523 | init_PtrArray(&d->links); |
506 | init_String(&d->title); | 524 | init_String(&d->title); |
507 | init_PtrArray(&d->images); | 525 | init_PtrArray(&d->images); |
526 | setThemeSeed_GmDocument(d, NULL); | ||
508 | } | 527 | } |
509 | 528 | ||
510 | void deinit_GmDocument(iGmDocument *d) { | 529 | void deinit_GmDocument(iGmDocument *d) { |
@@ -527,6 +546,30 @@ void reset_GmDocument(iGmDocument *d) { | |||
527 | clear_Array(&d->layout); | 546 | clear_Array(&d->layout); |
528 | clear_String(&d->url); | 547 | clear_String(&d->url); |
529 | clear_String(&d->localHost); | 548 | clear_String(&d->localHost); |
549 | d->themeSeed = 0; | ||
550 | } | ||
551 | |||
552 | void setThemeSeed_GmDocument(iGmDocument *d, const iBlock *seed) { | ||
553 | static const iChar siteIcons[] = { | ||
554 | 0x25ed, 0x2600, 0x2601, 0x2604, 0x2605, 0x2606, 0x265c, 0x265e, 0x2690, | ||
555 | 0x2691, 0x2693, 0x2698, 0x2699, 0x26f0, 0x270e, 0x2728, 0x272a, 0x272f, | ||
556 | 0x2731, 0x2738, 0x273a, 0x273e, 0x2740, 0x2742, 0x2744, 0x2748, 0x274a, | ||
557 | 0x2751, 0x2756, 0x2766, 0x27bd, 0x27c1, 0x27d0, 0x2b19, 0x1f300, 0x1f303, | ||
558 | 0x1f306, 0x1f308, 0x1f30a, 0x1f319, 0x1f31f, 0x1f320, 0x1f340, 0x1f4cd, 0x1f4e1, | ||
559 | 0x1f657, 0x1f659, 0x1f665, 0x1f78b, 0x1f796, 0x1f79c, | ||
560 | }; | ||
561 | d->themeSeed = 0; | ||
562 | d->siteIcon = 0; | ||
563 | if (seed && !isEmpty_Block(seed)) { | ||
564 | d->themeSeed = crc32_Block(seed); | ||
565 | d->siteIcon = siteIcons[(d->themeSeed >> 7) % iElemCount(siteIcons)]; | ||
566 | } | ||
567 | /* Special exceptions. */ { | ||
568 | const iRangecc host = urlHost_String(&d->url); | ||
569 | if (equalCase_Rangecc(&host, "gemini.circumlunar.space")) { | ||
570 | d->siteIcon = 0x264a; /* gemini */ | ||
571 | } | ||
572 | } | ||
530 | } | 573 | } |
531 | 574 | ||
532 | void setFormat_GmDocument(iGmDocument *d, enum iGmDocumentFormat format) { | 575 | void setFormat_GmDocument(iGmDocument *d, enum iGmDocumentFormat format) { |
@@ -786,6 +829,10 @@ const iString *title_GmDocument(const iGmDocument *d) { | |||
786 | return &d->title; | 829 | return &d->title; |
787 | } | 830 | } |
788 | 831 | ||
832 | iChar siteIcon_GmDocument(const iGmDocument *d) { | ||
833 | return d->siteIcon; | ||
834 | } | ||
835 | |||
789 | const char *findLoc_GmRun(const iGmRun *d, iInt2 pos) { | 836 | const char *findLoc_GmRun(const iGmRun *d, iInt2 pos) { |
790 | const int x = pos.x - left_Rect(d->bounds); | 837 | const int x = pos.x - left_Rect(d->bounds); |
791 | const char *loc; | 838 | const char *loc; |