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

Diff for /mandoc/term.c between version 1.189 and 1.201

version 1.189, 2011/05/15 14:50:01 version 1.201, 2011/09/21 09:57:13
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010, 2011 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
Line 33 
Line 33 
 #include "term.h"  #include "term.h"
 #include "main.h"  #include "main.h"
   
 static  void              spec(struct termp *, const char *, size_t);  static  void             adjbuf(struct termp *p, int);
 static  void              res(struct termp *, const char *, size_t);  static  void             bufferc(struct termp *, char);
 static  void              bufferc(struct termp *, char);  static  void             encode(struct termp *, const char *, size_t);
 static  void              adjbuf(struct termp *p, int);  static  void             encode1(struct termp *, int);
 static  void              encode(struct termp *, const char *, size_t);  
   
   
 void  void
 term_free(struct termp *p)  term_free(struct termp *p)
 {  {
Line 72  term_end(struct termp *p)
Line 70  term_end(struct termp *p)
         (*p->end)(p);          (*p->end)(p);
 }  }
   
   
 struct termp *  
 term_alloc(enum termenc enc)  
 {  
         struct termp    *p;  
   
         p = mandoc_calloc(1, sizeof(struct termp));  
         p->enc = enc;  
         return(p);  
 }  
   
   
 /*  /*
  * Flush a line of text.  A "line" is loosely defined as being something   * Flush a line of text.  A "line" is loosely defined as being something
  * that should be followed by a newline, regardless of whether it's   * that should be followed by a newline, regardless of whether it's
Line 93  term_alloc(enum termenc enc)
Line 79  term_alloc(enum termenc enc)
  *   *
  * The following flags may be specified:   * The following flags may be specified:
  *   *
  *  - TERMP_NOLPAD: when beginning to write the line, don't left-pad the  
  *    offset value.  This is useful when doing columnar lists where the  
  *    prior column has right-padded.  
  *  
  *  - TERMP_NOBREAK: this is the most important and is used when making   *  - TERMP_NOBREAK: this is the most important and is used when making
  *    columns.  In short: don't print a newline and instead pad to the   *    columns.  In short: don't print a newline and instead expect the
  *    right margin.  Used in conjunction with TERMP_NOLPAD.   *    next call to do the padding up to the start of the next column.
  *   *
  *  - TERMP_TWOSPACE: when padding, make sure there are at least two   *  - TERMP_TWOSPACE: make sure there is room for at least two space
  *    space characters of padding.  Otherwise, rather break the line.   *    characters of padding.  Otherwise, rather break the line.
  *   *
  *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and   *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
  *    the line is overrun, and don't pad-right if it's underrun.   *    the line is overrun, and don't pad-right if it's underrun.
  *   *
  *  - TERMP_HANG: like TERMP_DANGLE, but doesn't newline when   *  - TERMP_HANG: like TERMP_DANGLE, but doesn't newline when
  *    overruning, instead save the position and continue at that point   *    overrunning, instead save the position and continue at that point
  *    when the next invocation.   *    when the next invocation.
  *   *
  *  In-line line breaking:   *  In-line line breaking:
Line 148  term_flushln(struct termp *p)
Line 130  term_flushln(struct termp *p)
         bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;          bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
   
         /*          /*
          * Indent the first line of a paragraph.           * Calculate the required amount of padding.
          */           */
         vbl = p->flags & TERMP_NOLPAD ? (size_t)0 : p->offset;          vbl = p->offset + p->overstep > p->viscol ?
                 p->offset + p->overstep - p->viscol : 0;
   
         vis = vend = 0;          vis = vend = 0;
         i = 0;          i = 0;
Line 201  term_flushln(struct termp *p)
Line 184  term_flushln(struct termp *p)
                 if (vend > bp && 0 == jhy && vis > 0) {                  if (vend > bp && 0 == jhy && vis > 0) {
                         vend -= vis;                          vend -= vis;
                         (*p->endline)(p);                          (*p->endline)(p);
                           p->viscol = 0;
                         if (TERMP_NOBREAK & p->flags) {                          if (TERMP_NOBREAK & p->flags) {
                                 p->viscol = p->rmargin;                                  vbl = p->rmargin;
                                 (*p->advance)(p, p->rmargin);  
                                 vend += p->rmargin - p->offset;                                  vend += p->rmargin - p->offset;
                         } else {                          } else
                                 p->viscol = 0;  
                                 vbl = p->offset;                                  vbl = p->offset;
                         }  
   
                         /* Remove the p->overstep width. */                          /* Remove the p->overstep width. */
   
Line 250  term_flushln(struct termp *p)
Line 231  term_flushln(struct termp *p)
                         if (ASCII_HYPH == p->buf[i]) {                          if (ASCII_HYPH == p->buf[i]) {
                                 (*p->letter)(p, '-');                                  (*p->letter)(p, '-');
                                 p->viscol += (*p->width)(p, '-');                                  p->viscol += (*p->width)(p, '-');
                         } else {                                  continue;
                                 (*p->letter)(p, p->buf[i]);  
                                 p->viscol += (*p->width)(p, p->buf[i]);  
                         }                          }
   
                           (*p->letter)(p, p->buf[i]);
                           if (8 == p->buf[i])
                                   p->viscol -= (*p->width)(p, p->buf[i-1]);
                           else
                                   p->viscol += (*p->width)(p, p->buf[i]);
                 }                  }
                 vis = vend;                  vis = vend;
         }          }
Line 262  term_flushln(struct termp *p)
Line 247  term_flushln(struct termp *p)
          * If there was trailing white space, it was not printed;           * If there was trailing white space, it was not printed;
          * so reset the cursor position accordingly.           * so reset the cursor position accordingly.
          */           */
         vis -= vbl;          if (vis)
                   vis -= vbl;
   
         p->col = 0;          p->col = 0;
         p->overstep = 0;          p->overstep = 0;
Line 287  term_flushln(struct termp *p)
Line 273  term_flushln(struct termp *p)
                  * move it one step LEFT and flag the rest of the line                   * move it one step LEFT and flag the rest of the line
                  * to be longer.                   * to be longer.
                  */                   */
                 if (p->overstep >= -1) {                  if (p->overstep < -1)
                         assert((int)maxvis + p->overstep >= 0);  
                         maxvis += (size_t)p->overstep;  
                 } else  
                         p->overstep = 0;                          p->overstep = 0;
                   return;
   
         } else if (TERMP_DANGLE & p->flags)          } else if (TERMP_DANGLE & p->flags)
                 return;                  return;
   
         /* Right-pad. */          /* If the column was overrun, break the line. */
         if (maxvis > vis +          if (maxvis <= vis +
             ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) {              ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) {
                 p->viscol += maxvis - vis;  
                 (*p->advance)(p, maxvis - vis);  
                 vis += (maxvis - vis);  
         } else {        /* ...or newline break. */  
                 (*p->endline)(p);                  (*p->endline)(p);
                 p->viscol = p->rmargin;                  p->viscol = 0;
                 (*p->advance)(p, p->rmargin);  
         }          }
 }  }
   
Line 320  term_newln(struct termp *p)
Line 299  term_newln(struct termp *p)
 {  {
   
         p->flags |= TERMP_NOSPACE;          p->flags |= TERMP_NOSPACE;
         if (0 == p->col && 0 == p->viscol) {          if (p->col || p->viscol)
                 p->flags &= ~TERMP_NOLPAD;                  term_flushln(p);
                 return;  
         }  
         term_flushln(p);  
         p->flags &= ~TERMP_NOLPAD;  
 }  }
   
   
Line 344  term_vspace(struct termp *p)
Line 319  term_vspace(struct termp *p)
         (*p->endline)(p);          (*p->endline)(p);
 }  }
   
   
 static void  
 numbered(struct termp *p, const char *word, size_t len)  
 {  
         char             c;  
   
         if ('\0' != (c = mchars_num2char(word, len)))  
                 encode(p, &c, 1);  
 }  
   
   
 static void  
 spec(struct termp *p, const char *word, size_t len)  
 {  
         const char      *rhs;  
         size_t           sz;  
   
         rhs = mchars_spec2str(p->symtab, word, len, &sz);  
         if (rhs)  
                 encode(p, rhs, sz);  
         else if (1 == len)  
                 encode(p, word, len);  
 }  
   
   
 static void  
 res(struct termp *p, const char *word, size_t len)  
 {  
         const char      *rhs;  
         size_t           sz;  
   
         rhs = mchars_res2str(p->symtab, word, len, &sz);  
         if (rhs)  
                 encode(p, rhs, sz);  
 }  
   
   
 void  void
 term_fontlast(struct termp *p)  term_fontlast(struct termp *p)
 {  {
Line 445  term_fontpop(struct termp *p)
Line 383  term_fontpop(struct termp *p)
         p->fonti--;          p->fonti--;
 }  }
   
   
 /*  /*
  * Handle pwords, partial words, which may be either a single word or a   * Handle pwords, partial words, which may be either a single word or a
  * phrase that cannot be broken down (such as a literal string).  This   * phrase that cannot be broken down (such as a literal string).  This
Line 454  term_fontpop(struct termp *p)
Line 391  term_fontpop(struct termp *p)
 void  void
 term_word(struct termp *p, const char *word)  term_word(struct termp *p, const char *word)
 {  {
         const char      *seq;          const char      *seq, *cp;
         int              sz;          char             c;
           int              sz, uc;
         size_t           ssz;          size_t           ssz;
         enum mandoc_esc  esc;          enum mandoc_esc  esc;
   
Line 490  term_word(struct termp *p, const char *word)
Line 428  term_word(struct termp *p, const char *word)
                 if (ESCAPE_ERROR == esc)                  if (ESCAPE_ERROR == esc)
                         break;                          break;
   
                   if (TERMENC_ASCII != p->enc)
                           switch (esc) {
                           case (ESCAPE_UNICODE):
                                   uc = mchars_num2uc(seq + 1, sz - 1);
                                   if ('\0' == uc)
                                           break;
                                   encode1(p, uc);
                                   continue;
                           case (ESCAPE_SPECIAL):
                                   uc = mchars_spec2cp(p->symtab, seq, sz);
                                   if (uc <= 0)
                                           break;
                                   encode1(p, uc);
                                   continue;
                           default:
                                   break;
                           }
   
                 switch (esc) {                  switch (esc) {
                   case (ESCAPE_UNICODE):
                           encode1(p, '?');
                           break;
                 case (ESCAPE_NUMBERED):                  case (ESCAPE_NUMBERED):
                         numbered(p, seq, sz);                          c = mchars_num2char(seq, sz);
                           if ('\0' != c)
                                   encode(p, &c, 1);
                         break;                          break;
                 case (ESCAPE_PREDEF):  
                         res(p, seq, sz);  
                         break;  
                 case (ESCAPE_SPECIAL):                  case (ESCAPE_SPECIAL):
                         spec(p, seq, sz);                          cp = mchars_spec2str(p->symtab, seq, sz, &ssz);
                           if (NULL != cp)
                                   encode(p, cp, ssz);
                           else if (1 == ssz)
                                   encode(p, seq, sz);
                         break;                          break;
                 case (ESCAPE_FONTBOLD):                  case (ESCAPE_FONTBOLD):
                         term_fontrepl(p, TERMFONT_BOLD);                          term_fontrepl(p, TERMFONT_BOLD);
Line 506  term_word(struct termp *p, const char *word)
Line 468  term_word(struct termp *p, const char *word)
                 case (ESCAPE_FONTITALIC):                  case (ESCAPE_FONTITALIC):
                         term_fontrepl(p, TERMFONT_UNDER);                          term_fontrepl(p, TERMFONT_UNDER);
                         break;                          break;
                   case (ESCAPE_FONT):
                           /* FALLTHROUGH */
                 case (ESCAPE_FONTROMAN):                  case (ESCAPE_FONTROMAN):
                         term_fontrepl(p, TERMFONT_NONE);                          term_fontrepl(p, TERMFONT_NONE);
                         break;                          break;
Line 522  term_word(struct termp *p, const char *word)
Line 486  term_word(struct termp *p, const char *word)
         }          }
 }  }
   
   
 static void  static void
 adjbuf(struct termp *p, int sz)  adjbuf(struct termp *p, int sz)
 {  {
Line 536  adjbuf(struct termp *p, int sz)
Line 499  adjbuf(struct termp *p, int sz)
                 (p->buf, sizeof(int) * (size_t)p->maxcols);                  (p->buf, sizeof(int) * (size_t)p->maxcols);
 }  }
   
   
 static void  static void
 bufferc(struct termp *p, char c)  bufferc(struct termp *p, char c)
 {  {
Line 547  bufferc(struct termp *p, char c)
Line 509  bufferc(struct termp *p, char c)
         p->buf[p->col++] = c;          p->buf[p->col++] = c;
 }  }
   
   /*
    * See encode().
    * Do this for a single (probably unicode) value.
    * Does not check for non-decorated glyphs.
    */
   static void
   encode1(struct termp *p, int c)
   {
           enum termfont     f;
   
           if (p->col + 4 >= p->maxcols)
                   adjbuf(p, p->col + 4);
   
           f = term_fonttop(p);
   
           if (TERMFONT_NONE == f) {
                   p->buf[p->col++] = c;
                   return;
           } else if (TERMFONT_UNDER == f) {
                   p->buf[p->col++] = '_';
           } else
                   p->buf[p->col++] = c;
   
           p->buf[p->col++] = 8;
           p->buf[p->col++] = c;
   }
   
 static void  static void
 encode(struct termp *p, const char *word, size_t sz)  encode(struct termp *p, const char *word, size_t sz)
 {  {
Line 577  encode(struct termp *p, const char *word, size_t sz)
Line 565  encode(struct termp *p, const char *word, size_t sz)
                 adjbuf(p, p->col + 1 + (len * 3));                  adjbuf(p, p->col + 1 + (len * 3));
   
         for (i = 0; i < len; i++) {          for (i = 0; i < len; i++) {
                 if ( ! isgraph((unsigned char)word[i])) {                  if (ASCII_HYPH != word[i] &&
                       ! isgraph((unsigned char)word[i])) {
                         p->buf[p->col++] = word[i];                          p->buf[p->col++] = word[i];
                         continue;                          continue;
                 }                  }
   
                 if (TERMFONT_UNDER == f)                  if (TERMFONT_UNDER == f)
                         p->buf[p->col++] = '_';                          p->buf[p->col++] = '_';
                   else if (ASCII_HYPH == word[i])
                           p->buf[p->col++] = '-';
                 else                  else
                         p->buf[p->col++] = word[i];                          p->buf[p->col++] = word[i];
   
Line 592  encode(struct termp *p, const char *word, size_t sz)
Line 583  encode(struct termp *p, const char *word, size_t sz)
         }          }
 }  }
   
   
 size_t  size_t
 term_len(const struct termp *p, size_t sz)  term_len(const struct termp *p, size_t sz)
 {  {
Line 605  size_t
Line 595  size_t
 term_strlen(const struct termp *p, const char *cp)  term_strlen(const struct termp *p, const char *cp)
 {  {
         size_t           sz, rsz, i;          size_t           sz, rsz, i;
         int              ssz;          int              ssz, c;
         const char      *seq, *rhs;          const char      *seq, *rhs;
           enum mandoc_esc  esc;
         static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' };          static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' };
   
         /*          /*
Line 621  term_strlen(const struct termp *p, const char *cp)
Line 612  term_strlen(const struct termp *p, const char *cp)
                 for (i = 0; i < rsz; i++)                  for (i = 0; i < rsz; i++)
                         sz += (*p->width)(p, *cp++);                          sz += (*p->width)(p, *cp++);
   
                   c = 0;
                 switch (*cp) {                  switch (*cp) {
                 case ('\\'):                  case ('\\'):
                         cp++;                          cp++;
                         switch (mandoc_escape(&cp, &seq, &ssz)) {                          esc = mandoc_escape(&cp, &seq, &ssz);
                         case (ESCAPE_ERROR):                          if (ESCAPE_ERROR == esc)
                                 return(sz);                                  return(sz);
                         case (ESCAPE_PREDEF):  
                                 rhs = mchars_res2str                          if (TERMENC_ASCII != p->enc)
                                         (p->symtab, seq, ssz, &rsz);                                  switch (esc) {
                                   case (ESCAPE_UNICODE):
                                           c = mchars_num2uc
                                                   (seq + 1, ssz - 1);
                                           if ('\0' == c)
                                                   break;
                                           sz += (*p->width)(p, c);
                                           continue;
                                   case (ESCAPE_SPECIAL):
                                           c = mchars_spec2cp
                                                   (p->symtab, seq, ssz);
                                           if (c <= 0)
                                                   break;
                                           sz += (*p->width)(p, c);
                                           continue;
                                   default:
                                           break;
                                   }
   
                           rhs = NULL;
   
                           switch (esc) {
                           case (ESCAPE_UNICODE):
                                   sz += (*p->width)(p, '?');
                                 break;                                  break;
                           case (ESCAPE_NUMBERED):
                                   c = mchars_num2char(seq, ssz);
                                   if ('\0' != c)
                                           sz += (*p->width)(p, c);
                                   break;
                         case (ESCAPE_SPECIAL):                          case (ESCAPE_SPECIAL):
                                 rhs = mchars_spec2str                                  rhs = mchars_spec2str
                                         (p->symtab, seq, ssz, &rsz);                                          (p->symtab, seq, ssz, &rsz);
Line 642  term_strlen(const struct termp *p, const char *cp)
Line 662  term_strlen(const struct termp *p, const char *cp)
                                 rsz = ssz;                                  rsz = ssz;
                                 break;                                  break;
                         default:                          default:
                                 rhs = NULL;  
                                 break;                                  break;
                         }                          }
   

Legend:
Removed from v.1.189  
changed lines
  Added in v.1.201

CVSweb