From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp1.rz.uni-karlsruhe.de (Debian-exim@smtp1.rz.uni-karlsruhe.de [129.13.185.217]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id o4OKjIUM007353 for ; Mon, 24 May 2010 14:45:19 -0600 (MDT) Received: from hekate.usta.de (asta-nat.asta.uni-karlsruhe.de [172.22.63.82]) by smtp1.rz.uni-karlsruhe.de with esmtp (Exim 4.63 #1) id 1OGeWS-0004uA-TE; Mon, 24 May 2010 22:45:17 +0200 Received: from donnerwolke.usta.de ([172.24.96.3]) by hekate.usta.de with esmtp (Exim 4.71) (envelope-from ) id 1OGeWS-000168-SH for tech@mdocml.bsd.lv; Mon, 24 May 2010 22:45:16 +0200 Received: from iris.usta.de ([172.24.96.5] helo=usta.de) by donnerwolke.usta.de with esmtp (Exim 4.69) (envelope-from ) id 1OGeWS-00039v-RW for tech@mdocml.bsd.lv; Mon, 24 May 2010 22:45:16 +0200 Received: from schwarze by usta.de with local (Exim 4.71) (envelope-from ) id 1OGeWS-0003Cm-IG for tech@mdocml.bsd.lv; Mon, 24 May 2010 22:45:16 +0200 Date: Mon, 24 May 2010 22:45:16 +0200 From: Ingo Schwarze To: tech@mdocml.bsd.lv Subject: PATCH: fix vertical spacing in nested lists Message-ID: <20100524204516.GB21391@iris.usta.de> X-Mailinglist: mdocml-tech Reply-To: tech@mdocml.bsd.lv MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="uAKRQypu60I7Lcqm" Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) --uAKRQypu60I7Lcqm Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi Joerg and Kristaps, OK, so now i'm producing stacked diffs. The following will only apply *after* you have applied 05.tabbing.patch. It touches more or less the same lines of the same files. There is no clear corresponding commit in OpenBSD, it needed several iterations to get this right. In particular, term.c 1.23: > When the last field on an output line is empty, break the line > if and only if something was printed on that line. > This avoids double line breaks after nested lists > while still breaking lines after items with empty body. term.c 1.28, mdoc_term.c 1.74: > Partial revert of term.c rev. 1.23 > because jmc@ noticed that it broke blank lines in literal displays. > > The original idea was to suppress stray blank lines. > But we don't want to suppress *all* blank lines, > instead just those caused by nested lists. > So do the check whether there was any output on this line, > i.e. whether or not to break the line, > at the right place, which is after processing the .It body. term.c 1.29, term.h 1.15: > Fix rendering of multiple successive .It macros without intervening text; > another problem reported by jmc@. > > The physical output line may contain output from more than one buffer. > Thus, to decide whether a line break is needed, it's insufficient to > only look at the number of bytes in the current output buffer. > Keep track of the number of characters already written, too. Joerg, you may remeber we discussed this while walking along the southern and western edge of the village of Nienhagen just before reaching the Baltic sea. From a layering point of view, it may be better to do this half a layer upwards, that is not in term_flushln(), but in bufferc(), which would require a trivial rewrite of buffera() in terms of bufferc(). I doubt it can conveniently be done a full layer upwards, that is on the layer of mdoc(7) macros, because it is not at all obvious on that layer whether a macro will or will not generate non-whitespace output with the given output device settings at the end of the day. So, it would be useful to try and write an implementation setting the flag in bufferc() instead of term_flushln(). If this gets done quickly and turns out to be better than this one, i will happily throw this one away and also replace it in the OpenBSD tree. If this kind of replacement needs more thought or time, no problem either, then we can come back to it later when we are not in a hurry. In that case, i propose to use this one for now: It works and is only mildly ugly, and it will get us in sync. For now, personally, i'm focussing on getting my other patches ready for commit, so we can reach synced state asap. This diff is also available from /usr/vhosts/mdocml.bsd.lv/patch/schwarze/08.viscol.patch A test page is attached, covering only the nesting case. Testing the empty .It case in .Bl -tag is easy anyway. Thoughts? Yours, Ingo --- term.h Mon May 24 16:54:52 2010 +++ term.h Sat May 15 23:09:53 2010 @@ -39,6 +39,7 @@ struct termp { size_t offset; /* Margin offest. */ size_t tabwidth; /* Distance of tab positions. */ size_t col; /* Bytes in buf. */ + size_t viscol; /* Chars on current line. */ int overstep; /* See termp_flushln(). */ int flags; #define TERMP_SENTENCE (1 << 1) /* Space before a sentence. */ --- term.c Mon May 24 16:54:52 2010 +++ term.c Mon May 24 00:45:01 2010 @@ -190,27 +187,29 @@ term_flushln(struct termp *p) */ /* LINTED */ for ( ; j < (int)p->col; j++) { if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j]) break; if (8 == p->buf[j]) vend--; else vend++; } /* * Find out whether we would exceed the right margin. * If so, break to the next line. */ if (vend > bp && vis > 0) { vend -= vis; putchar('\n'); if (TERMP_NOBREAK & p->flags) { + p->viscol = p->rmargin; for (j = 0; j < (int)p->rmargin; j++) putchar(' '); vend += p->rmargin - p->offset; } else { + p->viscol = 0; vbl = p->offset; } @@ -251,9 +256,11 @@ term_flushln(struct termp *p) if (vbl) { for (j = 0; j < (int)vbl; j++) putchar(' '); + p->viscol += vbl; vbl = 0; } putchar(p->buf[i]); + p->viscol += 1; } vend += vbl; vis = vend; @@ -263,6 +270,7 @@ term_flushln(struct termp *p) p->overstep = 0; if ( ! (TERMP_NOBREAK & p->flags)) { + p->viscol = 0; putchar('\n'); return; } @@ -294,11 +302,13 @@ term_flushln(struct termp *p) /* Right-pad. */ if (maxvis > vis + /* LINTED */ - ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) + ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) { + p->viscol += maxvis - vis; for ( ; vis < maxvis; vis++) putchar(' '); - else { /* ...or newline break. */ + } else { /* ...or newline break. */ putchar('\n'); + p->viscol = p->rmargin; for (i = 0; i < (int)p->rmargin; i++) putchar(' '); } @@ -315,7 +325,7 @@ term_newln(struct termp *p) { p->flags |= TERMP_NOSPACE; - if (0 == p->col) { + if (0 == p->col && 0 == p->viscol) { p->flags &= ~TERMP_NOLPAD; return; } @@ -335,6 +345,7 @@ term_vspace(struct termp *p) { term_newln(p); + p->viscol = 0; putchar('\n'); } --- mdoc_term.c Mon May 24 16:54:52 2010 +++ mdoc_term.c Mon May 24 19:10:03 2010 @@ -1014,14 +1010,14 @@ termp_it_post(DECL_ARGS) /* FALLTHROUGH */ case (LIST_inset): if (MDOC_BODY == n->type) - term_flushln(p); + term_newln(p); break; case (LIST_column): if (MDOC_HEAD == n->type) term_flushln(p); break; default: - term_flushln(p); + term_newln(p); break; } @@ -1633,12 +1629,10 @@ termp_bd_pre(DECL_ARGS) for (nn = n->child; nn; nn = nn->next) { p->flags |= TERMP_NOSPACE; print_mdoc_node(p, pair, m, nn); - if (NULL == nn->next) - continue; - if (nn->prev && nn->prev->line < nn->line) + if (NULL == nn->prev || + nn->prev->line < nn->line || + NULL == nn->next) term_flushln(p); - else if (NULL == nn->prev) - term_flushln(p); } p->tabwidth = tabwidth; @@ -1668,7 +1662,7 @@ termp_bd_post(DECL_ARGS) p->rmargin = p->maxrmargin = TERM_MAXMARGIN; p->flags |= TERMP_NOSPACE; - term_flushln(p); + term_newln(p); p->rmargin = rm; p->maxrmargin = rmax; --uAKRQypu60I7Lcqm Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="nested.in" .Dd $Mdocdate: April 12 2010 $ .Dt BL-NESTED 1 .Os .Sh NAME .Nm Bl-nested .Nd nested lists .Sh DESCRIPTION inset: .Bl -inset .It outer list .Bl -inset .It inner list .El .El inset compact: .Bl -inset -compact .It outer list .Bl -inset -compact .It inner list .El .El dash: .Bl -dash .It outer list .Bl -dash .It inner list .El .El dash compact: .Bl -dash -compact .It outer list .Bl -dash -compact .It inner list .El .El final text --uAKRQypu60I7Lcqm-- -- To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv