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

Diff for /mandoc/term.c between version 1.71 and 1.85

version 1.71, 2009/03/31 13:50:19 version 1.85, 2009/07/14 15:49:44
Line 1 
Line 1 
 /* $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>   * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *   *
  * 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   * purpose with or without fee is hereby granted, provided that the above
  * above copyright notice and this permission notice appear in all   * copyright notice and this permission notice appear in all copies.
  * copies.  
  *   *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  * PERFORMANCE OF THIS SOFTWARE.  
  */   */
 #include <assert.h>  #include <assert.h>
 #include <err.h>  #include <err.h>
Line 39  static void    term_pescape(struct termp *, 
Line 37  static void    term_pescape(struct termp *, 
 static  void              term_nescape(struct termp *,  static  void              term_nescape(struct termp *,
                                 const char *, size_t);                                  const char *, size_t);
 static  void              term_chara(struct termp *, char);  static  void              term_chara(struct termp *, char);
 static  void              term_stringa(struct termp *,  static  void              term_encodea(struct termp *, char);
                                 const char *, size_t);  
 static  int               term_isopendelim(const char *, int);  static  int               term_isopendelim(const char *, int);
 static  int               term_isclosedelim(const char *, int);  static  int               term_isclosedelim(const char *, int);
   
Line 54  ascii_alloc(void)
Line 51  ascii_alloc(void)
   
   
 int  int
 terminal_run(void *arg, const struct man *man,  terminal_man(void *arg, const struct man *man)
                 const struct mdoc *mdoc)  
 {  {
         struct termp    *p;          struct termp    *p;
   
         p = (struct termp *)arg;          p = (struct termp *)arg;
   
         if (NULL == p->symtab)          if (NULL == p->symtab)
                 p->symtab = term_ascii2htab();                  p->symtab = term_ascii2htab();
   
         if (man)          return(man_run(p, man));
                 return(man_run(p, man));  }
         if (mdoc)  
                 return(mdoc_run(p, mdoc));  
   
         return(1);  
   int
   terminal_mdoc(void *arg, const struct mdoc *mdoc)
   {
           struct termp    *p;
   
           p = (struct termp *)arg;
           if (NULL == p->symtab)
                   p->symtab = term_ascii2htab();
   
           return(mdoc_run(p, mdoc));
 }  }
   
   
Line 173  term_isopendelim(const char *p, int len)
Line 176  term_isopendelim(const char *p, int len)
  * Specifically, a line is whatever's in p->buf of length p->col, which   * Specifically, a line is whatever's in p->buf of length p->col, which
  * is zeroed after this function returns.   * is zeroed after this function returns.
  *   *
  * The variables TERMP_NOLPAD, TERMP_LITERAL and TERMP_NOBREAK are of   * The usage of termp:flags is as follows:
  * critical importance here.  Their behaviour follows:  
  *   *
  *  - TERMP_NOLPAD: when beginning to write the line, don't left-pad the   *  - TERMP_NOLPAD: when beginning to write the line, don't left-pad the
  *    offset value.  This is useful when doing columnar lists where the   *    offset value.  This is useful when doing columnar lists where the
Line 184  term_isopendelim(const char *p, int len)
Line 186  term_isopendelim(const char *p, int len)
  *    columns.  In short: don't print a newline and instead pad to the   *    columns.  In short: don't print a newline and instead pad to the
  *    right margin.  Used in conjunction with TERMP_NOLPAD.   *    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:   *  In-line line breaking:
  *   *
  *  If TERMP_NOBREAK is specified and the line overruns the right   *  If TERMP_NOBREAK is specified and the line overruns the right
Line 197  term_isopendelim(const char *p, int len)
Line 204  term_isopendelim(const char *p, int len)
  *  Otherwise, the line will break at the right margin.  Extremely long   *  Otherwise, the line will break at the right margin.  Extremely long
  *  lines will cause the system to emit a warning (TODO: hyphenate, if   *  lines will cause the system to emit a warning (TODO: hyphenate, if
  *  possible).   *  possible).
    *
    *  FIXME: newline breaks occur (in groff) also occur when a single
    *  space follows a NOBREAK!
  */   */
 void  void
 term_flushln(struct termp *p)  term_flushln(struct termp *p)
 {  {
         int              i, j;          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.           * First, establish the maximum columns of "visible" content.
Line 217  term_flushln(struct termp *p)
Line 228  term_flushln(struct termp *p)
         bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;          bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
         vis = 0;          vis = 0;
   
           if (sv >= 0) {
                   vis = (size_t)sv;
                   sv = -1;
           }
   
         /*          /*
          * If in the standard case (left-justified), then begin with our           * If in the standard case (left-justified), then begin with our
          * indentation, otherwise (columns, etc.) just start spitting           * indentation, otherwise (columns, etc.) just start spitting
Line 247  term_flushln(struct termp *p)
Line 263  term_flushln(struct termp *p)
                 }                  }
   
                 /*                  /*
                  * Do line-breaking.  If we're greater than our                   * Choose the number of blanks to prepend: no blank at the
                  * break-point and already in-line, break to the next                   * beginning of a line, one between words -- but do not
                  * line and start writing.  If we're at the line start,                   * actually write them yet.
                  * then write out the word (TODO: hyphenate) and break  
                  * in a subsequent loop invocation.  
                  */                   */
                   vbl = (size_t)(0 == vis ? 0 : 1);
   
                 if ( ! (TERMP_NOBREAK & p->flags)) {                  /*
                         if (vis && vis + vsz > bp) {                   * Find out whether we would exceed the right margin.
                                 putchar('\n');                   * 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++)                                  for (j = 0; j < (int)p->offset; j++)
                                         putchar(' ');                                          putchar(' ');
                                 vis = 0;                                  vis = 0;
                         }                          }
                 } else if (vis && vis + vsz > bp) {                  } else {
                         putchar('\n');                          for (j = 0; j < (int)vbl; j++)
                         for (j = 0; j < (int)p->rmargin; j++)  
                                 putchar(' ');                                  putchar(' ');
                         vis = p->rmargin - p->offset;                          vis += vbl;
                 }                  }
   
                 /*                  /*
                  * Write out the word and a trailing space.  Omit the                   * Finally, write out the word.
                  * space if we're the last word in the line or beyond  
                  * our breakpoint.  
                  */                   */
   
                 for ( ; i < (int)p->col; i++) {                  for ( ; i < (int)p->col; i++) {
                         if (' ' == p->buf[i])                          if (' ' == p->buf[i])
                                 break;                                  break;
                         putchar(p->buf[i]);                          putchar(p->buf[i]);
                 }                  }
                 vis += vsz;                  vis += vsz;
                 if (i < (int)p->col && vis <= bp) {  
                         putchar(' ');  
                         vis++;  
                 }  
         }          }
   
         /*          /*
Line 292  term_flushln(struct termp *p)
Line 308  term_flushln(struct termp *p)
          */           */
   
         if ((TERMP_NOBREAK & p->flags) && vis >= maxvis) {          if ((TERMP_NOBREAK & p->flags) && vis >= maxvis) {
                 if ( ! (TERMP_NONOBREAK & p->flags)) {                  if ( ! (TERMP_DANGLE & p->flags) &&
                                   ! (TERMP_HANG & p->flags)) {
                         putchar('\n');                          putchar('\n');
                         for (i = 0; i < (int)p->rmargin; i++)                          for (i = 0; i < (int)p->rmargin; i++)
                                 putchar(' ');                                  putchar(' ');
                 }                  }
                   if (TERMP_HANG & p->flags)
                           sv = (int)(vis - maxvis);
                 p->col = 0;                  p->col = 0;
                 return;                  return;
         }          }
Line 307  term_flushln(struct termp *p)
Line 326  term_flushln(struct termp *p)
          */           */
   
         if (p->flags & TERMP_NOBREAK) {          if (p->flags & TERMP_NOBREAK) {
                 if ( ! (TERMP_NONOBREAK & p->flags))                  if ( ! (TERMP_DANGLE & p->flags))
                         for ( ; vis < maxvis; vis++)                          for ( ; vis < maxvis; vis++)
                                 putchar(' ');                                  putchar(' ');
         } else          } else
Line 405  term_nescape(struct termp *p, const char *word, size_t
Line 424  term_nescape(struct termp *p, const char *word, size_t
 {  {
         const char      *rhs;          const char      *rhs;
         size_t           sz;          size_t           sz;
           int              i;
   
         if (NULL == (rhs = term_a2ascii(p->symtab, word, len, &sz)))          rhs = term_a2ascii(p->symtab, word, len, &sz);
                 return;          if (rhs)
         term_stringa(p, rhs, sz);                  for (i = 0; i < (int)sz; i++)
                           term_encodea(p, rhs[i]);
 }  }
   
   
Line 517  term_pword(struct termp *p, const char *word, int len)
Line 538  term_pword(struct termp *p, const char *word, int len)
          * before the word.           * before the word.
          */           */
   
         for (i = 0; i < len; i++) {          for (i = 0; i < len; i++)
                 if ('\\' == word[i]) {                  if ('\\' == word[i])
                         term_pescape(p, word, &i, len);                          term_pescape(p, word, &i, len);
                         continue;                  else
                 }                          term_encodea(p, word[i]);
   
                 if (TERMP_STYLE & p->flags) {  
                         if (TERMP_BOLD & p->flags) {  
                                 term_chara(p, word[i]);  
                                 term_chara(p, 8);  
                         }  
                         if (TERMP_UNDER & p->flags) {  
                                 term_chara(p, '_');  
                                 term_chara(p, 8);  
                         }  
                 }  
   
                 term_chara(p, word[i]);  
         }  
   
         if (term_isopendelim(word, len))          if (term_isopendelim(word, len))
                 p->flags |= TERMP_NOSPACE;                  p->flags |= TERMP_NOSPACE;
 }  }
   
   
 /*  /*
  * Like term_chara() but for arbitrary-length buffers.  Resize the  
  * buffer by a factor of two (if the buffer is less than that) or the  
  * buffer's size.  
  */  
 static void  
 term_stringa(struct termp *p, const char *c, size_t sz)  
 {  
         size_t           s;  
   
         if (0 == sz)  
                 return;  
   
         assert(c);  
         if (p->col + sz >= p->maxcols) {  
                 if (0 == p->maxcols)  
                         p->maxcols = 256;  
                 s = sz > p->maxcols * 2 ? sz : p->maxcols * 2;  
                 p->buf = realloc(p->buf, s);  
                 if (NULL == p->buf)  
                         err(1, "realloc");  
                 p->maxcols = s;  
         }  
   
         (void)memcpy(&p->buf[(int)p->col], c, sz);  
         p->col += sz;  
 }  
   
   
 /*  
  * Insert a single character into the line-buffer.  If the buffer's   * Insert a single character into the line-buffer.  If the buffer's
  * space is exceeded, then allocate more space by doubling the buffer   * space is exceeded, then allocate more space by doubling the buffer
  * size.   * size.
Line 593  term_chara(struct termp *p, char c)
Line 571  term_chara(struct termp *p, char c)
         p->buf[(int)(p->col)++] = c;          p->buf[(int)(p->col)++] = c;
 }  }
   
   
   static void
   term_encodea(struct termp *p, char c)
   {
   
           if (TERMP_STYLE & p->flags) {
                   if (TERMP_BOLD & p->flags) {
                           term_chara(p, c);
                           term_chara(p, 8);
                   }
                   if (TERMP_UNDER & p->flags) {
                           term_chara(p, '_');
                           term_chara(p, 8);
                   }
           }
           term_chara(p, c);
   }

Legend:
Removed from v.1.71  
changed lines
  Added in v.1.85

CVSweb