]> git.cameronkatri.com Git - mandoc.git/blobdiff - term.c
Implement the \\$@ escape sequence (insert all macro arguments,
[mandoc.git] / term.c
diff --git a/term.c b/term.c
index b97b9be3956ef47dc09832b3c1cc9cd4cf7e3c9a..0b7222896b7b024c8404b2fe955c3bd245bd97e4 100644 (file)
--- a/term.c
+++ b/term.c
@@ -1,7 +1,7 @@
-/*     $Id: term.c,v 1.269 2017/06/12 19:05:47 schwarze Exp $ */
+/*     $Id: term.c,v 1.275 2018/08/16 13:54:06 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -116,6 +116,7 @@ term_flushln(struct termp *p)
        size_t           jhy;   /* last hyph before overflow w/r/t j */
        size_t           maxvis; /* output position of visible boundary */
        int              ntab;  /* number of tabs to prepend */
+       int              breakline; /* after this word */
 
        vbl = (p->flags & TERMP_NOPAD) || p->tcol->offset < p->viscol ?
            0 : p->tcol->offset - p->viscol;
@@ -128,7 +129,7 @@ term_flushln(struct termp *p)
            p->maxrmargin - p->viscol - vbl : 0;
        vis = vend = 0;
 
-       if ((p->flags && TERMP_MULTICOL) == 0)
+       if ((p->flags & TERMP_MULTICOL) == 0)
                p->tcol->col = 0;
        while (p->tcol->col < p->tcol->lastcol) {
 
@@ -155,7 +156,13 @@ term_flushln(struct termp *p)
                 */
 
                jhy = 0;
+               breakline = 0;
                for (j = p->tcol->col; j < p->tcol->lastcol; j++) {
+                       if (p->tcol->buf[j] == '\n') {
+                               if ((p->flags & TERMP_BRIND) == 0)
+                                       breakline = 1;
+                               continue;
+                       }
                        if (p->tcol->buf[j] == ' ' || p->tcol->buf[j] == '\t')
                                break;
 
@@ -221,6 +228,8 @@ term_flushln(struct termp *p)
                for ( ; p->tcol->col < p->tcol->lastcol; p->tcol->col++) {
                        if (vend > bp && jhy > 0 && p->tcol->col > jhy)
                                break;
+                       if (p->tcol->buf[p->tcol->col] == '\n')
+                               continue;
                        if (p->tcol->buf[p->tcol->col] == '\t')
                                break;
                        if (p->tcol->buf[p->tcol->col] == ' ') {
@@ -260,6 +269,26 @@ term_flushln(struct termp *p)
                                    p->tcol->buf[p->tcol->col]);
                }
                vis = vend;
+
+               if (breakline == 0)
+                       continue;
+
+               /* Explicitly requested output line break. */
+
+               if (p->flags & TERMP_MULTICOL)
+                       return;
+
+               endline(p);
+               breakline = 0;
+               vis = vend = 0;
+
+               /* Re-establish indentation. */
+
+               vbl = p->tcol->offset;
+               maxvis = p->tcol->rmargin > vbl ?
+                   p->tcol->rmargin - vbl : 0;
+               bp = !(p->flags & TERMP_NOBREAK) ? maxvis :
+                   p->maxrmargin > vbl ?  p->maxrmargin - vbl : 0;
        }
 
        /*
@@ -487,16 +516,34 @@ term_word(struct termp *p, const char *word)
                case ESCAPE_FONTPREV:
                        term_fontlast(p);
                        continue;
+               case ESCAPE_BREAK:
+                       bufferc(p, '\n');
+                       continue;
                case ESCAPE_NOSPACE:
                        if (p->flags & TERMP_BACKAFTER)
                                p->flags &= ~TERMP_BACKAFTER;
                        else if (*word == '\0')
                                p->flags |= (TERMP_NOSPACE | TERMP_NONEWLINE);
                        continue;
+               case ESCAPE_DEVICE:
+                       if (p->type == TERMTYPE_PDF)
+                               encode(p, "pdf", 3);
+                       else if (p->type == TERMTYPE_PS)
+                               encode(p, "ps", 2);
+                       else if (p->enc == TERMENC_ASCII)
+                               encode(p, "ascii", 5);
+                       else
+                               encode(p, "utf8", 4);
+                       continue;
                case ESCAPE_HORIZ:
+                       if (*seq == '|') {
+                               seq++;
+                               uc = -p->col;
+                       } else
+                               uc = 0;
                        if (a2roffsu(seq, &su, SCALE_EM) == NULL)
                                continue;
-                       uc = term_hspan(p, &su) / 24;
+                       uc += term_hen(p, &su);
                        if (uc > 0)
                                while (uc-- > 0)
                                        bufferc(p, ASCII_NBRSP);
@@ -515,19 +562,19 @@ term_word(struct termp *p, const char *word)
                        }
                        continue;
                case ESCAPE_HLINE:
-                       if ((seq = a2roffsu(seq, &su, SCALE_EM)) == NULL)
+                       if ((cp = a2roffsu(seq, &su, SCALE_EM)) == NULL)
                                continue;
-                       uc = term_hspan(p, &su) / 24;
+                       uc = term_hen(p, &su);
                        if (uc <= 0) {
                                if (p->tcol->rmargin <= p->tcol->offset)
                                        continue;
                                lsz = p->tcol->rmargin - p->tcol->offset;
                        } else
                                lsz = uc;
-                       if (*seq == '\0')
+                       if (*cp == seq[-1])
                                uc = -1;
-                       else if (*seq == '\\') {
-                               seq++;
+                       else if (*cp == '\\') {
+                               seq = cp + 1;
                                esc = mandoc_escape(&seq, &cp, &sz);
                                switch (esc) {
                                case ESCAPE_UNICODE:
@@ -544,7 +591,7 @@ term_word(struct termp *p, const char *word)
                                        break;
                                }
                        } else
-                               uc = *seq;
+                               uc = *cp;
                        if (uc < 0x20 || (uc > 0x7E && uc < 0xA0))
                                uc = '_';
                        if (p->enc == TERMENC_ASCII) {
@@ -823,6 +870,21 @@ term_strlen(const struct termp *p, const char *cp)
                                                sz += cond_width(p, uc, &skip);
                                }
                                continue;
+                       case ESCAPE_DEVICE:
+                               if (p->type == TERMTYPE_PDF) {
+                                       rhs = "pdf";
+                                       rsz = 3;
+                               } else if (p->type == TERMTYPE_PS) {
+                                       rhs = "ps";
+                                       rsz = 2;
+                               } else if (p->enc == TERMENC_ASCII) {
+                                       rhs = "ascii";
+                                       rsz = 5;
+                               } else {
+                                       rhs = "utf8";
+                                       rsz = 4;
+                               }
+                               break;
                        case ESCAPE_SKIPCHAR:
                                skip = 1;
                                continue;
@@ -934,7 +996,7 @@ term_vspan(const struct termp *p, const struct roffsu *su)
 }
 
 /*
- * Convert a scaling width to basic units, rounding down.
+ * Convert a scaling width to basic units, rounding towards 0.
  */
 int
 term_hspan(const struct termp *p, const struct roffsu *su)
@@ -942,3 +1004,17 @@ term_hspan(const struct termp *p, const struct roffsu *su)
 
        return (*p->hspan)(p, su);
 }
+
+/*
+ * Convert a scaling width to basic units, rounding to closest.
+ */
+int
+term_hen(const struct termp *p, const struct roffsu *su)
+{
+       int bu;
+
+       if ((bu = (*p->hspan)(p, su)) >= 0)
+               return (bu + 11) / 24;
+       else
+               return -((-bu + 11) / 24);
+}