version 1.282, 2020/09/02 16:40:36 |
version 1.289, 2022/08/15 18:12:30 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
|
* Copyright (c) 2010-2022 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org> |
|
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 58 term_setcol(struct termp *p, size_t maxtcol) |
|
Line 58 term_setcol(struct termp *p, size_t maxtcol) |
|
void |
void |
term_free(struct termp *p) |
term_free(struct termp *p) |
{ |
{ |
|
term_tab_free(); |
for (p->tcol = p->tcols; p->tcol < p->tcols + p->maxtcol; p->tcol++) |
for (p->tcol = p->tcols; p->tcol < p->tcols + p->maxtcol; p->tcol++) |
free(p->tcol->buf); |
free(p->tcol->buf); |
free(p->tcols); |
free(p->tcols); |
Line 156 term_flushln(struct termp *p) |
|
Line 157 term_flushln(struct termp *p) |
|
/* Finally, print the field content. */ |
/* Finally, print the field content. */ |
|
|
term_field(p, vbl, nbr); |
term_field(p, vbl, nbr); |
|
p->tcol->taboff += vbr + (*p->width)(p, ' '); |
|
|
/* |
/* |
* If there is no text left in the field, exit the loop. |
* If there is no text left in the field, exit the loop. |
Line 206 term_flushln(struct termp *p) |
|
Line 208 term_flushln(struct termp *p) |
|
return; |
return; |
|
|
endline(p); |
endline(p); |
p->viscol = 0; |
|
|
|
/* |
/* |
* Normally, start the next line at the same indentation |
* Normally, start the next line at the same indentation |
Line 267 term_fill(struct termp *p, size_t *nbr, size_t *vbr, s |
|
Line 268 term_fill(struct termp *p, size_t *nbr, size_t *vbr, s |
|
vis -= (*p->width)(p, p->tcol->buf[ic - 1]); |
vis -= (*p->width)(p, p->tcol->buf[ic - 1]); |
continue; |
continue; |
|
|
case '\t': /* Normal ASCII whitespace. */ |
|
case ' ': |
case ' ': |
case ASCII_BREAK: /* Escape \: (breakpoint). */ |
case ASCII_BREAK: /* Escape \: (breakpoint). */ |
switch (p->tcol->buf[ic]) { |
vn = vis; |
case '\t': |
if (p->tcol->buf[ic] == ' ') |
vn = term_tab_next(vis); |
vn += (*p->width)(p, ' '); |
break; |
|
case ' ': |
|
vn = vis + (*p->width)(p, ' '); |
|
break; |
|
case ASCII_BREAK: |
|
vn = vis; |
|
break; |
|
default: |
|
abort(); |
|
} |
|
/* Can break at the end of a word. */ |
/* Can break at the end of a word. */ |
if (breakline || vn > vtarget) |
if (breakline || vn > vtarget) |
break; |
break; |
Line 316 term_fill(struct termp *p, size_t *nbr, size_t *vbr, s |
|
Line 306 term_fill(struct termp *p, size_t *nbr, size_t *vbr, s |
|
*vbr = vis; |
*vbr = vis; |
continue; |
continue; |
|
|
case ASCII_NBRSP: /* Non-breakable space. */ |
default: |
p->tcol->buf[ic] = ' '; |
switch (p->tcol->buf[ic]) { |
/* FALLTHROUGH */ |
case '\t': |
default: /* Printable character. */ |
vis += p->tcol->taboff; |
|
vis = term_tab_next(vis); |
|
vis -= p->tcol->taboff; |
|
break; |
|
case ASCII_NBRZW: /* Non-breakable zero-width. */ |
|
break; |
|
case ASCII_NBRSP: /* Non-breakable space. */ |
|
p->tcol->buf[ic] = ' '; |
|
/* FALLTHROUGH */ |
|
default: /* Printable character. */ |
|
vis += (*p->width)(p, p->tcol->buf[ic]); |
|
break; |
|
} |
graph = 1; |
graph = 1; |
vis += (*p->width)(p, p->tcol->buf[ic]); |
|
if (vis > vtarget && *nbr > 0) |
if (vis > vtarget && *nbr > 0) |
return; |
return; |
continue; |
continue; |
Line 351 term_field(struct termp *p, size_t vbl, size_t nbr) |
|
Line 352 term_field(struct termp *p, size_t vbl, size_t nbr) |
|
{ |
{ |
size_t ic; /* Character position in the input buffer. */ |
size_t ic; /* Character position in the input buffer. */ |
size_t vis; /* Visual position of the current character. */ |
size_t vis; /* Visual position of the current character. */ |
|
size_t vt; /* Visual position including tab offset. */ |
size_t dv; /* Visual width of the current character. */ |
size_t dv; /* Visual width of the current character. */ |
size_t vn; /* Visual position of the next character. */ |
|
|
|
vis = 0; |
vis = 0; |
for (ic = p->tcol->col; ic < nbr; ic++) { |
for (ic = p->tcol->col; ic < nbr; ic++) { |
Line 365 term_field(struct termp *p, size_t vbl, size_t nbr) |
|
Line 366 term_field(struct termp *p, size_t vbl, size_t nbr) |
|
switch (p->tcol->buf[ic]) { |
switch (p->tcol->buf[ic]) { |
case '\n': |
case '\n': |
case ASCII_BREAK: |
case ASCII_BREAK: |
|
case ASCII_NBRZW: |
continue; |
continue; |
case '\t': |
case '\t': |
vn = term_tab_next(vis); |
|
vbl += vn - vis; |
|
vis = vn; |
|
continue; |
|
case ' ': |
case ' ': |
case ASCII_NBRSP: |
case ASCII_NBRSP: |
dv = (*p->width)(p, ' '); |
if (p->tcol->buf[ic] == '\t') { |
|
vt = p->tcol->taboff + vis; |
|
dv = term_tab_next(vt) - vt; |
|
} else |
|
dv = (*p->width)(p, ' '); |
vbl += dv; |
vbl += dv; |
vis += dv; |
vis += dv; |
continue; |
continue; |
Line 435 endline(struct termp *p) |
|
Line 437 endline(struct termp *p) |
|
void |
void |
term_newln(struct termp *p) |
term_newln(struct termp *p) |
{ |
{ |
|
p->tcol->taboff = 0; |
p->flags |= TERMP_NOSPACE; |
p->flags |= TERMP_NOSPACE; |
if (p->tcol->lastcol || p->viscol) |
if (p->tcol->lastcol || p->viscol) |
term_flushln(p); |
term_flushln(p); |
Line 571 term_word(struct termp *p, const char *word) |
|
Line 573 term_word(struct termp *p, const char *word) |
|
break; |
break; |
case ESCAPE_NUMBERED: |
case ESCAPE_NUMBERED: |
uc = mchars_num2char(seq, sz); |
uc = mchars_num2char(seq, sz); |
if (uc < 0) |
if (uc >= 0) |
continue; |
break; |
break; |
bufferc(p, ASCII_NBRZW); |
|
continue; |
case ESCAPE_SPECIAL: |
case ESCAPE_SPECIAL: |
if (p->enc == TERMENC_ASCII) { |
if (p->enc == TERMENC_ASCII) { |
cp = mchars_spec2str(seq, sz, &ssz); |
cp = mchars_spec2str(seq, sz, &ssz); |
if (cp != NULL) |
if (cp != NULL) |
encode(p, cp, ssz); |
encode(p, cp, ssz); |
|
else |
|
bufferc(p, ASCII_NBRZW); |
} else { |
} else { |
uc = mchars_spec2cp(seq, sz); |
uc = mchars_spec2cp(seq, sz); |
if (uc > 0) |
if (uc > 0) |
encode1(p, uc); |
encode1(p, uc); |
|
else |
|
bufferc(p, ASCII_NBRZW); |
} |
} |
continue; |
continue; |
case ESCAPE_UNDEF: |
case ESCAPE_UNDEF: |
uc = *seq; |
uc = *seq; |
break; |
break; |
case ESCAPE_FONTBOLD: |
case ESCAPE_FONTBOLD: |
|
case ESCAPE_FONTCB: |
term_fontrepl(p, TERMFONT_BOLD); |
term_fontrepl(p, TERMFONT_BOLD); |
continue; |
continue; |
case ESCAPE_FONTITALIC: |
case ESCAPE_FONTITALIC: |
|
case ESCAPE_FONTCI: |
term_fontrepl(p, TERMFONT_UNDER); |
term_fontrepl(p, TERMFONT_UNDER); |
continue; |
continue; |
case ESCAPE_FONTBI: |
case ESCAPE_FONTBI: |
term_fontrepl(p, TERMFONT_BI); |
term_fontrepl(p, TERMFONT_BI); |
continue; |
continue; |
case ESCAPE_FONT: |
case ESCAPE_FONT: |
case ESCAPE_FONTCW: |
case ESCAPE_FONTCR: |
case ESCAPE_FONTROMAN: |
case ESCAPE_FONTROMAN: |
term_fontrepl(p, TERMFONT_NONE); |
term_fontrepl(p, TERMFONT_NONE); |
continue; |
continue; |
Line 625 term_word(struct termp *p, const char *word) |
|
Line 634 term_word(struct termp *p, const char *word) |
|
encode(p, "utf8", 4); |
encode(p, "utf8", 4); |
continue; |
continue; |
case ESCAPE_HORIZ: |
case ESCAPE_HORIZ: |
|
if (p->flags & TERMP_BACKAFTER) { |
|
p->flags &= ~TERMP_BACKAFTER; |
|
continue; |
|
} |
if (*seq == '|') { |
if (*seq == '|') { |
seq++; |
seq++; |
uc = -p->col; |
uc = -p->col; |
Line 633 term_word(struct termp *p, const char *word) |
|
Line 646 term_word(struct termp *p, const char *word) |
|
if (a2roffsu(seq, &su, SCALE_EM) == NULL) |
if (a2roffsu(seq, &su, SCALE_EM) == NULL) |
continue; |
continue; |
uc += term_hen(p, &su); |
uc += term_hen(p, &su); |
if (uc > 0) |
if (uc >= 0) { |
while (uc-- > 0) |
while (uc > 0) { |
bufferc(p, ASCII_NBRSP); |
uc -= term_len(p, 1); |
else if (p->col > (size_t)(-uc)) |
if (p->flags & TERMP_BACKBEFORE) |
|
p->flags &= ~TERMP_BACKBEFORE; |
|
else |
|
bufferc(p, ASCII_NBRSP); |
|
} |
|
continue; |
|
} |
|
if (p->flags & TERMP_BACKBEFORE) { |
|
p->flags &= ~TERMP_BACKBEFORE; |
|
assert(p->col > 0); |
|
p->col--; |
|
} |
|
if (p->col >= (size_t)(-uc)) { |
p->col += uc; |
p->col += uc; |
else { |
} else { |
uc += p->col; |
uc += p->col; |
p->col = 0; |
p->col = 0; |
if (p->tcol->offset > (size_t)(-uc)) { |
if (p->tcol->offset > (size_t)(-uc)) { |
Line 726 term_word(struct termp *p, const char *word) |
|
Line 751 term_word(struct termp *p, const char *word) |
|
if (p->col > p->tcol->lastcol) |
if (p->col > p->tcol->lastcol) |
p->col = p->tcol->lastcol; |
p->col = p->tcol->lastcol; |
continue; |
continue; |
|
case ESCAPE_IGNORE: |
|
bufferc(p, ASCII_NBRZW); |
|
continue; |
default: |
default: |
continue; |
continue; |
} |
} |
Line 917 term_strlen(const struct termp *p, const char *cp) |
|
Line 945 term_strlen(const struct termp *p, const char *cp) |
|
int ssz, skip, uc; |
int ssz, skip, uc; |
const char *seq, *rhs; |
const char *seq, *rhs; |
enum mandoc_esc esc; |
enum mandoc_esc esc; |
static const char rej[] = { '\\', ASCII_NBRSP, ASCII_HYPH, |
static const char rej[] = { '\\', ASCII_NBRSP, ASCII_NBRZW, |
ASCII_BREAK, '\0' }; |
ASCII_BREAK, ASCII_HYPH, '\0' }; |
|
|
/* |
/* |
* Account for escaped sequences within string length |
* Account for escaped sequences within string length |