diff options
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r-- | src/gmdocument.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index 2f3a006f..1ff085c7 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -304,6 +304,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
304 | iBool isPreformat = iFalse; | 304 | iBool isPreformat = iFalse; |
305 | iRangecc preAltText = iNullRange; | 305 | iRangecc preAltText = iNullRange; |
306 | int preFont = preformatted_FontId; | 306 | int preFont = preformatted_FontId; |
307 | uint16_t preId = 0; | ||
307 | iBool enableIndents = iFalse; | 308 | iBool enableIndents = iFalse; |
308 | iBool addSiteBanner = d->siteBannerEnabled; | 309 | iBool addSiteBanner = d->siteBannerEnabled; |
309 | enum iGmLineType prevType = text_GmLineType; | 310 | enum iGmLineType prevType = text_GmLineType; |
@@ -313,12 +314,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
313 | } | 314 | } |
314 | while (nextSplit_Rangecc(content, "\n", &contentLine)) { | 315 | while (nextSplit_Rangecc(content, "\n", &contentLine)) { |
315 | iRangecc line = contentLine; /* `line` will be trimmed later; would confuse nextSplit */ | 316 | iRangecc line = contentLine; /* `line` will be trimmed later; would confuse nextSplit */ |
316 | iGmRun run; | 317 | iGmRun run = { .color = white_ColorId }; |
317 | run.flags = 0; | ||
318 | run.color = white_ColorId; | ||
319 | run.linkId = 0; | ||
320 | run.imageId = 0; | ||
321 | run.audioId = 0; | ||
322 | enum iGmLineType type; | 318 | enum iGmLineType type; |
323 | int indent = 0; | 319 | int indent = 0; |
324 | /* Detect the type of the line. */ | 320 | /* Detect the type of the line. */ |
@@ -330,6 +326,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
330 | indent = indents[type]; | 326 | indent = indents[type]; |
331 | if (type == preformatted_GmLineType) { | 327 | if (type == preformatted_GmLineType) { |
332 | isPreformat = iTrue; | 328 | isPreformat = iTrue; |
329 | preId++; | ||
333 | preFont = preformatted_FontId; | 330 | preFont = preformatted_FontId; |
334 | /* Use a smaller font if the block contents are wide. */ | 331 | /* Use a smaller font if the block contents are wide. */ |
335 | if (measurePreformattedBlock_GmDocument_(d, line.start, preFont).x > | 332 | if (measurePreformattedBlock_GmDocument_(d, line.start, preFont).x > |
@@ -370,6 +367,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
370 | addSiteBanner = iFalse; /* overrides the banner */ | 367 | addSiteBanner = iFalse; /* overrides the banner */ |
371 | continue; | 368 | continue; |
372 | } | 369 | } |
370 | run.preId = preId; | ||
373 | run.font = (d->format == plainText_GmDocumentFormat ? regularMonospace_FontId : preFont); | 371 | run.font = (d->format == plainText_GmDocumentFormat ? regularMonospace_FontId : preFont); |
374 | indent = indents[type]; | 372 | indent = indents[type]; |
375 | } | 373 | } |
@@ -509,8 +507,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
509 | } | 507 | } |
510 | run.bounds.pos = addX_I2(pos, indent * gap_Text); | 508 | run.bounds.pos = addX_I2(pos, indent * gap_Text); |
511 | const char *contPos; | 509 | const char *contPos; |
512 | const int avail = d->size.x - run.bounds.pos.x; | 510 | const int avail = isPreformat ? 0 : (d->size.x - run.bounds.pos.x); |
513 | const iInt2 dims = tryAdvance_Text(run.font, runLine, avail, &contPos); | 511 | const iInt2 dims = tryAdvance_Text(run.font, runLine, avail, &contPos); |
512 | iChangeFlags(run.flags, wide_GmRunFlag, (isPreformat && dims.x > d->size.x)); | ||
514 | run.bounds.size.x = iMax(avail, dims.x); /* Extends to the right edge for selection. */ | 513 | run.bounds.size.x = iMax(avail, dims.x); /* Extends to the right edge for selection. */ |
515 | run.bounds.size.y = dims.y; | 514 | run.bounds.size.y = dims.y; |
516 | run.visBounds = run.bounds; | 515 | run.visBounds = run.bounds; |
@@ -596,6 +595,19 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
596 | prevType = type; | 595 | prevType = type; |
597 | } | 596 | } |
598 | d->size.y = pos.y; | 597 | d->size.y = pos.y; |
598 | /* Go over the preformatted blocks and mark them wide if at least one run is wide. */ { | ||
599 | iForEach(Array, i, &d->layout) { | ||
600 | iGmRun *run = i.value; | ||
601 | if (run->preId && run->flags & wide_GmRunFlag) { | ||
602 | iGmRunRange block = findPreformattedRange_GmDocument(d, run); | ||
603 | for (const iGmRun *j = block.start; j != block.end; j++) { | ||
604 | iConstCast(iGmRun *, j)->flags |= wide_GmRunFlag; | ||
605 | } | ||
606 | /* Skip to the end of the block. */ | ||
607 | i.pos = block.end - (const iGmRun *) constData_Array(&d->layout) - 1; | ||
608 | } | ||
609 | } | ||
610 | } | ||
599 | } | 611 | } |
600 | 612 | ||
601 | void init_GmDocument(iGmDocument *d) { | 613 | void init_GmDocument(iGmDocument *d) { |
@@ -1237,6 +1249,23 @@ iRangecc findTextBefore_GmDocument(const iGmDocument *d, const iString *text, co | |||
1237 | return found; | 1249 | return found; |
1238 | } | 1250 | } |
1239 | 1251 | ||
1252 | iGmRunRange findPreformattedRange_GmDocument(const iGmDocument *d, const iGmRun *run) { | ||
1253 | iAssert(run->preId); | ||
1254 | iGmRunRange range = { run, run }; | ||
1255 | /* Find the beginning. */ | ||
1256 | while (range.start > (const iGmRun *) constData_Array(&d->layout)) { | ||
1257 | const iGmRun *prev = range.start - 1; | ||
1258 | if (prev->preId != run->preId) break; | ||
1259 | range.start = prev; | ||
1260 | } | ||
1261 | /* Find the ending. */ | ||
1262 | while (range.end < (const iGmRun *) constEnd_Array(&d->layout)) { | ||
1263 | if (range.end->preId != run->preId) break; | ||
1264 | range.end++; | ||
1265 | } | ||
1266 | return range; | ||
1267 | } | ||
1268 | |||
1240 | const iGmRun *findRun_GmDocument(const iGmDocument *d, iInt2 pos) { | 1269 | const iGmRun *findRun_GmDocument(const iGmDocument *d, iInt2 pos) { |
1241 | /* TODO: Perf optimization likely needed; use a block map? */ | 1270 | /* TODO: Perf optimization likely needed; use a block map? */ |
1242 | const iGmRun *last = NULL; | 1271 | const iGmRun *last = NULL; |