summaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:21 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:21 +0000
commit84735728ed5f6a07d87254860e2776775c54b85b (patch)
tree3b8bd2195fd61ff50279b2bcfaaf41af01b0279f /parse.c
Initial revisionXORG-STABLE
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c479
1 files changed, 479 insertions, 0 deletions
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..a65a031
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,479 @@
+/* $XConsortium: parse.c,v 1.13 94/04/17 20:43:36 keith Exp $ */
+/*
+
+Copyright (c) 1991 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+/* $XFree86: xc/programs/xditview/parse.c,v 1.5 2001/08/27 23:35:12 dawes Exp $ */
+
+/*
+ * parse.c
+ *
+ * parse dvi input
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+static int StopSeen = 0;
+static void ParseDrawFunction(DviWidget dw, char *buf);
+static void ParseDeviceControl(DviWidget dw);
+static void PutCharacters(DviWidget dw, unsigned char *src, int len);
+static void push_env(DviWidget dw);
+static void pop_env(DviWidget dw);
+
+#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
+
+#ifdef USE_XFT
+static int
+charWidth (DviWidget dw, XftFont *font, char c)
+{
+ XGlyphInfo extents;
+
+ XftTextExtents8 (XtDisplay (dw), font,
+ (unsigned char *) &c, 1, &extents);
+ return extents.xOff;
+}
+#else
+#define charWidth(dw,fi,c) (\
+ (fi)->per_char ?\
+ (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
+ :\
+ (fi)->max_bounds.width\
+)
+#endif
+
+int
+ParseInput(dw)
+ DviWidget dw;
+{
+ int n, k;
+ int c;
+ char Buffer[BUFSIZ];
+ int NextPage;
+ int prevFont;
+ int otherc;
+ unsigned char tc;
+
+ StopSeen = 0;
+
+ /*
+ * make sure some state exists
+ */
+
+ if (!dw->dvi.state)
+ push_env (dw);
+ for (;;) {
+ switch (DviGetC(dw, &c)) {
+ case '\n':
+ break;
+ case ' ': /* when input is text */
+ case 0: /* occasional noise creeps in */
+ break;
+ case '{': /* push down current environment */
+ push_env(dw);
+ break;
+ case '}':
+ pop_env(dw);
+ break;
+ /*
+ * two motion digits plus a character
+ */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ HorizontalMove(dw, (c-'0')*10 +
+ DviGetC(dw,&otherc)-'0');
+ /* fall through */
+ case 'c': /* single ascii character */
+ (void) DviGetC(dw,&c);
+ if (c == ' ')
+ break;
+ tc = c;
+ PutCharacters (dw, &tc, 1);
+ break;
+ case 'C':
+ GetWord(dw, Buffer, BUFSIZ);
+ {
+ DviCharNameMap *map;
+ int i;
+ unsigned char *ligature;
+
+ c = -1;
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (map)
+ {
+ c = DviCharIndex (map, Buffer);
+ if (c == -1)
+ {
+ ligature = DviCharIsLigature (map, Buffer);
+ if (ligature) {
+ i = strlen ((char *) ligature);
+ PutCharacters (dw, ligature, i);
+ break;
+ }
+ }
+ }
+ prevFont = -1;
+ if (c == -1) {
+ for (i = 1; (map = QueryFontMap (dw, i)); i++)
+ if (map->special)
+ if ((c = DviCharIndex (map, Buffer)) != -1) {
+ prevFont = dw->dvi.state->font_number;
+ dw->dvi.state->font_number = i;
+ break;
+ }
+ }
+ if (c != -1)
+ {
+ tc = c;
+ PutCharacters (dw, &tc, 1);
+ }
+ if (prevFont != -1)
+ dw->dvi.state->font_number = prevFont;
+ }
+ break;
+ case 'D': /* draw function */
+ GetLine(dw, Buffer, BUFSIZ);
+ ParseDrawFunction(dw, Buffer);
+ break;
+ case 's': /* ignore fractional sizes */
+ n = GetNumber(dw);
+ if (!dw->dvi.size_scale)
+ {
+ static int guesses[] = { 1, 4, 100, 1000, 1 };
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (8 <= n/guesses[i] && n/guesses[i] <= 24)
+ {
+ break;
+ }
+ dw->dvi.size_scale = guesses[i];
+ }
+ dw->dvi.state->font_size = n;
+ dw->dvi.state->line_width = n * (dw->dvi.device_resolution /
+ (720 * dw->dvi.size_scale));
+ break;
+ case 'f':
+ n = GetNumber(dw);
+ dw->dvi.state->font_number = n;
+ break;
+ case 'H': /* absolute horizontal motion */
+ k = GetNumber(dw);
+ HorizontalGoto(dw, k);
+ break;
+ case 'h': /* relative horizontal motion */
+ k = GetNumber(dw);
+ HorizontalMove(dw, k);
+ break;
+ case 'w': /* word space */
+ break;
+ case 'V':
+ n = GetNumber(dw);
+ VerticalGoto(dw, n);
+ break;
+ case 'v':
+ n = GetNumber(dw);
+ VerticalMove(dw, n);
+ break;
+ case 'P': /* new spread */
+ break;
+ case 'p': /* new page */
+ (void) GetNumber(dw);
+ NextPage = dw->dvi.current_page + 1;
+ RememberPagePosition(dw, NextPage);
+ FlushCharCache (dw);
+ return(NextPage);
+ case 'n': /* end of line */
+ GetNumber(dw);
+ GetNumber(dw);
+ HorizontalGoto(dw, 0);
+ break;
+ case '#': /* comment */
+ case 'F': /* file info */
+ GetLine(dw, NULL, 0);
+ break;
+ case 't': /* text */
+ GetLine(dw, Buffer, BUFSIZ);
+ PutCharacters (dw, (unsigned char *)Buffer,
+ strlen (Buffer));
+ dw->dvi.state->x = ToDevice (dw, dw->dvi.cache.x);
+ break;
+ case 'x': /* device control */
+ ParseDeviceControl(dw);
+ break;
+ case EOF:
+ dw->dvi.last_page = dw->dvi.current_page;
+ FlushCharCache (dw);
+ return dw->dvi.current_page;
+ default:
+ GetLine (dw, Buffer, BUFSIZ);
+ fprintf (stderr, "Unknown command %s\n", Buffer);
+ break;
+ }
+ }
+}
+
+static void
+push_env(dw)
+ DviWidget dw;
+{
+ DviState *new;
+
+ new = (DviState *) XtMalloc (sizeof (*new));
+ if (dw->dvi.state)
+ *new = *(dw->dvi.state);
+ else {
+ new->font_size = 10 * dw->dvi.size_scale;
+ new->font_number = 1;
+ new->line_style = 0;
+ new->line_width = 10;
+ new->x = 0;
+ new->y = 0;
+ }
+ new->next = dw->dvi.state;
+ dw->dvi.state = new;
+}
+
+static void
+pop_env(dw)
+ DviWidget dw;
+{
+ DviState *old;
+
+ old = dw->dvi.state;
+ dw->dvi.state = old->next;
+ XtFree ((char *) old);
+}
+
+static void
+InitTypesetter (DviWidget dw)
+{
+ while (dw->dvi.state)
+ pop_env (dw);
+ dw->dvi.size_scale = dw->dvi.size_scale_set;
+ push_env (dw);
+ FlushCharCache (dw);
+}
+
+static void
+SetFont (DviWidget dw)
+{
+ dw->dvi.cache.font_size = dw->dvi.state->font_size;
+ dw->dvi.cache.font_number = dw->dvi.state->font_number;
+ dw->dvi.cache.font = QueryFont (dw,
+ dw->dvi.cache.font_number,
+ dw->dvi.cache.font_size);
+}
+
+static void
+PutCharacters (dw, src, len)
+ DviWidget dw;
+ unsigned char *src;
+ int len;
+{
+ int xx, yx;
+ int fx, fy;
+ char *dst;
+ int c;
+
+ xx = ToX(dw, dw->dvi.state->x);
+ yx = ToX(dw, dw->dvi.state->y);
+ fy = FontSizeInPixels (dw, dw->dvi.state->font_size);
+ fx = fy * len;
+ /*
+ * quick and dirty extents calculation:
+ */
+ if (yx + fy >= dw->dvi.extents.y1 &&
+ yx - fy <= dw->dvi.extents.y2 &&
+ xx + fx >= dw->dvi.extents.x1 &&
+ xx - fx <= dw->dvi.extents.x2)
+ {
+#ifdef USE_XFT
+ XftFont *font;
+ DviTextItem *text;
+#else
+ register XFontStruct *font;
+ register XTextItem *text;
+#endif
+
+ if (!dw->dvi.display_enable)
+ return;
+
+ if (yx != dw->dvi.cache.y ||
+ dw->dvi.cache.char_index + len > DVI_CHAR_CACHE_SIZE)
+ FlushCharCache (dw);
+ /*
+ * load a new font, if the current block is not empty,
+ * step to the next.
+ */
+ if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
+ dw->dvi.cache.font_number != dw->dvi.state->font_number)
+ {
+ SetFont (dw);
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ }
+ }
+ if (xx != dw->dvi.cache.x) {
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ }
+ }
+ if (!dw->dvi.cache.font)
+ SetFont (dw);
+ text = &dw->dvi.cache.cache[dw->dvi.cache.index];
+ font = dw->dvi.cache.font;
+ dst = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
+ if (text->nchars == 0) {
+ text->chars = dst;
+#ifdef USE_XFT
+ text->x = xx;
+#else
+ text->delta = xx - dw->dvi.cache.x;
+#endif
+#ifdef USE_XFT
+ text->font = font;
+#endif
+ if (font != dw->dvi.font) {
+#ifndef USE_XFT
+ text->font = font->fid;
+#endif
+ dw->dvi.font = font;
+ }
+#ifndef USE_XFT
+ else
+ text->font = None;
+#endif
+ dw->dvi.cache.x = xx;
+ }
+ dw->dvi.cache.char_index += len;
+ text->nchars += len;
+ while (len--)
+ {
+ c = *src++;
+ *dst++ = c;
+ if (font)
+ dw->dvi.cache.x += charWidth(dw,font,c);
+ }
+ }
+}
+
+static void
+ParseDrawFunction(dw, buf)
+ DviWidget dw;
+ char *buf;
+{
+ int n, m, n1, m1;
+
+ SetGCForDraw (dw);
+ switch (buf[0]) {
+ case 'l': /* draw a line */
+ sscanf(buf+1, "%d %d", &n, &m);
+ DrawLine(dw, n, m);
+ break;
+ case 'c': /* circle */
+ sscanf(buf+1, "%d", &n);
+ DrawCircle(dw, n);
+ break;
+ case 'e': /* ellipse */
+ sscanf(buf+1, "%d %d", &m, &n);
+ DrawEllipse(dw, m, n);
+ break;
+ case 'a': /* arc */
+ sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
+ DrawArc(dw, n, m, n1, m1);
+ break;
+ case '~': /* wiggly line */
+ DrawSpline(dw, buf+1,1);
+ break;
+ case 't': /* line width */
+ sscanf(buf+1, "%d", &n);
+ dw->dvi.state->line_width = n;
+ break;
+ case 's': /* line style */
+ sscanf(buf+1, "%d", &n);
+ /* XXX */
+ break;
+ default:
+ /* warning("unknown drawing function %s", buf); */
+ break;
+ }
+}
+
+extern int LastPage, CurrentPage;
+
+static void
+ParseDeviceControl(dw) /* Parse the x commands */
+ DviWidget dw;
+{
+ char str[20], str1[50];
+ int c, n;
+
+ GetWord (dw, str, 20);
+ switch (str[0]) { /* crude for now */
+ case 'T': /* output device */
+ GetWord(dw, str, 20);
+ break;
+ case 'i': /* initialize */
+ InitTypesetter (dw);
+ break;
+ case 't': /* trailer */
+ break;
+ case 'p': /* pause -- can restart */
+ break;
+ case 's': /* stop */
+ StopSeen = 1;
+ return;
+ case 'r': /* resolution when prepared */
+ SetDeviceResolution (dw, GetNumber (dw));
+ break;
+ case 'f': /* font used */
+ n = GetNumber(dw);
+ GetWord(dw, str, 20);
+ GetLine(dw, str1, 50);
+ SetFontPosition(dw, n, str, str1);
+ break;
+ case 'H': /* char height */
+ break;
+ case 'S': /* slant */
+ break;
+ }
+ while (DviGetC(dw,&c) != '\n') /* skip rest of input line */
+ if (c == EOF)
+ return;
+}