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

Diff for /mandoc/term.c between version 1.139 and 1.144

version 1.139, 2010/05/24 21:51:20 version 1.144, 2010/06/08 09:20:08
Line 22 
Line 22 
   
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
   #include <getopt.h>
   #include <stdint.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 35 
Line 37 
 #include "mdoc.h"  #include "mdoc.h"
 #include "main.h"  #include "main.h"
   
 static  struct termp     *term_alloc(enum termenc, size_t);  #define PS_CHAR_WIDTH     6
   #define PS_CHAR_HEIGHT    12
   #define PS_CHAR_TOPMARG  (792 - 24)
   #define PS_CHAR_TOP      (PS_CHAR_TOPMARG - 36)
   #define PS_CHAR_LEFT      36
   #define PS_CHAR_BOTMARG   24
   #define PS_CHAR_BOT      (PS_CHAR_BOTMARG + 36)
   
   static  struct termp     *alloc(char *, enum termenc, enum termtype);
 static  void              term_free(struct termp *);  static  void              term_free(struct termp *);
 static  void              spec(struct termp *, const char *, size_t);  static  void              spec(struct termp *, const char *, size_t);
 static  void              res(struct termp *, const char *, size_t);  static  void              res(struct termp *, const char *, size_t);
Line 43  static void    buffera(struct termp *, const char *, s
Line 53  static void    buffera(struct termp *, const char *, s
 static  void              bufferc(struct termp *, char);  static  void              bufferc(struct termp *, char);
 static  void              adjbuf(struct termp *p, size_t);  static  void              adjbuf(struct termp *p, size_t);
 static  void              encode(struct termp *, const char *, size_t);  static  void              encode(struct termp *, const char *, size_t);
   static  void              advance(struct termp *, size_t);
   static  void              endline(struct termp *);
   static  void              letter(struct termp *, char);
   static  void              pageopen(struct termp *);
   
   
 void *  void *
 ascii_alloc(size_t width)  ascii_alloc(char *outopts)
 {  {
   
         return(term_alloc(TERMENC_ASCII, width));          return(alloc(outopts, TERMENC_ASCII, TERMTYPE_CHAR));
 }  }
   
   
   void *
   ps_alloc(void)
   {
   
           return(alloc(NULL, TERMENC_ASCII, TERMTYPE_PS));
   }
   
   
 void  void
 terminal_free(void *arg)  terminal_free(void *arg)
 {  {
Line 69  term_free(struct termp *p)
Line 91  term_free(struct termp *p)
                 free(p->buf);                  free(p->buf);
         if (p->symtab)          if (p->symtab)
                 chars_free(p->symtab);                  chars_free(p->symtab);
   
         free(p);          free(p);
 }  }
   
   
   /*
    * Push a single letter into our output engine.
    */
   static void
   letter(struct termp *p, char c)
   {
   
           if (TERMTYPE_CHAR == p->type) {
                   /*
                    * If using the terminal device, just push the letter
                    * out into the screen.
                    */
                   putchar(c);
                   return;
           }
   
           if ( ! (PS_INLINE & p->psstate)) {
                   /*
                    * If we're not in a PostScript "word" context, then
                    * open one now at the current cursor.
                    */
                   printf("%zu %zu moveto\n", p->pscol, p->psrow);
                   putchar('(');
                   p->psstate |= PS_INLINE;
           }
   
           /*
            * We need to escape these characters as per the PostScript
            * specification.  We would also escape non-graphable characters
            * (like tabs), but none of them would get to this point and
            * it's superfluous to abort() on them.
            */
   
           switch (c) {
           case ('('):
                   /* FALLTHROUGH */
           case (')'):
                   /* FALLTHROUGH */
           case ('\\'):
                   putchar('\\');
                   break;
           default:
                   break;
           }
   
           /* Write the character and adjust where we are on the page. */
           putchar(c);
           p->pscol += PS_CHAR_WIDTH;
   }
   
   
   /*
    * Begin a "terminal" context.  Since terminal encompasses PostScript,
    * the actual terminal, etc., there are a few things we can do here.
    */
   void
   term_begin(struct termp *p, term_margin head,
                   term_margin foot, const void *arg)
   {
   
           p->headf = head;
           p->footf = foot;
           p->argf = arg;
   
           if (TERMTYPE_CHAR == p->type) {
                   /* Emit the header and be done. */
                   (*p->headf)(p, p->argf);
                   return;
           }
   
           /*
            * Emit the standard PostScript prologue, set our initial page
            * position, then run pageopen() on the initial page.
            */
   
           printf("%s\n", "%!PS");
           printf("%s\n", "/Courier");
           printf("%s\n", "10 selectfont");
   
           p->pspage = 1;
           p->psstate = 0;
           pageopen(p);
   }
   
   
   /*
    * Open a page.  This is only used for -Tps at the moment.  It opens a
    * page context, printing the header and the footer.  THE OUTPUT BUFFER
    * MUST BE EMPTY.  If it is not, output will ghost on the next line and
    * we'll be all gross and out of state.
    */
   static void
   pageopen(struct termp *p)
   {
   
           assert(TERMTYPE_PS == p->type);
           assert(0 == p->psstate);
   
           p->pscol = PS_CHAR_LEFT;
           p->psrow = PS_CHAR_TOPMARG;
           p->psstate |= PS_MARGINS;
   
           (*p->headf)(p, p->argf);
           endline(p);
   
           p->psstate &= ~PS_MARGINS;
           assert(0 == p->psstate);
   
           p->pscol = PS_CHAR_LEFT;
           p->psrow = PS_CHAR_BOTMARG;
           p->psstate |= PS_MARGINS;
   
           (*p->footf)(p, p->argf);
           endline(p);
   
           p->psstate &= ~PS_MARGINS;
           assert(0 == p->psstate);
   
           p->pscol = PS_CHAR_LEFT;
           p->psrow = PS_CHAR_TOP;
   
   }
   
   
   void
   term_end(struct termp *p)
   {
   
           if (TERMTYPE_CHAR == p->type) {
                   (*p->footf)(p, p->argf);
                   return;
           }
   
           printf("%s\n", "%%END");
   }
   
   
   static void
   endline(struct termp *p)
   {
   
           if (TERMTYPE_CHAR == p->type) {
                   putchar('\n');
                   return;
           }
   
           if (PS_INLINE & p->psstate) {
                   printf(") show\n");
                   p->psstate &= ~PS_INLINE;
           }
   
           if (PS_MARGINS & p->psstate)
                   return;
   
           p->pscol = PS_CHAR_LEFT;
           if (p->psrow >= PS_CHAR_HEIGHT + PS_CHAR_BOT) {
                   p->psrow -= PS_CHAR_HEIGHT;
                   return;
           }
   
           /*
            * XXX: can't run pageopen() until we're certain a flushln() has
            * occured, else the buf will reopen in an awkward state on the
            * next line.
            */
           printf("showpage\n");
           p->psrow = PS_CHAR_TOP;
   }
   
   
   /*
    * Advance the output engine by a certain amount of whitespace.
    */
   static void
   advance(struct termp *p, size_t len)
   {
           size_t          i;
   
           if (TERMTYPE_CHAR == p->type) {
                   /* Just print whitespace on the terminal. */
                   for (i = 0; i < len; i++)
                           putchar(' ');
                   return;
           }
   
           if (PS_INLINE & p->psstate) {
                   /* Dump out any existing line scope. */
                   printf(") show\n");
                   p->psstate &= ~PS_INLINE;
           }
   
           p->pscol += len ? len * PS_CHAR_WIDTH : 0;
   }
   
   
 static struct termp *  static struct termp *
 term_alloc(enum termenc enc, size_t width)  alloc(char *outopts, enum termenc enc, enum termtype type)
 {  {
         struct termp *p;          struct termp    *p;
           const char      *toks[2];
           char            *v;
           size_t           width;
   
           toks[0] = "width";
           toks[1] = NULL;
   
         p = calloc(1, sizeof(struct termp));          p = calloc(1, sizeof(struct termp));
         if (NULL == p) {          if (NULL == p) {
                 perror(NULL);                  perror(NULL);
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
         }          }
   
           p->type = type;
         p->tabwidth = 5;          p->tabwidth = 5;
         p->enc = enc;          p->enc = enc;
   
           width = 80;
   
           while (outopts && *outopts)
                   switch (getsubopt(&outopts, UNCONST(toks), &v)) {
                   case (0):
                           width = (size_t)atoi(v);
                           break;
                   default:
                           break;
                   }
   
         /* Enforce some lower boundary. */          /* Enforce some lower boundary. */
         if (width < 60)          if (width < 60)
                 width = 60;                  width = 60;
Line 138  term_flushln(struct termp *p)
Line 374  term_flushln(struct termp *p)
         size_t           vend;  /* end of word visual position on output */          size_t           vend;  /* end of word visual position on output */
         size_t           bp;    /* visual right border position */          size_t           bp;    /* visual right border position */
         int              j;     /* temporary loop index */          int              j;     /* temporary loop index */
           int              jhy;   /* last hyphen before line overflow */
         size_t           maxvis, mmax;          size_t           maxvis, mmax;
   
         /*          /*
Line 190  term_flushln(struct termp *p)
Line 427  term_flushln(struct termp *p)
                  */                   */
   
                 /* LINTED */                  /* LINTED */
                 for ( ; j < (int)p->col; j++) {                  for (jhy = 0; j < (int)p->col; j++) {
                         if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j])                          if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j])
                                 break;                                  break;
                         if (8 == p->buf[j])                          if (8 != p->buf[j]) {
                                 vend--;                                  if (vend > vis && vend < bp &&
                         else                                      ASCII_HYPH == p->buf[j])
                                           jhy = j;
                                 vend++;                                  vend++;
                           } else
                                   vend--;
                 }                  }
   
                 /*                  /*
                  * Find out whether we would exceed the right margin.                   * Find out whether we would exceed the right margin.
                  * If so, break to the next line.                   * If so, break to the next line.
                  */                   */
                 if (vend > bp && vis > 0) {                  if (vend > bp && 0 == jhy && vis > 0) {
                         vend -= vis;                          vend -= vis;
                         putchar('\n');                          endline(p);
                         if (TERMP_NOBREAK & p->flags) {                          if (TERMP_NOBREAK & p->flags) {
                                 p->viscol = p->rmargin;                                  p->viscol = p->rmargin;
                                 for (j = 0; j < (int)p->rmargin; j++)                                  advance(p, p->rmargin);
                                         putchar(' ');  
                                 vend += p->rmargin - p->offset;                                  vend += p->rmargin - p->offset;
                         } else {                          } else {
                                 p->viscol = 0;                                  p->viscol = 0;
Line 231  term_flushln(struct termp *p)
Line 470  term_flushln(struct termp *p)
   
                 /* Write out the [remaining] word. */                  /* Write out the [remaining] word. */
                 for ( ; i < (int)p->col; i++) {                  for ( ; i < (int)p->col; i++) {
                           if (vend > bp && jhy > 0 && i > jhy)
                                   break;
                         if ('\t' == p->buf[i])                          if ('\t' == p->buf[i])
                                 break;                                  break;
                         if (' ' == p->buf[i]) {                          if (' ' == p->buf[i]) {
Line 251  term_flushln(struct termp *p)
Line 492  term_flushln(struct termp *p)
                          * so write preceding white space now.                           * so write preceding white space now.
                          */                           */
                         if (vbl) {                          if (vbl) {
                                 for (j = 0; j < (int)vbl; j++)                                  advance(p, vbl);
                                         putchar(' ');  
                                 p->viscol += vbl;                                  p->viscol += vbl;
                                 vbl = 0;                                  vbl = 0;
                         }                          }
                         putchar(p->buf[i]);  
                           if (ASCII_HYPH == p->buf[i])
                                   letter(p, '-');
                           else
                                   letter(p, p->buf[i]);
   
                         p->viscol += 1;                          p->viscol += 1;
                 }                  }
                 vend += vbl;                  vend += vbl;
Line 268  term_flushln(struct termp *p)
Line 513  term_flushln(struct termp *p)
   
         if ( ! (TERMP_NOBREAK & p->flags)) {          if ( ! (TERMP_NOBREAK & p->flags)) {
                 p->viscol = 0;                  p->viscol = 0;
                 putchar('\n');                  endline(p);
                 return;                  return;
         }          }
   
Line 301  term_flushln(struct termp *p)
Line 546  term_flushln(struct termp *p)
         if (maxvis > vis + /* LINTED */          if (maxvis > vis + /* LINTED */
                         ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) {                          ((TERMP_TWOSPACE & p->flags) ? 1 : 0)) {
                 p->viscol += maxvis - vis;                  p->viscol += maxvis - vis;
                 for ( ; vis < maxvis; vis++)                  advance(p, maxvis - vis);
                         putchar(' ');                  vis += (maxvis - vis);
         } else {        /* ...or newline break. */          } else {        /* ...or newline break. */
                 putchar('\n');                  endline(p);
                 p->viscol = p->rmargin;                  p->viscol = p->rmargin;
                 for (i = 0; i < (int)p->rmargin; i++)                  advance(p, p->rmargin);
                         putchar(' ');  
         }          }
 }  }
   
Line 343  term_vspace(struct termp *p)
Line 587  term_vspace(struct termp *p)
   
         term_newln(p);          term_newln(p);
         p->viscol = 0;          p->viscol = 0;
         putchar('\n');          endline(p);
 }  }
   
   
Line 595  encode(struct termp *p, const char *word, size_t sz)
Line 839  encode(struct termp *p, const char *word, size_t sz)
          * character by character.           * character by character.
          */           */
   
         if (TERMFONT_NONE == (f = term_fonttop(p))) {          if (TERMTYPE_PS == p->type) {
                   buffera(p, word, sz);
                   return;
           } else if (TERMFONT_NONE == (f = term_fonttop(p))) {
                 buffera(p, word, sz);                  buffera(p, word, sz);
                 return;                  return;
         }          }

Legend:
Removed from v.1.139  
changed lines
  Added in v.1.144

CVSweb