]> git.cameronkatri.com Git - mandoc.git/blobdiff - term.c
Support for TERMP_HANG in flushln(): -hang lists.
[mandoc.git] / term.c
diff --git a/term.c b/term.c
index 3b7fb4c0f44348b74a92cb53c6865ec086f1bc22..973ad2c2b1c7d3f66081b614fac9048d6e5e41bc 100644 (file)
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/*     $Id: term.c,v 1.80 2009/06/22 10:40:04 kristaps Exp $ */
+/*     $Id: term.c,v 1.84 2009/07/14 15:16:41 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -176,8 +176,7 @@ term_isopendelim(const char *p, int len)
  * Specifically, a line is whatever's in p->buf of length p->col, which
  * is zeroed after this function returns.
  *
- * The variables TERMP_NOLPAD, TERMP_LITERAL and TERMP_NOBREAK are of
- * critical importance here.  Their behaviour follows:
+ * The usage of termp:flags is as follows:
  *
  *  - TERMP_NOLPAD: when beginning to write the line, don't left-pad the
  *    offset value.  This is useful when doing columnar lists where the
@@ -187,7 +186,12 @@ term_isopendelim(const char *p, int len)
  *    columns.  In short: don't print a newline and instead pad to the
  *    right margin.  Used in conjunction with TERMP_NOLPAD.
  *
- *  - TERMP_NONOBREAK: don't newline when TERMP_NOBREAK is specified.
+ *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
+ *    the line is overrun, and don't pad-right if it's underrun.
+ *
+ *  - TERMP_HANG: like TERMP_DANGLE, but doesn't newline when
+ *    overruning, instead save the position and continue at that point
+ *    when the next invocation.
  *
  *  In-line line breaking:
  *
@@ -200,12 +204,16 @@ term_isopendelim(const char *p, int len)
  *  Otherwise, the line will break at the right margin.  Extremely long
  *  lines will cause the system to emit a warning (TODO: hyphenate, if
  *  possible).
+ *
+ *  FIXME: newline breaks occur (in groff) also occur when a single
+ *  space follows a NOBREAK!
  */
 void
 term_flushln(struct termp *p)
 {
        int              i, j;
-       size_t           vsz, vis, maxvis, mmax, bp;
+       size_t           vbl, vsz, vis, maxvis, mmax, bp;
+       static int       sv = -1;
 
        /*
         * First, establish the maximum columns of "visible" content.
@@ -220,6 +228,11 @@ term_flushln(struct termp *p)
        bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
        vis = 0;
 
+       if (sv >= 0) {
+               vis = (size_t)sv;
+               sv = -1;
+       }
+
        /*
         * If in the standard case (left-justified), then begin with our
         * indentation, otherwise (columns, etc.) just start spitting
@@ -250,35 +263,37 @@ term_flushln(struct termp *p)
                }
 
                /*
-                * Do line-breaking.  If we're greater than our
-                * break-point and already in-line, break to the next
-                * line and start writing.  If we're at the line start,
-                * then write out the word (TODO: hyphenate) and break
-                * in a subsequent loop invocation.
+                * Choose the number of blanks to prepend: no blank at the
+                * beginning of a line, one between words -- but do not
+                * actually write them yet.
                 */
+               vbl = (size_t)(0 == vis ? 0 : 1);
 
-               if ( ! (TERMP_NOBREAK & p->flags)) {
-                       if (vis && vis + vsz > bp) {
-                               putchar('\n');
+               /*
+                * Find out whether we would exceed the right margin.
+                * If so, break to the next line.  (TODO: hyphenate)
+                * Otherwise, write the chosen number of blanks now.
+                */
+               if (vis && vis + vbl + vsz > bp) {
+                       putchar('\n');
+                       if (TERMP_NOBREAK & p->flags) {
+                               for (j = 0; j < (int)p->rmargin; j++)
+                                       putchar(' ');
+                               vis = p->rmargin - p->offset;
+                       } else {
                                for (j = 0; j < (int)p->offset; j++)
                                        putchar(' ');
                                vis = 0;
-                       } 
-               } else if (vis && vis + vsz > bp) {
-                       putchar('\n');
-                       for (j = 0; j < (int)p->rmargin; j++)
+                       }
+               } else {
+                       for (j = 0; j < (int)vbl; j++)
                                putchar(' ');
-                       vis = p->rmargin - p->offset;
+                       vis += vbl;
                }
 
                /*
-                * Prepend a space if we're not already at the beginning
-                * of the line, then the word.
+                * Finally, write out the word.
                 */
-
-               if (0 < vis++)
-                       putchar(' ');
-
                for ( ; i < (int)p->col; i++) {
                        if (' ' == p->buf[i])
                                break;
@@ -292,12 +307,15 @@ term_flushln(struct termp *p)
         * cause a newline and offset at the right margin.
         */
 
-       if ((TERMP_NOBREAK & p->flags) && vis > maxvis) {
-               if ( ! (TERMP_NONOBREAK & p->flags)) {
+       if ((TERMP_NOBREAK & p->flags) && vis >= maxvis) {
+               if ( ! (TERMP_DANGLE & p->flags) &&
+                               ! (TERMP_HANG & p->flags)) {
                        putchar('\n');
                        for (i = 0; i < (int)p->rmargin; i++)
                                putchar(' ');
                }
+               if (TERMP_HANG & p->flags)
+                       sv = vis - maxvis;
                p->col = 0;
                return;
        }
@@ -308,8 +326,8 @@ term_flushln(struct termp *p)
         */
 
        if (p->flags & TERMP_NOBREAK) {
-               if ( ! (TERMP_NONOBREAK & p->flags))
-                       for ( ; vis <= maxvis; vis++)
+               if ( ! (TERMP_DANGLE & p->flags))
+                       for ( ; vis < maxvis; vis++)
                                putchar(' ');
        } else
                putchar('\n');
@@ -408,7 +426,8 @@ term_nescape(struct termp *p, const char *word, size_t len)
        size_t           sz;
        int              i;
 
-       if ((rhs = term_a2ascii(p->symtab, word, len, &sz))) 
+       rhs = term_a2ascii(p->symtab, word, len, &sz);
+       if (rhs)
                for (i = 0; i < (int)sz; i++) 
                        term_encodea(p, rhs[i]);
 }