home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xditview / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-30  |  9.5 KB  |  416 lines

  1. /* $XConsortium: parse.c,v 1.12 91/07/30 14:10:46 keith Exp $ */
  2. /*
  3.  * Copyright 1991 Massachusetts Institute of Technology
  4.  *
  5.  * Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both that
  8.  * copyright notice and this permission notice appear in supporting
  9.  * documentation, and that the name of M.I.T. not be used in advertising or
  10.  * publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.  M.I.T. makes no representations about the
  12.  * suitability of this software for any purpose.  It is provided "as is"
  13.  * without express or implied warranty.
  14.  *
  15.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  17.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  19.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  20.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  */
  23.  
  24. /*
  25.  * parse.c
  26.  *
  27.  * parse dvi input
  28.  */
  29.  
  30. #include <X11/Xos.h>
  31. #include <X11/IntrinsicP.h>
  32. #include <X11/StringDefs.h>
  33. #include <stdio.h>
  34. #include <ctype.h>
  35. #include "DviP.h"
  36.  
  37. static int StopSeen = 0;
  38. static ParseDrawFunction(), ParseDeviceControl();
  39. static push_env(), pop_env();
  40.  
  41. extern char *GetWord(), *GetLine ();
  42.  
  43. #define HorizontalMove(dw, delta)    ((dw)->dvi.state->x += (delta))
  44.  
  45. #define charWidth(fi,c) (\
  46.     (fi)->per_char ?\
  47.     (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
  48.     :\
  49.     (fi)->max_bounds.width\
  50. )
  51.     
  52. ParseInput(dw)
  53.     register DviWidget    dw;
  54. {
  55.     int        n, k;
  56.     int        c;
  57.     char        Buffer[BUFSIZ];
  58.     int        NextPage;
  59.     int        prevFont;
  60.     int        otherc;
  61.     unsigned char    tc;
  62.  
  63.     StopSeen = 0;
  64.  
  65.     /*
  66.      * make sure some state exists
  67.      */
  68.  
  69.     if (!dw->dvi.state)
  70.         push_env (dw);
  71.     for (;;) {
  72.         switch (DviGetC(dw, &c)) {
  73.         case '\n':    
  74.             break;
  75.         case ' ':    /* when input is text */
  76.         case 0:        /* occasional noise creeps in */
  77.             break;
  78.         case '{':    /* push down current environment */
  79.             push_env(dw);
  80.             break;
  81.         case '}':
  82.             pop_env(dw);
  83.             break;
  84.         /*
  85.          * two motion digits plus a character
  86.          */
  87.         case '0': case '1': case '2': case '3': case '4':
  88.         case '5': case '6': case '7': case '8': case '9':
  89.             HorizontalMove(dw, (c-'0')*10 +
  90.                        DviGetC(dw,&otherc)-'0');
  91.             /* fall through */
  92.         case 'c':    /* single ascii character */
  93.             (void) DviGetC(dw,&c);
  94.                 if (c == ' ')
  95.                 break;
  96.             tc = c;
  97.             PutCharacters (dw, &tc, 1);
  98.             break;
  99.         case 'C':
  100.             GetWord(dw, Buffer, BUFSIZ);
  101.             {
  102.                         DviCharNameMap    *map;
  103.                 int            i;
  104.                 unsigned char    *ligature;
  105.                     
  106.                 c = -1;
  107.                         map = QueryFontMap (dw, dw->dvi.state->font_number);
  108.                         if (map)
  109.                 {
  110.                         c = DviCharIndex (map, Buffer);
  111.                 if (c == -1)
  112.                 {
  113.                     ligature = DviCharIsLigature (map, Buffer);
  114.                     if (ligature) {
  115.                     i = strlen ((char *) ligature);
  116.                     PutCharacters (dw, ligature, i);
  117.                     break;
  118.                        }
  119.                 }
  120.                 }
  121.                 prevFont = -1;
  122.                         if (c == -1) {
  123.                     for (i = 1; map = QueryFontMap (dw, i); i++)
  124.                     if (map->special)
  125.                         if ((c = DviCharIndex (map, Buffer)) != -1) {
  126.                         prevFont = dw->dvi.state->font_number;
  127.                         dw->dvi.state->font_number = i;
  128.                         break;
  129.                         }
  130.                 }
  131.                 if (c != -1)
  132.                 {
  133.                 tc = c;
  134.                 PutCharacters (dw, &tc, 1);
  135.                 }
  136.                 if (prevFont != -1)
  137.                 dw->dvi.state->font_number = prevFont;
  138.             }
  139.             break;
  140.         case 'D':    /* draw function */
  141.             GetLine(dw, Buffer, BUFSIZ);
  142.             ParseDrawFunction(dw, Buffer);
  143.             break;
  144.         case 's':    /* ignore fractional sizes */
  145.             n = GetNumber(dw);
  146.             dw->dvi.state->font_size = n;
  147.             dw->dvi.state->line_width = FontSizeInDevice(dw, n / 10.0);
  148.             break;
  149.         case 'f':
  150.             n = GetNumber(dw);
  151.             dw->dvi.state->font_number = n;
  152.             break;
  153.         case 'H':    /* absolute horizontal motion */
  154.             k = GetNumber(dw);
  155.             HorizontalGoto(dw, k);
  156.             break;
  157.         case 'h':    /* relative horizontal motion */
  158.             k = GetNumber(dw);
  159.             HorizontalMove(dw, k);
  160.             break;
  161.         case 'w':    /* word space */
  162.             break;
  163.         case 'V':
  164.             n = GetNumber(dw);
  165.             VerticalGoto(dw, n);
  166.             break;
  167.         case 'v':
  168.             n = GetNumber(dw);
  169.             VerticalMove(dw, n);
  170.             break;
  171.         case 'P':    /* new spread */
  172.             break;
  173.         case 'p':    /* new page */
  174.             (void) GetNumber(dw);
  175.             NextPage = dw->dvi.current_page + 1;
  176.             RememberPagePosition(dw, NextPage);
  177.             FlushCharCache (dw);
  178.             return(NextPage);
  179.         case 'n':    /* end of line */
  180.             GetNumber(dw);
  181.             GetNumber(dw);
  182.             HorizontalGoto(dw, 0);
  183.             break;
  184.         case '#':    /* comment */
  185.             GetLine(dw, NULL, 0);
  186.             break;
  187.         case 'x':    /* device control */
  188.             ParseDeviceControl(dw);
  189.             break;
  190.         case EOF:
  191.             dw->dvi.last_page = dw->dvi.current_page;
  192.             FlushCharCache (dw);
  193.             return dw->dvi.current_page;
  194.         default:
  195.             break;
  196.         }
  197.     }
  198. }
  199.  
  200. static
  201. push_env(dw)
  202.     DviWidget    dw;
  203. {
  204.     DviState    *new;
  205.  
  206.     new = (DviState *) XtMalloc (sizeof (*new));
  207.     if (dw->dvi.state)
  208.         *new = *(dw->dvi.state);
  209.     else {
  210.         new->font_size = 10;
  211.         new->font_number = 1;
  212.         new->line_style = 0;
  213.         new->line_width = FontSizeInDevice(dw, 10/10);
  214.         new->x = 0;
  215.         new->y = 0;
  216.     }
  217.     new->next = dw->dvi.state;
  218.     dw->dvi.state = new;
  219. }
  220.  
  221. static
  222. pop_env(dw)
  223.     DviWidget    dw;
  224. {
  225.     DviState    *old;
  226.  
  227.     old = dw->dvi.state;
  228.     dw->dvi.state = old->next;
  229.     XtFree ((char *) old);
  230. }
  231.  
  232. static
  233. InitTypesetter (dw)
  234.     DviWidget    dw;
  235. {
  236.     while (dw->dvi.state)
  237.         pop_env (dw);
  238.     push_env (dw);
  239.     FlushCharCache (dw);
  240. }
  241.  
  242. SetFont (dw)
  243.     DviWidget    dw;
  244. {
  245.     dw->dvi.cache.font_size = dw->dvi.state->font_size;
  246.     dw->dvi.cache.font_number = dw->dvi.state->font_number;
  247.     dw->dvi.cache.font = QueryFont (dw,
  248.               dw->dvi.cache.font_number,
  249.               dw->dvi.cache.font_size);
  250. }
  251.  
  252. PutCharacters (dw, src, len)
  253.     DviWidget        dw;
  254.     unsigned char   *src;
  255.     int            len;
  256. {
  257.     int        xx, yx;
  258.     int        fx, fy;
  259.     char    *dst;
  260.     int        c;
  261.  
  262.     xx = ToX(dw, dw->dvi.state->x);
  263.     yx = ToX(dw, dw->dvi.state->y);
  264.     fy = FontSizeInPixels (dw, dw->dvi.state->font_size);
  265.     fx = fy * len;
  266.     /*
  267.      * quick and dirty extents calculation:
  268.      */
  269.     if (yx + fy >= dw->dvi.extents.y1 &&
  270.     yx - fy <= dw->dvi.extents.y2 &&
  271.     xx + fx >= dw->dvi.extents.x1 &&
  272.     xx - fx <= dw->dvi.extents.x2)
  273.     {
  274.     register XFontStruct    *font;
  275.     register XTextItem        *text;
  276.  
  277.     if (!dw->dvi.display_enable)
  278.         return FALSE;
  279.  
  280.     if (yx != dw->dvi.cache.y ||
  281.         dw->dvi.cache.char_index + len > DVI_CHAR_CACHE_SIZE)
  282.         FlushCharCache (dw);
  283.     /*
  284.      * load a new font, if the current block is not empty,
  285.      * step to the next.
  286.      */
  287.     if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
  288.         dw->dvi.cache.font_number != dw->dvi.state->font_number)
  289.     {
  290.         SetFont (dw);
  291.         if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
  292.         ++dw->dvi.cache.index;
  293.         if (dw->dvi.cache.index >= dw->dvi.cache.max)
  294.             FlushCharCache (dw);
  295.         dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
  296.         }
  297.     }
  298.     if (xx != dw->dvi.cache.x) {
  299.         if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
  300.         ++dw->dvi.cache.index;
  301.         if (dw->dvi.cache.index >= dw->dvi.cache.max)
  302.             FlushCharCache (dw);
  303.         dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
  304.         }
  305.     }
  306.     text = &dw->dvi.cache.cache[dw->dvi.cache.index];
  307.     font = dw->dvi.cache.font;
  308.     dst = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
  309.     if (text->nchars == 0) {
  310.         text->chars = dst;
  311.         text->delta = xx - dw->dvi.cache.x;
  312.         if (font != dw->dvi.font) {
  313.         text->font = font->fid;
  314.         dw->dvi.font = font;
  315.         } else
  316.         text->font = None;
  317.         dw->dvi.cache.x += text->delta;
  318.     }
  319.     dw->dvi.cache.char_index += len;
  320.     text->nchars += len;
  321.     while (len--)
  322.     {
  323.         c = *src++;
  324.         *dst++ = c;
  325.         dw->dvi.cache.x += charWidth(font,c);
  326.     }
  327.     return TRUE;
  328.     }
  329.     return FALSE;
  330. }
  331.  
  332. static
  333. ParseDrawFunction(dw, buf)
  334.     DviWidget    dw;
  335.     char        *buf;
  336. {
  337.     int    n, m, n1, m1;
  338.  
  339.     SetGCForDraw (dw);
  340.     switch (buf[0]) {
  341.     case 'l':                /* draw a line */
  342.     sscanf(buf+1, "%d %d", &n, &m);
  343.     DrawLine(dw, n, m);
  344.     break;
  345.     case 'c':                /* circle */
  346.     sscanf(buf+1, "%d", &n);
  347.     DrawCircle(dw, n);
  348.     break;
  349.     case 'e':                /* ellipse */
  350.     sscanf(buf+1, "%d %d", &m, &n);
  351.     DrawEllipse(dw, m, n);
  352.     break;
  353.     case 'a':                /* arc */
  354.     sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
  355.     DrawArc(dw, n, m, n1, m1);
  356.     break;
  357.     case '~':                /* wiggly line */
  358.     DrawSpline(dw, buf+1,1);
  359.     break;
  360.     case 't':                /* line width */
  361.     sscanf(buf+1, "%d", &n);
  362.     dw->dvi.state->line_width = n;
  363.     break;
  364.     case 's':                /* line style */
  365.     sscanf(buf+1, "%d", &n);
  366.     /* XXX */
  367.     break;
  368.     default:
  369.     /* warning("unknown drawing function %s", buf); */
  370.     break;
  371.     }
  372.  
  373. static
  374. ParseDeviceControl(dw)                /* Parse the x commands */
  375.     DviWidget    dw;
  376. {
  377.     char str[20], str1[50];
  378.     int c, n;
  379.     extern int LastPage, CurrentPage;
  380.  
  381.     GetWord (dw, str, 20);
  382.     switch (str[0]) {            /* crude for now */
  383.     case 'T':                /* output device */
  384.     GetWord(dw, str, 20);
  385.     break;
  386.     case 'i':                /* initialize */
  387.     InitTypesetter (dw);
  388.     break;
  389.     case 't':                /* trailer */
  390.     break;
  391.     case 'p':                /* pause -- can restart */
  392.     break;
  393.     case 's':                /* stop */
  394.     StopSeen = 1;
  395.     return;
  396.     case 'r':                /* resolution when prepared */
  397.     SetDeviceResolution (dw, GetNumber (dw));
  398.     break;
  399.     case 'f':                /* font used */
  400.     n = GetNumber(dw);
  401.     GetWord(dw, str, 20);
  402.     GetLine(dw, str1, 50);
  403.     SetFontPosition(dw, n, str, str1);
  404.     break;
  405.     case 'H':                /* char height */
  406.     break;
  407.     case 'S':                /* slant */
  408.     break;
  409.     }
  410.     while (DviGetC(dw,&c) != '\n')        /* skip rest of input line */
  411.         if (c == EOF)
  412.             return;
  413.     return;
  414. }
  415.