home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / groff / libXdvi / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-03  |  8.9 KB  |  420 lines

  1. /*
  2.  * parse.c
  3.  *
  4.  * parse dvi input
  5.  */
  6.  
  7. #include <X11/Xos.h>
  8. #include <X11/IntrinsicP.h>
  9. #include <X11/StringDefs.h>
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include "DviP.h"
  13.  
  14. static int StopSeen = 0;
  15. static ParseDrawFunction(), ParseDeviceControl();
  16. static push_env(), pop_env();
  17.  
  18. #define HorizontalMove(dw, delta)    ((dw)->dvi.state->x += (delta))
  19.  
  20. #define charWidth(fi,c) (\
  21.     (fi)->per_char ?\
  22.     (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
  23.     :\
  24.     (fi)->max_bounds.width\
  25. )
  26.  
  27.  
  28. int charExists (fi, c)
  29.     XFontStruct    *fi;
  30.     int        c;
  31. {
  32.     XCharStruct *p;
  33.  
  34.     if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
  35.         return 0;
  36.     p = fi->per_char + (c - fi->min_char_or_byte2);
  37.     return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
  38.         || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
  39. }
  40.  
  41.    
  42. ParseInput(dw)
  43.     register DviWidget    dw;
  44. {
  45.     int        n, k;
  46.     int        c;
  47.     char        Buffer[BUFSIZ];
  48.     int        NextPage;
  49.     int        prevFont;
  50.     int        otherc;
  51.  
  52.     StopSeen = 0;
  53.  
  54.     /*
  55.      * make sure some state exists
  56.      */
  57.  
  58.     if (!dw->dvi.state)
  59.         push_env (dw);
  60.     for (;;) {
  61.         switch (DviGetC(dw, &c)) {
  62.         case '\n':    
  63.             break;
  64.         case ' ':    /* when input is text */
  65.         case 0:        /* occasional noise creeps in */
  66.             break;
  67.         case '{':    /* push down current environment */
  68.             push_env(dw);
  69.             break;
  70.         case '}':
  71.             pop_env(dw);
  72.             break;
  73.         /*
  74.          * two motion digits plus a character
  75.          */
  76.         case '0': case '1': case '2': case '3': case '4':
  77.         case '5': case '6': case '7': case '8': case '9':
  78.             HorizontalMove(dw, (c-'0')*10 +
  79.                        DviGetC(dw,&otherc)-'0');
  80.             /* fall through */
  81.         case 'c':    /* single ascii character */
  82.             DviGetC(dw,&c);
  83.                 if (c == ' ')
  84.                 break;
  85.             Buffer[0] = c;
  86.             Buffer[1] = '\0';
  87.             goto FunnyCharacter;
  88.  
  89.         case 'C':
  90.             GetWord(dw, Buffer, BUFSIZ);
  91.             FunnyCharacter:
  92.             prevFont = -1;
  93.             c = -1;
  94.             {
  95.                         DviCharNameMap    *map;
  96.                 int            i;
  97.                     
  98.                         map = QueryFontMap (dw, dw->dvi.state->font_number);
  99.                         if (map) {
  100.                             c = DviCharIndex (map, Buffer);
  101.                             if (c == -1) {
  102.                     for (i = 1; map = QueryFontMap (dw, i); i++)
  103.                         if (map->special)
  104.                         if ((c = DviCharIndex (map, Buffer)) != -1) {
  105.                             prevFont = dw->dvi.state->font_number;
  106.                             dw->dvi.state->font_number = i;
  107.                             break;
  108.                         }
  109.                     }
  110.                         }
  111.             }
  112.             if (c == -1)
  113.                 break;
  114.         NumberedCharacter:
  115.             /*
  116.              * quick and dirty extents calculation:
  117.              */
  118.             if (dw->dvi.state->y + 24 >= dw->dvi.extents.y1 &&
  119.                 dw->dvi.state->y - 24 <= dw->dvi.extents.y2 &&
  120.                 dw->dvi.state->x + 24 >= dw->dvi.extents.x1 &&
  121.                 dw->dvi.state->x - 24 <= dw->dvi.extents.x2)
  122.             {
  123.                         register XFontStruct    *font;
  124.                 register XTextItem        *text;
  125.                     
  126.                         if (!dw->dvi.display_enable)
  127.                             break;
  128.                     
  129.                         if (dw->dvi.state->y != dw->dvi.cache.y ||
  130.                             dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE)
  131.                 FlushCharCache (dw);
  132.                 /*
  133.                  * load a new font, if the current block is not empty,
  134.                  * step to the next.
  135.                  */
  136.                 if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
  137.                            dw->dvi.cache.font_number != dw->dvi.state->font_number)
  138.                     {
  139.                     dw->dvi.cache.font_size = dw->dvi.state->font_size;
  140.                     dw->dvi.cache.font_number = dw->dvi.state->font_number;
  141.                     dw->dvi.cache.font = QueryFont (dw,
  142.                               dw->dvi.cache.font_number,
  143.                               dw->dvi.cache.font_size);
  144.                 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
  145.                     ++dw->dvi.cache.index;
  146.                     if (dw->dvi.cache.index >= dw->dvi.cache.max)
  147.                     FlushCharCache (dw);
  148.                     dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
  149.                 }
  150.                         }
  151.                 if (dw->dvi.cache.x != dw->dvi.state->x) {
  152.                 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
  153.                     ++dw->dvi.cache.index;
  154.                     if (dw->dvi.cache.index >= dw->dvi.cache.max)
  155.                     FlushCharCache (dw);
  156.                     dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
  157.                 }
  158.                 }
  159.                         font = dw->dvi.cache.font;
  160.                 text = &dw->dvi.cache.cache[dw->dvi.cache.index];
  161.                 if (text->nchars == 0) {
  162.                 text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
  163.                 text->delta = dw->dvi.state->x - dw->dvi.cache.x;
  164.                 if (font != dw->dvi.font) {
  165.                     text->font = font->fid;
  166.                     dw->dvi.font = font;
  167.                 } else
  168.                     text->font = None;
  169.                 dw->dvi.cache.x += text->delta;
  170.                 }
  171.                 if (charExists(font, c)) {
  172.                     dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
  173.                     ++text->nchars;
  174.                     dw->dvi.cache.x += charWidth(font,c);
  175.                 }
  176.             }
  177.             if (prevFont != -1)
  178.                 dw->dvi.state->font_number = prevFont;
  179.             break;
  180.         case 'D':    /* draw function */
  181.             GetLine(dw, Buffer, BUFSIZ);
  182.             if (dw->dvi.display_enable)
  183.                 ParseDrawFunction(dw, Buffer);
  184.             break;
  185.         case 's':    /* ignore fractional sizes */
  186.             n = GetNumber(dw);
  187.             dw->dvi.state->font_size = n;
  188.             break;
  189.         case 'f':
  190.             n = GetNumber(dw);
  191.             dw->dvi.state->font_number = n;
  192.             break;
  193.         case 'H':    /* absolute horizontal motion */
  194.             k = GetNumber(dw);
  195.             HorizontalGoto(dw, k);
  196.             break;
  197.         case 'h':    /* relative horizontal motion */
  198.             k = GetNumber(dw);
  199.             HorizontalMove(dw, k);
  200.             break;
  201.         case 'w':    /* word space */
  202.             break;
  203.         case 'V':
  204.             n = GetNumber(dw);
  205.             VerticalGoto(dw, n);
  206.             break;
  207.         case 'v':
  208.             n = GetNumber(dw);
  209.             VerticalMove(dw, n);
  210.             break;
  211.         case 'P':    /* new spread */
  212.             break;
  213.         case 'p':    /* new page */
  214.             (void) GetNumber(dw);
  215.             NextPage = dw->dvi.current_page + 1;
  216.             RememberPagePosition(dw, NextPage);
  217.             FlushCharCache (dw);
  218.             return(NextPage);
  219.         case 'N':
  220.             c = GetNumber(dw);
  221.             goto NumberedCharacter;
  222.         case 'n':    /* end of line */
  223.             GetNumber(dw);
  224.             GetNumber(dw);
  225.             HorizontalGoto(dw, 0);
  226.             break;
  227.         case '+':    /* continuation of X device control */
  228.         case '#':    /* comment */
  229.             GetLine(dw, NULL, 0);
  230.             break;
  231.         case 'x':    /* device control */
  232.             ParseDeviceControl(dw);
  233.             break;
  234.         case EOF:
  235.             dw->dvi.last_page = dw->dvi.current_page;
  236.             FlushCharCache (dw);
  237.             return dw->dvi.current_page;
  238.         default:
  239.             break;
  240.         }
  241.     }
  242. }
  243.  
  244. static
  245. push_env(dw)
  246.     DviWidget    dw;
  247. {
  248.     DviState    *new;
  249.  
  250.     new = (DviState *) malloc (sizeof (*new));
  251.     if (dw->dvi.state)
  252.         *new = *(dw->dvi.state);
  253.     else {
  254.         new->font_size = 10;
  255.         new->font_number = 1;
  256.         new->x = 0;
  257.         new->y = 0;
  258.     }
  259.     new->next = dw->dvi.state;
  260.     dw->dvi.state = new;
  261. }
  262.  
  263. static
  264. pop_env(dw)
  265.     DviWidget    dw;
  266. {
  267.     DviState    *old;
  268.  
  269.     old = dw->dvi.state;
  270.     dw->dvi.state = old->next;
  271.     free ((char *) old);
  272. }
  273.  
  274. static
  275. InitTypesetter (dw)
  276.     DviWidget    dw;
  277. {
  278.     while (dw->dvi.state)
  279.         pop_env (dw);
  280.     push_env (dw);
  281.     FlushCharCache (dw);
  282. }
  283.  
  284. #define DRAW_ARGS_MAX 128
  285.  
  286. static
  287. ParseDrawFunction(dw, buf)
  288. DviWidget    dw;
  289. char        *buf;
  290. {
  291.     int v[DRAW_ARGS_MAX];
  292.     int i;
  293.     char *ptr;
  294.     
  295.     v[0] = v[1] = v[2] = v[3] = 0;
  296.     
  297.     if (buf[0] == '\0')
  298.         return;
  299.     ptr = buf+1;
  300.     
  301.     for (i = 0; i < DRAW_ARGS_MAX; i++) {
  302.         if (sscanf(ptr, "%d", v + i) != 1)
  303.             break;
  304.         while (*ptr == ' ')
  305.             ptr++;
  306.         while (*ptr != '\0' && *ptr != ' ')
  307.             ptr++;
  308.     }
  309.     
  310.     switch (buf[0]) {
  311.     case 'l':                /* draw a line */
  312.         DrawLine(dw, v[0], v[1]);
  313.         break;
  314.     case 'c':                /* circle */
  315.         DrawCircle(dw, v[0]);
  316.         break;
  317.     case 'C':
  318.         DrawFilledCircle(dw, v[0]);
  319.         break;
  320.     case 'e':                /* ellipse */
  321.         DrawEllipse(dw, v[0], v[1]);
  322.         break;
  323.     case 'E':
  324.         DrawFilledEllipse(dw, v[0], v[1]);
  325.         break;
  326.     case 'a':                /* arc */
  327.         DrawArc(dw, v[0], v[1], v[2], v[3]);
  328.         break;
  329.     case 'p':
  330.         DrawPolygon(dw, v, i);
  331.         break;
  332.     case 'P':
  333.         DrawFilledPolygon(dw, v, i);
  334.         break;
  335.     case '~':                /* wiggly line */
  336.         DrawSpline(dw, v, i);
  337.         break;
  338.     case 't':
  339.         dw->dvi.line_thickness = v[0];
  340.         break;
  341.     case 'f':
  342.         if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
  343.             dw->dvi.fill = v[0];
  344.         break;
  345.     default:
  346. #if 0
  347.         warning("unknown drawing function %s", buf);
  348. #endif
  349.         break;
  350.     }
  351.     
  352.     if (buf[0] == 'e') {
  353.         if (i > 0)
  354.             dw->dvi.state->x += v[0];
  355.     }
  356.     else {
  357.         while (--i >= 0) {
  358.             if (i & 1)
  359.                 dw->dvi.state->y += v[i];
  360.             else
  361.                 dw->dvi.state->x += v[i];
  362.         }
  363.     }
  364.  
  365. static
  366. ParseDeviceControl(dw)                /* Parse the x commands */
  367.     DviWidget    dw;
  368. {
  369.         char str[20], str1[50], buf[50];
  370.     int c, n;
  371.     extern int LastPage, CurrentPage;
  372.  
  373.     GetWord (dw, str, 20);
  374.     switch (str[0]) {            /* crude for now */
  375.     case 'T':                /* output device */
  376.         GetWord(dw, str, 20);
  377.         break;
  378.     case 'i':                /* initialize */
  379.         InitTypesetter (dw);
  380.         break;
  381.     case 't':                /* trailer */
  382.         break;
  383.     case 'p':                /* pause -- can restart */
  384.         break;
  385.     case 's':                /* stop */
  386.         StopSeen = 1;
  387.         return;
  388.     case 'r':                /* resolution when prepared */
  389.         SetDeviceResolution (dw, GetNumber (dw));
  390.         break;
  391.     case 'f':                /* font used */
  392.         n = GetNumber(dw);
  393.         GetWord(dw, str, 20);
  394.         GetLine(dw, str1, 50);
  395.         SetFontPosition(dw, n, str, str1);
  396.         break;
  397.     case 'H':                /* char height */
  398.         break;
  399.     case 'S':                /* slant */
  400.         break;
  401.     }
  402.     while (DviGetC(dw,&c) != '\n')        /* skip rest of input line */
  403.         if (c == EOF)
  404.             return;
  405.     return;
  406. }
  407.  
  408.  
  409. /*
  410. Local Variables:
  411. c-indent-level: 8
  412. c-continued-statement-offset: 8
  413. c-brace-offset: -8
  414. c-argdecl-indent: 8
  415. c-label-offset: -8
  416. c-tab-always-indent: nil
  417. End:
  418. */
  419.