diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-04-23 00:23:48 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-04-23 00:23:48 +0000 |
commit | 08a70c0e33aa4a198b1254e84f2f1194f0e347c7 (patch) | |
tree | a397266c9694ebd25708a046b00bd040571f1d67 /usr.bin/mandoc/term.c | |
parent | 793b146da12a082a33d45f1ebd7aaa099711e14d (diff) |
Handle literal tab characters both in literal context (.Bd -literal)
and outside. In literal context, tab stops are at each eigth column;
outside, they are at each fifth column.
Use tabwidth = 5 as the default and temporarily switch to 8 in termp_bd_pre().
This requires to move the term_flushln() of the final line of a display from
termp_bd_post() to termp_bd_pre(); the former still needs term_newln()
to handle the final lines of non-literal displays.
Handling inside term_flushln() is tricky because a tab collapses with
inter-word spacing, but not with another tab.
Missing feature reported independently by jmc@ and deraadt@.
Diffstat (limited to 'usr.bin/mandoc/term.c')
-rw-r--r-- | usr.bin/mandoc/term.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index 79c51aea6e7..45191b5e3da 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.29 2010/04/13 22:41:48 schwarze Exp $ */ +/* $Id: term.c,v 1.30 2010/04/23 00:23:47 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -79,6 +79,7 @@ term_alloc(enum termenc enc) perror(NULL); exit(EXIT_FAILURE); } + p->tabwidth = 5; p->enc = enc; return(p); } @@ -154,7 +155,7 @@ term_flushln(struct termp *p) * breaking the line. */ - vis = vend = i = 0; + vis = i = 0; while (i < (int)p->col) { /* @@ -165,6 +166,21 @@ term_flushln(struct termp *p) vbl = (size_t)(ASCII_EOS == p->buf[i] ? 2 : (0 == vis ? 0 : 1)); vis += vbl; + vend = vis; + + /* + * Handle literal tab characters. + */ + for (j = i; j < (int)p->col; j++) { + if ('\t' != p->buf[j]) + break; + /* Collapse tab with inter-word spacing. */ + if (vis > 0 && j == i) + vend = vis - 1; + vend = (vend/p->tabwidth+1)*p->tabwidth; + vbl += vend - vis; + vis = vend; + } /* * Count up visible word characters. Control sequences @@ -174,8 +190,8 @@ term_flushln(struct termp *p) */ /* LINTED */ - for (j = i, jhy = 0, vend = vis; j < (int)p->col; j++) { - if (j && ' ' == p->buf[j]) + for (jhy = 0; j < (int)p->col; j++) { + if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j]) break; else if (8 == p->buf[j]) vend--; @@ -233,11 +249,19 @@ term_flushln(struct termp *p) } /* + * Skip leading tabs, they were handled above. + */ + while (i < (int)p->col && '\t' == p->buf[i]) + i++; + + /* * Finally, write out the word. */ for ( ; i < (int)p->col; i++) { if (vend > bp && jhy > 0 && i > jhy) break; + if ('\t' == p->buf[i]) + break; if (' ' == p->buf[i]) { i++; break; |