diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:21 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:49:21 +0000 |
commit | 84735728ed5f6a07d87254860e2776775c54b85b (patch) | |
tree | 3b8bd2195fd61ff50279b2bcfaaf41af01b0279f /parse.c |
Initial revisionXORG-STABLE
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 479 |
1 files changed, 479 insertions, 0 deletions
@@ -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; +} |