[BACK]Return to term.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/term.c between version 1.280 and 1.291

version 1.280, 2019/01/15 12:16:18 version 1.291, 2023/04/28 19:11:04
Line 1 
Line 1 
 /*      $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-2019 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 38  static void   bufferc(struct termp *, char);
Line 38  static void   bufferc(struct termp *, char);
 static  void             encode(struct termp *, const char *, size_t);  static  void             encode(struct termp *, const char *, size_t);
 static  void             encode1(struct termp *, int);  static  void             encode1(struct termp *, int);
 static  void             endline(struct termp *);  static  void             endline(struct termp *);
 static  void             term_field(struct termp *, size_t, size_t,  static  void             term_field(struct termp *, size_t, size_t);
                                 size_t, size_t);  
 static  void             term_fill(struct termp *, size_t *, size_t *,  static  void             term_fill(struct termp *, size_t *, size_t *,
                                 size_t);                                  size_t);
   
Line 59  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 127  term_flushln(struct termp *p)
Line 127  term_flushln(struct termp *p)
                  * and with the BRNEVER flag, never break it at all.                   * and with the BRNEVER flag, never break it at all.
                  */                   */
   
                 vtarget = p->flags & TERMP_BRNEVER ? SIZE_MAX :                  vtarget = (p->flags & TERMP_NOBREAK) == 0 ? vfield :
                     (p->flags & TERMP_NOBREAK) == 0 ? vfield :  
                     p->maxrmargin > p->viscol + vbl ?                      p->maxrmargin > p->viscol + vbl ?
                     p->maxrmargin - p->viscol - vbl : 0;                      p->maxrmargin - p->viscol - vbl : 0;
   
Line 137  term_flushln(struct termp *p)
Line 136  term_flushln(struct termp *p)
                  * If there is whitespace only, print nothing.                   * If there is whitespace only, print nothing.
                  */                   */
   
                 term_fill(p, &nbr, &vbr, vtarget);                  term_fill(p, &nbr, &vbr,
                       p->flags & TERMP_BRNEVER ? SIZE_MAX : vtarget);
                 if (nbr == 0)                  if (nbr == 0)
                         break;                          break;
   
Line 156  term_flushln(struct termp *p)
Line 156  term_flushln(struct termp *p)
   
                 /* Finally, print the field content. */                  /* Finally, print the field content. */
   
                 term_field(p, vbl, nbr, vbr, vtarget);                  term_field(p, vbl, nbr);
                   if (vbr < vtarget)
                           p->tcol->taboff += vbr;
                   else
                           p->tcol->taboff += vtarget;
                   p->tcol->taboff += (*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 176  term_flushln(struct termp *p)
Line 181  term_flushln(struct termp *p)
                                         vbr += (*p->width)(p, ' ');                                          vbr += (*p->width)(p, ' ');
                                 continue;                                  continue;
                         case '\n':                          case '\n':
                           case ASCII_NBRZW:
                         case ASCII_BREAK:                          case ASCII_BREAK:
                           case ASCII_TABREF:
                                 continue;                                  continue;
                         default:                          default:
                                 break;                                  break;
Line 187  term_flushln(struct termp *p)
Line 194  term_flushln(struct termp *p)
                         break;                          break;
   
                 /*                  /*
                  * At the location of an automtic line break, input                   * At the location of an automatic line break, input
                  * space characters are consumed by the line break.                   * space characters are consumed by the line break.
                  */                   */
   
Line 207  term_flushln(struct termp *p)
Line 214  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 258  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
Line 264  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
         size_t   vn;        /* Visual position of the next character. */          size_t   vn;        /* Visual position of the next character. */
         int      breakline; /* Break at the end of this word. */          int      breakline; /* Break at the end of this word. */
         int      graph;     /* Last character was non-blank. */          int      graph;     /* Last character was non-blank. */
           int      taboff;    /* Temporary offset for literal tabs. */
   
         *nbr = *vbr = vis = 0;          *nbr = *vbr = vis = 0;
         breakline = graph = 0;          breakline = graph = 0;
           taboff = p->tcol->taboff;
         for (ic = p->tcol->col; ic < p->tcol->lastcol; ic++) {          for (ic = p->tcol->col; ic < p->tcol->lastcol; ic++) {
                 switch (p->tcol->buf[ic]) {                  switch (p->tcol->buf[ic]) {
                 case '\b':  /* Escape \o (overstrike) or backspace markup. */                  case '\b':  /* Escape \o (overstrike) or backspace markup. */
Line 268  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
Line 276  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;  
                         }  
                         /* 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 315  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
Line 314  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
                         *vbr = vis;                          *vbr = vis;
                         continue;                          continue;
   
                 case ASCII_NBRSP:  /* Non-breakable space. */                  case ASCII_TABREF:
                         p->tcol->buf[ic] = ' ';                          taboff = -vis - (*p->width)(p, ' ');
                         /* FALLTHROUGH */                          continue;
                 default:  /* Printable character. */  
                   default:
                           switch (p->tcol->buf[ic]) {
                           case '\t':
                                   if (taboff < 0 && (size_t)-taboff > vis)
                                           vis = 0;
                                   else
                                           vis += taboff;
                                   vis = term_tab_next(vis);
                                   vis -= 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 343  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
Line 360  term_fill(struct termp *p, size_t *nbr, size_t *vbr, s
 /*  /*
  * Print the contents of one field   * Print the contents of one field
  * with an indentation of        vbl      visual columns,   * with an indentation of        vbl      visual columns,
  * an input string length of     nbr      characters,   * and an input string length of nbr      characters.
  * an output width of            vbr      visual columns,  
  * and a desired field width of  vtarget  visual columns.  
  */   */
 static void  static void
 term_field(struct termp *p, size_t vbl, size_t nbr, size_t vbr, size_t vtarget)  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. */          int      taboff; /* Temporary offset for literal tabs. */
   
         vis = 0;          vis = 0;
           taboff = p->tcol->taboff;
         for (ic = p->tcol->col; ic < nbr; ic++) {          for (ic = p->tcol->col; ic < nbr; ic++) {
   
                 /*                  /*
Line 366  term_field(struct termp *p, size_t vbl, size_t nbr, si
Line 383  term_field(struct termp *p, size_t vbl, size_t nbr, si
                 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 ASCII_TABREF:
                         vn = term_tab_next(vis);                          taboff = -vis - (*p->width)(p, ' ');
                         vbl += vn - vis;  
                         vis = vn;  
                         continue;                          continue;
                   case '\t':
                 case ' ':                  case ' ':
                 case ASCII_NBRSP:                  case ASCII_NBRSP:
                         dv = (*p->width)(p, ' ');                          if (p->tcol->buf[ic] == '\t') {
                                   if (taboff < 0 && (size_t)-taboff > vis)
                                           vt = 0;
                                   else
                                           vt = vis + taboff;
                                   dv = term_tab_next(vt) - vt;
                           } else
                                   dv = (*p->width)(p, ' ');
                         vbl += dv;                          vbl += dv;
                         vis += dv;                          vis += dv;
                         continue;                          continue;
Line 436  endline(struct termp *p)
Line 460  endline(struct termp *p)
 void  void
 term_newln(struct termp *p)  term_newln(struct termp *p)
 {  {
   
         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);
           p->tcol->taboff = 0;
 }  }
   
 /*  /*
Line 572  term_word(struct termp *p, const char *word)
Line 596  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 626  term_word(struct termp *p, const char *word)
Line 657  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 634  term_word(struct termp *p, const char *word)
Line 669  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 727  term_word(struct termp *p, const char *word)
Line 774  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 774  bufferc(struct termp *p, char c)
Line 824  bufferc(struct termp *p, char c)
                 p->tcol->lastcol = p->col;                  p->tcol->lastcol = p->col;
 }  }
   
   void
   term_tab_ref(struct termp *p)
   {
           if (p->tcol->lastcol && p->tcol->lastcol <= p->col &&
               (p->flags & TERMP_NOBUF) == 0)
                   bufferc(p, ASCII_TABREF);
   }
   
 /*  /*
  * See encode().   * See encode().
  * Do this for a single (probably unicode) value.   * Do this for a single (probably unicode) value.
Line 918  term_strlen(const struct termp *p, const char *cp)
Line 976  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, ASCII_TABREF, '\0' };
   
         /*          /*
          * Account for escaped sequences within string length           * Account for escaped sequences within string length

Legend:
Removed from v.1.280  
changed lines
  Added in v.1.291

CVSweb