diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi/previewers/texx.c |
Initial commit
Diffstat (limited to 'dviware/umddvi/previewers/texx.c')
-rw-r--r-- | dviware/umddvi/previewers/texx.c | 1382 |
1 files changed, 1382 insertions, 0 deletions
diff --git a/dviware/umddvi/previewers/texx.c b/dviware/umddvi/previewers/texx.c new file mode 100644 index 0000000000..feaf524b29 --- /dev/null +++ b/dviware/umddvi/previewers/texx.c @@ -0,0 +1,1382 @@ +/* + * This program is Copyright (C) 1987 by the Board of Trustees of the + * University of Illinois, and by the author Dirk Grunwald. + * + * This program may be freely copied, as long as this copyright + * message remaines affixed. It may not be sold, altough it may + * be distributed with other software which is sold. If the + * software is distributed, the source code must be made available. + * + * No warrenty, expressed or implied, is given with this software. + * It is presented in the hope that it will prove useful. + */ +#include <sys/types.h> +#include <X/Xlib.h> +#include <X/Xutil.h> +#include <X/cursorfont.h> +#include <stdio.h> +#include <ctype.h> + +#include "dvistuff.h" +/* + * These constants may need to be changed on your implementation + */ + +#define BitsPerByte 8 +#define BitsPerShort 16 +#define BytesPerShort (sizeof(short)) + +#define BitsPerByteMask 0x7 +#define BitsPerByteShift 3 + +#define BytesPerShot 2 +/* + * Note that ROUNDUP evaluates Y twice. + */ +#define ROUNDUP(x,y) (((x)+(y)-1) / (y)) + + + +int debug = 0; +static int obscured = 1; + + +/* + * X-11 related variables + */ + +Display *DISP; +static Window win; +static int backpix; +static GC highpix, forepix; +static GC specialGC; +static int defaultScreen; + +static Cursor workingCursor; +static Cursor readyCursor; + +/* + * TeX-Dvi related variables + */ + +static int rawDviHeight; +static int rawDviWidth; /* part of X interface, not dvistuff */ +static int maxHeight; +static int maxWidth; + +static int screenWidth, screenHeight; + +#define MAX_LEAVES 2 +#define LEAF_LEFT 0 +#define LEAF_RIGHT 1 + +static int Leaves; +static int currentLeaf = 0; +static int pageOnLeaf[MAX_LEAVES] = {-1,-1}; +static int haveLargePage[MAX_LEAVES] = {-1, -1}; + +#define SHRINK_NORMAL 0 +#define SHRINK_LARGE 1 +#define MAX_SHRINKS 2 + +static int page_w[MAX_SHRINKS], page_h[MAX_SHRINKS]; +static int leaf_w[MAX_SHRINKS]; + +static int shrinkFactor[MAX_SHRINKS]; +static int currentShrink; +static struct glyph **shrunkenGlyphs[MAX_SHRINKS][MAX_FONTFAMILY]; +static XImage **shrunkenImages[MAX_SHRINKS][MAX_FONTFAMILY]; + +static int reverse = 0; + +static double specialConv; + +char *malloc(), *calloc(), *index(); + +#define MAX(a,b) ((a) < (b)) ? (b) : (a) +#define MIN(a,b) ((a) < (b)) ? (a) : (b) + +/* + * I don't know why this is needed, but our sun seems to thing + * and is or & vice versa + */ + +#ifdef mc68000 +#define GXAND GXand +#define GXOR GXor +#else +#define GXAND GXor +#define GXOR GXand +#endif + +main(argc, argv) + int argc; + char **argv; +{ + + int xargc=argc; + char **xargv=argv; + + char *file; + char *display = NULL; + char *option; + + int bwidth = 2; + char *fore_color; + char *back_color; + char *high_color; + char *brdr_color; + char *mous_color; + char *geometry = NULL, def[32]; + + int bdrpix, mouspix; + XColor cdef; + XSizeHints hints; + XSetWindowAttributes xswattrs; + unsigned long xswattrs_mask; + + double atof(); + + char *getenv(); + + ProgName = *argv; + argv++; + argc--; + + if ((DISP = XOpenDisplay(display)) == NULL) { + + fprintf(stderr, "[%s] Can't open display '%s'\n", + ProgName, XDisplayName(display)); + exit(1); + } + + if ((option = XGetDefault(DISP, ProgName, "ReverseVideo")) && + strcmp(option, "on") == 0) + reverse = 1; + if (option = XGetDefault(DISP, ProgName, "BorderWidth")) + bwidth = atoi(option); + fore_color = XGetDefault(DISP, ProgName, "ForeGround"); + back_color = XGetDefault(DISP, ProgName, "BackGround"); + high_color = XGetDefault(DISP, ProgName, "Highlight"); + brdr_color = XGetDefault(DISP, ProgName, "Border"); + mous_color = XGetDefault(DISP, ProgName, "Mouse"); + + option = XGetDefault(DISP, ProgName, "NormalShrink"); + shrinkFactor[SHRINK_NORMAL] = (option == 0) ? 0 : atoi(option); + + option = XGetDefault(DISP, ProgName, "LargeShrink"); + shrinkFactor[SHRINK_LARGE] = (option == 0) ? 0 : atoi(option); + + option = XGetDefault(DISP, ProgName, "Blackness"); + dviBlackness = (option == 0) ? DEFAULT_BLACKNESS : atoi(option); + + option = XGetDefault(DISP, ProgName, "Leaves"); + Leaves = (option == 0) ? 0 : atoi(option); + + option = XGetDefault(DISP, ProgName, "Dpi"); + dviDPI = (option == 0) ? DEFAULT_DPI : atoi(option); + + option = XGetDefault(DISP, ProgName, "TopMargin"); + dviVVMargin = (option == 0) ? DEFAULT_VVMARGIN : atof(option) * dviDPI; + + option = XGetDefault(DISP, ProgName, "SideMargin"); + dviHHMargin = (option == 0) ? DEFAULT_HHMARGIN : atof(option) * dviDPI; + + file = NULL; + + while (argc) { + if (strcmp(*argv, "-p") == 0 && argc > 1) { + argv++; + argc--; + dviDPI = atoi(*argv); + if (dviDPI <= 0) goto usage; + } else if (strcmp(*argv, "-rv") == 0) { + reverse = !reverse; + } else if (strcmp(*argv, "-bw") == 0 && argc > 1) { + argv++; + argc--; + bwidth = atoi(*argv); + } else if (strcmp(*argv, "-fg") == 0 && argc > 1) { + argv++; + argc--; + fore_color = *argv; + } else if (strcmp(*argv, "-bg") == 0 && argc > 1) { + argv++; + argc--; + back_color = *argv; + } else if (strcmp(*argv, "-hl") == 0 && argc > 1) { + argv++; + argc--; + high_color = *argv; + } else if (strcmp(*argv, "-bd") == 0 && argc > 1) { + argv++; + argc--; + brdr_color = *argv; + } else if (strcmp(*argv, "-ms") == 0 && argc > 1) { + argv++; + argc--; + mous_color = *argv; + } else if (strcmp(*argv,"-l") == 0 && argc > 1) { + argv++; + argc--; + Leaves = atoi(*argv); + if( Leaves < 1 || Leaves > MAX_LEAVES) { + fprintf(stderr,"[%s] Bad number of leaves(%d), using %d\n", + ProgName, Leaves, MAX_LEAVES); + Leaves = MAX_LEAVES; + } + } else if (strcmp(*argv,"-ns") == 0 && argc > 1) { + argv++; + argc--; + shrinkFactor[SHRINK_NORMAL] = atoi(*argv); + } else if (strcmp(*argv,"-ls") == 0 && argc > 1) { + argv++; + argc--; + shrinkFactor[SHRINK_LARGE] = atoi(*argv); + } else if (strcmp(*argv,"-bl") == 0 && argc > 1) { + argv++; + argc--; + dviBlackness = atoi(*argv); + } else if (strcmp(*argv,"-dpi") == 0 && argc > 1) { + argv++; + argc--; + dviDPI = atoi(*argv); + } else if (strcmp(*argv,"-tm") == 0 && argc > 1) { + argv++; + argc--; + dviVVMargin = dviDPI * atof(*argv); + } else if (strcmp(*argv,"-sm") == 0 && argc > 1) { + argv++; + argc--; + dviHHMargin = dviDPI * atof(*argv); + } else if (**argv == '=') { + geometry = *argv; + } else if (**argv != '-') { + if (index(*argv, ':') != NULL) + display = *argv; + else + file = *argv; + } else { + usage: + fprintf(stderr, "Usage: %s [-s <shrink>] [-l <leaves>] [-rv] [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] [-ms <color>] [=<geometry>] [host:display] dviFile\n", + ProgName); + exit(1); + } + argv++; + argc--; + } + if (file == NULL) + goto usage; + if ((dviFile = fopen(file, "r")) == NULL) { + int n = strlen(file); + char *dvi_name; + + if (strcmp(file + n - sizeof(".dvi") + 1, ".dvi") == 0) { + perror(file); + exit(1); + } + dvi_name = malloc((unsigned) n + sizeof(".dvi")); + sprintf(dvi_name, "%s.dvi", file); + if ((dviFile = fopen(dvi_name, "r")) == NULL) { + perror(dvi_name); + exit(1); + } + } + + dviInit(); + + specialConv = (float) dviDPI / 1000.0; + +/* + * If no shrink factor was chosen, pick one which will work out nicely + * on their display + */ + + defaultScreen = XDefaultScreen(DISP); + + maxHeight = XDisplayHeight(DISP, defaultScreen) - 2 * bwidth; + maxWidth = XDisplayWidth(DISP, defaultScreen) - 2 * bwidth; + + rawDviHeight = dviTallestPage + 2 * dviVVMargin; + rawDviWidth = dviWidestPage + 2 * dviHHMargin; + + if (Leaves == 0) { + if (dviTotalPages == 1) { + Leaves = 1; + } else { + Leaves = 2; + } + } + + if (shrinkFactor[SHRINK_NORMAL] == 0) { + int sH; + int sW; + int sH2; + int sW2; + int shrink2; + + sH = (rawDviHeight + maxHeight - 1) / maxHeight; + sW = (Leaves * rawDviWidth + maxWidth - 1) / maxWidth; + + shrinkFactor[SHRINK_NORMAL] = MAX(sW, sH); + shrinkFactor[SHRINK_NORMAL] = MAX(shrinkFactor[SHRINK_NORMAL], 1); + +/* + * Check to see if we can get another shrink size bigger display + * if we cut the margins. + */ + + sH2 = (dviTallestPage + (dviHHMargin/32) + maxHeight - 1) + / maxHeight; + sW2 = ( Leaves * (dviWidestPage + (dviVVMargin/32)) + + maxHeight - 1) / maxHeight; + + shrink2 = MAX(sH2, sW2); + shrink2 = MAX(shrink2, 1); + + if (shrink2 < shrinkFactor[SHRINK_NORMAL]) { + dviVVMargin /= 32; + dviHHMargin /= 32; + rawDviHeight = dviTallestPage + 2 * dviVVMargin; + rawDviWidth = dviWidestPage + 2 * dviHHMargin; + shrinkFactor[SHRINK_NORMAL] = shrink2; + } + } + + page_h[SHRINK_NORMAL]=(rawDviHeight + shrinkFactor[SHRINK_NORMAL] - 1) + / shrinkFactor[SHRINK_NORMAL]; + leaf_w[SHRINK_NORMAL]=(rawDviWidth + shrinkFactor[SHRINK_NORMAL] - 1) + / shrinkFactor[SHRINK_NORMAL]; + +/* + * Based on the shrink factor, choose a shrink factor for the enlarged + * display + */ + + if (shrinkFactor[SHRINK_LARGE] == 0) { + shrinkFactor[SHRINK_LARGE] = shrinkFactor[SHRINK_NORMAL] / 2; + } + + shrinkFactor[SHRINK_LARGE] = MIN(shrinkFactor[SHRINK_LARGE], + shrinkFactor[SHRINK_NORMAL]-1); + shrinkFactor[SHRINK_LARGE] = MAX(shrinkFactor[SHRINK_LARGE], 1); + + page_h[SHRINK_LARGE]=(rawDviHeight + shrinkFactor[SHRINK_LARGE] - 1) + / shrinkFactor[SHRINK_LARGE]; + leaf_w[SHRINK_LARGE]=(rawDviWidth + shrinkFactor[SHRINK_LARGE] - 1) + / shrinkFactor[SHRINK_LARGE]; + +/* + * Compute the page size given the number of leaves. We may have + * to scale back if everything can't fit. + */ + + if (leaf_w[SHRINK_NORMAL] * Leaves <= maxWidth) { + page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL] * Leaves; + } else { + page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL]; + Leaves = 1; + } + + screenWidth = (page_w[SHRINK_NORMAL] > maxWidth) + ? maxWidth : page_w[SHRINK_NORMAL]; + screenHeight = (page_h[SHRINK_NORMAL] > maxHeight) + ? maxHeight : page_h[SHRINK_NORMAL]; + + highpix = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL); + forepix = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL); + + XCopyGC(DISP, DefaultGC(DISP, 0), (1L<<(GCLastBit+1))-1, highpix); + XCopyGC(DISP, highpix, (1L<<(GCLastBit+1))-1, forepix); + + if (reverse) { + + XSetForeground(DISP, forepix, WhitePixel(DISP, defaultScreen)); + XSetForeground(DISP, highpix, WhitePixel(DISP, defaultScreen)); + backpix = BlackPixel(DISP, defaultScreen); + bdrpix = WhitePixel(DISP, defaultScreen); + mouspix = WhitePixel(DISP, defaultScreen); + XSetFunction(DISP, forepix, GXAND); /* or */ + XSetFunction(DISP, highpix, GXAND); + + } else { + + XSetForeground(DISP, forepix, BlackPixel(DISP, defaultScreen)); + XSetForeground(DISP, highpix, BlackPixel(DISP, defaultScreen)); + backpix = WhitePixel(DISP, defaultScreen); + bdrpix = BlackPixel(DISP, defaultScreen); + mouspix = BlackPixel(DISP, defaultScreen); + XSetFunction(DISP, forepix, GXOR); /* and */ + XSetFunction(DISP, highpix, GXOR); + } + + if (DisplayCells(DISP, 0) > 2) { + Colormap dcm = DefaultColormap(DISP, defaultScreen); + if (fore_color + && XParseColor(DISP, dcm, fore_color, &cdef) + && XAllocColor(DISP, dcm, &cdef)) { + XSetForeground(DISP, forepix, cdef.pixel); + } + + if (back_color + && XParseColor(DISP, dcm, back_color, &cdef) + && XAllocColor(DISP, dcm, &cdef)) { + backpix = cdef.pixel; + } + + if (high_color + && XParseColor(DISP, dcm, high_color, &cdef) + && XAllocColor(DISP, dcm, &cdef)) { + XSetForeground(DISP, highpix, cdef.pixel); + } + + if (brdr_color + && XParseColor(DISP, dcm, brdr_color, &cdef) + && XAllocColor(DISP, dcm, &cdef)) + { + /* null statement? */ + } + + if (mous_color + && XParseColor(DISP, dcm, mous_color, &cdef) + && XAllocColor(DISP, dcm, &cdef)) { + mouspix = cdef.pixel; + } + } + + XSetBackground(DISP, forepix, backpix); + XSetBackground(DISP, highpix, backpix); + + sprintf(def, "=%dx%d+0+0", screenWidth, screenHeight); + + hints.width = page_w[SHRINK_NORMAL]; + hints.height = page_h[SHRINK_NORMAL]; + hints.x = 0; hints.y = 0; + hints.flags = (PSize | PPosition); + + xswattrs.border_pixel = bdrpix; + xswattrs.background_pixel = backpix; + xswattrs_mask = (CWBackPixel|CWBorderPixel); + + win = XCreateWindow(DISP, RootWindow(DISP, defaultScreen), + 0, 0, + screenWidth, screenHeight, + bdrpix, + 0, /* depth from parent */ + InputOutput, + CopyFromParent, + xswattrs_mask, + &xswattrs); + + XSetStandardProperties(DISP, win, + ProgName, "DVI Previewer", + None, + argv, argc, &hints); + + XMapRaised(DISP, win); + XSelectInput(DISP, win, + KeyPressMask|ButtonPressMask | ButtonReleaseMask + |ExposureMask | VisibilityChangeMask); + + workingCursor = XCreateFontCursor(DISP, XC_watch); + readyCursor = XCreateFontCursor(DISP, XC_spraycan); + + XDefineCursor(DISP, win, workingCursor); + XFlush(DISP); + + specialGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL); + XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, specialGC); + + mainLoop(); + stop_output(0); +} + +/* + * Pixmap manipulation routines + */ + +static Pixmap pasteUpPixmap[MAX_SHRINKS][MAX_LEAVES]; +static GC pasteFillGC; +static GC pasteCopyGC; + +static int largePixmapsAllocated = 0; + +/* + * Ideally, we'd like to paint up a local pixmap & then transmit the + * entire pixmap. However, it looks like pixmaps require interaction + * with the server. + * + * So, if the entire page fits on the screen, we'll paint the screen + * and when we're done, we'll copy the screen to the pixmap. This + * gives the illusion of progress, but allows us to do fast re-paints. + * + * If we're *not* on the display, we'll just draw to the pixmap and + * update it at the end + */ + +static int buildToPixmap = 1; + +static void +clearPixmap(leaf, shrinkSize) +int leaf; +int shrinkSize; +{ + if (leaf< 0 || leaf >= Leaves) { + fprintf(stderr,"[%s] Reference to bogus leaf in clearPixmap: %d\n", + ProgName, leaf); + exit(1); + } + + if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) { + fprintf(stderr,"[%s] reference to bogus shrink %d\n", + ProgName, shrinkSize); + exit(1); + } + + XFillRectangle(DISP, pasteUpPixmap[shrinkSize][leaf], pasteFillGC, 0, 0, + leaf_w[shrinkSize], page_h[shrinkSize]); +} + +static void +clearWindow(leaf) +int leaf; +{ + XFillRectangle(DISP, win, pasteFillGC, + leaf * leaf_w[SHRINK_NORMAL], 0, + leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL]); +} + +allocatePixmaps() +{ + int i; + + for (i = 0; i < Leaves; i++ ) { + pasteUpPixmap[SHRINK_NORMAL][i] = + XCreatePixmap(DISP, win, leaf_w[SHRINK_NORMAL], + page_h[SHRINK_NORMAL], 1); + + if (pasteUpPixmap[SHRINK_NORMAL][i] == 0) { + fprintf(stderr,"[%s] erp! out of PIXMAP memory!\n", + ProgName); + exit(1); + } + } + + largePixmapsAllocated = 0; + + if (pasteFillGC == 0) { + pasteFillGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen),0,NULL); + pasteCopyGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen),0,NULL); + XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, pasteFillGC); + XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, pasteCopyGC); + if (reverse) { + XSetForeground(DISP, pasteFillGC, BlackPixel(DISP, defaultScreen)); + } else { + XSetForeground(DISP, pasteFillGC, WhitePixel(DISP, defaultScreen)); + } + XSetFunction(DISP, pasteFillGC, GXcopy); + XSetFunction(DISP, pasteCopyGC, GXcopy); + } + +/* + * Clear the pixmap + */ + for (i = 0; i < Leaves; i++) { + clearPixmap(i, SHRINK_NORMAL); + } +} + +allocateLargePixmaps() +{ + int i; + for (i = 0; i < Leaves; i++) { + pasteUpPixmap[SHRINK_LARGE][i] = + XCreatePixmap(DISP, win, leaf_w[SHRINK_LARGE], + page_h[SHRINK_LARGE], 1); + + clearPixmap(i, SHRINK_LARGE); + } + + largePixmapsAllocated = 1; +} + +/* + * display the normal sized leaf + */ +static void +displayLeaves() +{ + int leaf; + XClearWindow(DISP,win); + for (leaf = 0; leaf < Leaves; leaf++) { + XCopyArea(DISP, pasteUpPixmap[SHRINK_NORMAL][leaf], win, forepix, + 0, 0, + leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], + leaf_w[SHRINK_NORMAL] * leaf, 0); + } +} + +static void displayLeaf(leaf) +int leaf; +{ + clearWindow(leaf); + XCopyArea(DISP, pasteUpPixmap[SHRINK_NORMAL][leaf], win, forepix, + 0, 0, + leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], + leaf_w[SHRINK_NORMAL] * leaf, 0); +} + +static void +swapLeaf(from, to) +int from; +int to; +{ + Pixmap tempPix; + int tempNum; + + if (to < 0 || to >= Leaves) { + fprintf(stderr,"[%s] bogus to leaf %d in swapLeaf\n", + ProgName, to); + exit(1); + } + if (from < 0 || from >= Leaves) { + fprintf(stderr,"[%s] bogus from leaf %d in swapLeaf\n", + ProgName, from); + exit(1); + } + + tempPix = pasteUpPixmap[SHRINK_NORMAL][to]; + pasteUpPixmap[SHRINK_NORMAL][to] = pasteUpPixmap[SHRINK_NORMAL][from]; + pasteUpPixmap[SHRINK_NORMAL][from] = tempPix; + + tempPix = pasteUpPixmap[SHRINK_LARGE][to]; + pasteUpPixmap[SHRINK_LARGE][to] = pasteUpPixmap[SHRINK_LARGE][from]; + pasteUpPixmap[SHRINK_LARGE][from] = tempPix; + + tempNum = pageOnLeaf[to]; + pageOnLeaf[to] = pageOnLeaf[from]; + pageOnLeaf[from] = tempNum; + + tempNum = haveLargePage[to]; + haveLargePage[to] = haveLargePage[from]; + haveLargePage[from] = tempNum; +} + +static void +buildLeaf(leaf, page, shrinkSize) +int leaf; +int page; +int shrinkSize; +{ + XDefineCursor(DISP, win, workingCursor); + + if (leaf < 0 || leaf >= Leaves) { + fprintf(stderr,"[%s] bogus leaf %d in buildLeaf\n", + ProgName, leaf); + exit(1); + } + + if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) { + fprintf(stderr,"[%s] Bogus shrink size %d in buildLeaf\n", + ProgName, shrinkSize); + exit(1); + } + + if (shrinkSize == SHRINK_LARGE && !largePixmapsAllocated) { + allocateLargePixmaps(); + } + +/* + * If this is a normal size page, kill the information + * for the large version. + */ + if (shrinkSize == SHRINK_NORMAL) { + haveLargePage[leaf] = -1; + } + +/* + * Determine if this is a valid page. If it's not, we'll just clear + * the particular leaf. + */ + + if (page < 0 || page >= dviTotalPages) { + clearPixmap(leaf, shrinkSize); + + if (shrinkSize == SHRINK_NORMAL) { + clearWindow(leaf); + } + } else { + + if (obscured || shrinkSize == SHRINK_LARGE) { + buildToPixmap = 1; + } else { + buildToPixmap = 0; + } + + if (buildToPixmap) { + clearPixmap(leaf, shrinkSize); + } else { + clearPixmap(leaf, shrinkSize); + if (shrinkSize == SHRINK_NORMAL) { + clearWindow(leaf); + } + } + +/* + * Note that dviPreparePage may change dviCurrentPage + */ + + currentLeaf = leaf; + currentShrink = shrinkSize; + + dviPreparePage(page); + + page = dviCurrentPage; + +/* + * Save the constructed page if we were painting it to the screen + */ + put_border(0, 0, leaf_w[currentShrink], page_h[currentShrink], 1); + + if (! buildToPixmap && shrinkSize == SHRINK_NORMAL) { + XCopyArea(DISP, win, pasteUpPixmap[SHRINK_NORMAL][leaf], forepix, + leaf * leaf_w[currentShrink], 0, + screenWidth, screenHeight, 0,0); + } else if (shrinkSize == SHRINK_NORMAL) { + displayLeaf(leaf); + } + } + + pageOnLeaf[leaf] = dviCurrentPage; + XDefineCursor(DISP, win, readyCursor); + + XFlush(DISP); +} + +/* + * interfaces to dvistuff + */ + +/* + * Whenever a new font is registers, we create a shrunken Glyph + * table for it. However, we don't shrink the glyphs -- that's + * done on the fly by the putChar routine. + */ + +DviFont * +applicationNewFont(f, key) +struct font *f; +int key; +{ + int shrink; + + if (key < 0 || key > MAX_FONTFAMILY) { + fprintf(stderr,"[%s] bogus key in Newfont = %d\n", + ProgName, key); + exit(1); + } + + for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) { + + if (shrunkenGlyphs[shrink][key] == 0) { + int lth = sizeof(struct glyph *) * MAX_GLYPH; + struct glyph **g; + + g = (struct glyph **) malloc( lth ); + bzero(g, lth); + shrunkenGlyphs[shrink][key] = g; + } + + if (shrunkenImages[shrink][key] == 0) { + int lth = sizeof(XImage *) * MAX_GLYPH; + XImage **image; + + image = (XImage **) malloc(lth); + bzero(image, lth); + shrunkenImages[shrink][key] = image; + } + } + + return(f); +} + +/* + * When we reset a font, we only need to free the storage for the + * shrunken glyphs. We keep the glyph table available because we're + * very likely to fill it in again. + */ + +void +applicationResetFont(fi, key) +struct fontinfo *fi; +int key; +{ + int i; + struct glyph **theseGlyphs; + XImage **theseImages; + int shrink; + + + for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) { + theseGlyphs = shrunkenGlyphs[shrink][key]; + if (theseGlyphs != 0) { + for (i = 0; i < MAX_GLYPH; i++) { + struct glyph *g; + + g = theseGlyphs[i]; + + if (g != 0) { + if ( g -> g_raster != 0) { + free(g -> g_raster); + } + free(g); + theseGlyphs[i] = 0; + } + } + } + + theseImages = shrunkenImages[shrink][key]; + + if (theseImages != 0) { + for (i = 0; i < MAX_GLYPH; i++) { + if (theseImages[i] != 0) { + XDestroyImage(theseImages[i]); + } + theseImages[i] = 0; + } + } + } +} + + +void +applicationPutChar(hh, vv, charCode) +int hh; +int vv; +int charCode; +{ + register struct glyph *g; + int x,y; + XImage *image; + int key; + + key = dviCurrentFont -> family; + + g = shrunkenGlyphs[currentShrink][key][charCode]; + + if (g == 0) { + g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode], + shrinkFactor[currentShrink], + shrinkFactor[currentShrink]); + shrunkenGlyphs[currentShrink][key][charCode] = g; + } + + if (g == 0 || !HASRASTER(g)) return; + + hh /= shrinkFactor[currentShrink]; + vv /= shrinkFactor[currentShrink]; + + x = hh - g -> g_xorigin; + y = vv - g -> g_yorigin; + + image = shrunkenImages[currentShrink][key][charCode]; + + if (image == 0 ) { + image = XCreateImage(DISP, DefaultVisual(DISP, defaultScreen), + 1, XYBitmap, + 0, g->g_raster, + g->g_width, g->g_height, + 16, 0); + + shrunkenImages[currentShrink][key][charCode] = image; + } + + if (buildToPixmap) { + XPutImage(DISP, pasteUpPixmap[currentShrink][currentLeaf], + forepix, image, + 0, 0, + x, y, + g->g_width, g->g_height); + } else { + XPutImage(DISP, win, + forepix, image, + 0, 0, + x + currentLeaf * leaf_w[currentShrink], y, + g->g_width, g->g_height); + } +} + +void +applicationSetRule(hh, vv, h, w) +int hh, vv; +int h, w; +{ +/* (w,h) specifies lower left corner of rule box */ + int nh, nw; + + hh /= shrinkFactor[currentShrink]; + vv /= shrinkFactor[currentShrink]; + + nh = h / shrinkFactor[currentShrink]; + nw = w / shrinkFactor[currentShrink]; + + if (nh == 0 && h != 0) { + nh = 1; + } + if (nw == 0 && w != 0) { + nw = 1 ; + } + + put_rectangle(hh, vv - nh, nw, nh, forepix); +} + +/* + * This code attempts to support the same set of specials + * as imagen1 + */ +static char * +skipWhite(c) +char *c; +{ + while (c != 0 && *c != 0 && isspace(*c)) c++; + return(c); +} + +static char * +skipNonWhite(c) +char *c; +{ + while (c != 0 && *c != 0 && ! isspace(*c)) c++; + return(c); +} + +#define MAX_POINTS 128 +static int pointListCount = 0; +static XPoint pointList[MAX_POINTS]; + +void +applicationDoSpecial(command) +char *command; +{ + char com[20]; + int x,y; + char *c, *oc; + + c = skipWhite(command); + if (*c == 0) return; + + oc = c; + c = skipNonWhite(c); + x = *c; + *c = '\000'; + strncpy(com, oc, 20); + *c = x; + c++; + + if (strcmp(com, "pa") == 0) { + sscanf(c, " %d %d ", &x, &y); + pointList[pointListCount].x = + (specialConv * x + dviHH) / shrinkFactor[currentShrink]; + pointList[pointListCount].y = + (specialConv * y + dviVV) / shrinkFactor[currentShrink]; + + if (! buildToPixmap) { + pointList[pointListCount].x += currentLeaf * leaf_w[currentShrink]; + } + + pointListCount++; + +/* + * Make all lines styles come out as a simple line. + * Crude, but effective. + */ + + } else if (strcmp(com, "fp") == 0 + || strcmp(com,"da") == 0 + || strcmp(com,"dt") == 0) { + if (pointListCount > 0) { + + if (buildToPixmap) { + XDrawLines(DISP, pasteUpPixmap[currentShrink][currentLeaf], + specialGC, pointList, pointListCount, + CoordModeOrigin); + } else { + XDrawLines(DISP, win, + specialGC, pointList, pointListCount, + CoordModeOrigin); + } + } + pointListCount = 0; + + } else if (strcmp(com, "pn") == 0) { + int penSize; + sscanf(c," %d ", &penSize); + penSize /= (shrinkFactor[currentShrink] * 2); /* looks good */ + penSize = MAX(penSize,1); + penSize = MIN(penSize,99); + XSetLineAttributes(DISP, specialGC, penSize, + LineSolid, CapButt, JoinMiter); + } else { + +/* + * For now, lets just flush the special + */ + fprintf(stderr, "[%s] special \"%s\" not implemented\n", + ProgName, command); + } +} + +int +mainLoop() +{ + int ch, arg, sign, number; + XEvent event; + XWindowAttributes query; + + char trbuf[100]; + char *string; + int nbytes=0; + + int repaint; + int rebuild; + +#define BOGUSDIR -1 +#define FOREWARD 0 +#define BACKWARD 1 +#define ABSOLUTE 2 + + int direction; + +/* + * + * We need to initialized 'obscured'. + * Ideally, we would like to know if we are covered at all, but + * the best I can come up with is a way to determine if we're + * mapped. This works well for wm, uwm & no window manager at all. + */ + + XClearWindow(DISP,win); + XSync(DISP, 0); + + XGetWindowAttributes(DISP, win, &query); + obscured = ! (query.map_state == IsViewable); + + allocatePixmaps(); + dviCurrentPage = 0; + buildLeaf(LEAF_LEFT, 0, SHRINK_NORMAL); + + if (Leaves == 2) { + XGetWindowAttributes(DISP, win, &query); /* status changed? */ + obscured = ! (query.map_state == IsViewable); + buildLeaf(LEAF_RIGHT, 1, SHRINK_NORMAL); + } + + arg = 0; + number = 0; + + for (;;) { + + repaint = 1; + rebuild = 0; + direction = BOGUSDIR; + + XDefineCursor(DISP, win, readyCursor); + + bzero(&event, sizeof(event)); + XNextEvent (DISP, &event); + + string = ""; + + switch (event.type) { + +/* + * If were painting to the display, and were not completely + * visible, wed better really paint to the pixmap, otherwise, + * all the stuff painted in an obscured region wont be in the pixmap. + */ + + case VisibilityNotify: + obscured = (event.xvisibility.state != VisibilityUnobscured); + continue; + + case Expose: + string = "\f"; + nbytes = 1; + break; + + + case ButtonPress: + { + int leaf; + int otherLeaf; + int normalLeafW = leaf_w[SHRINK_NORMAL]; + int leafX; + int leafY; + int lastLeaf = -1; + + int x = event.xbutton.x; + int y = event.xbutton.y; + int lastButton = event.xbutton.button; + +/* + * Determine which leaf was pointed to & where we will display it + */ + leaf = x / normalLeafW; + if (leaf < 0 || leaf >= Leaves) { + fprintf(stderr,"[%s] error in button press, leaf = %d\n", + ProgName, leaf); + exit(1); + } + + if (leaf != lastLeaf && lastLeaf != -1) { + displayLeaf(lastLeaf); + } + lastLeaf = leaf; + + if (Leaves == 1) { + otherLeaf = leaf; + } else { + otherLeaf = 1 - leaf; + } + +/* + * Build the enlarged page if its not already there +*/ + if (haveLargePage[leaf] != pageOnLeaf[leaf]) { + buildLeaf(leaf, pageOnLeaf[leaf], SHRINK_LARGE); + haveLargePage[leaf] = pageOnLeaf[leaf]; + } + +/* + * Determine where he was looking, build a (x,y) such that + * the thing he was pointing at will be on the screen, as close to + * center as possible. + */ + + leafX = (x - (leaf * normalLeafW)); + leafX = (leafX * shrinkFactor[SHRINK_NORMAL]) + / shrinkFactor[SHRINK_LARGE]; + + leafX -= (leaf_w[SHRINK_NORMAL] / 2); + leafX = MAX(leafX, 0); + leafX = MIN(leafX, leaf_w[SHRINK_LARGE]); + + leafY = (y * shrinkFactor[SHRINK_NORMAL]) + / shrinkFactor[SHRINK_LARGE]; + + leafY -= (page_h[SHRINK_NORMAL] / 2); + leafY = MAX(leafY, 0); + leafY = MIN(leafY, page_h[SHRINK_LARGE]); + +/* + * Display the enlarged image on the leaf, wait for another + * button event (the release, we hope)& then restore the image as it was + */ + clearWindow(otherLeaf); + XCopyArea(DISP, pasteUpPixmap[SHRINK_LARGE][leaf], + win, forepix, + leafX, leafY, + leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], + leaf_w[SHRINK_NORMAL] * otherLeaf, 0); + + bzero(&event, sizeof(event)); + for(;;) { + XNextEvent(DISP, &event); + if (event.type == ButtonRelease + && event.xbutton.button == lastButton) { + break; + } + } + displayLeaf(otherLeaf); + break; + } + + case ButtonRelease: + break; + + case KeyPress: + string = trbuf; + nbytes = XLookupString(&event, string, 100, NULL, NULL); + + break; + } + + if (nbytes == 0) continue; + + if (nbytes > 1) goto bad; + + switch (ch = *string) { + case 'q': + case '\003': /* control-C */ + case '\004': /* control-D */ + stop_output(0); + break; + + case 'n': + case 'f': + case ' ': + case '\n' : + case '\r' : + /* scroll forward */ + direction = FOREWARD; + rebuild = 1; + break; + + case 'p': + case 'b': + case '\b': + case 0177 : /* DEL */ + /* scroll backward */ + direction = BACKWARD; + rebuild = 1; + break; + + case '\f': + case 'r' : + /* repaint current page */ + repaint = 1; + break; + + case 'g': + /* go to absolute page */ + direction = ABSOLUTE; /* may not be, but tough */ + rebuild = 1; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (! arg) { + arg = 1; + sign = 1; + number = 0; + } + number = 10*number + sign*(ch - '0'); + + repaint = 0; + continue; + + case '-': + if (! arg) { + arg = 1; + sign = -1; + number = 0; + repaint = 0; + continue; + } else + goto bad; + default: + goto bad; + } + + if (rebuild && direction != BOGUSDIR) { + int newLeft; + int newRight; +/* + * canonicalize the request. arg is always > 0, were moving in + * some direction. + */ + + if (!arg || number == 0) { + number = 1; + } + + + if (number < 0) { + if (direction == FOREWARD) { + direction = BACKWARD; + } else if (direction == BACKWARD){ + direction = FOREWARD; + } + number = -number; + } + +/* + * Turn pages back + */ + if (direction == BACKWARD) { + newLeft = pageOnLeaf[LEAF_LEFT] - number; + } else if (direction == FOREWARD) { + newLeft = pageOnLeaf[LEAF_LEFT] + number; + } else { + newLeft = number - 1; /* pages numbered at 0 */ + } + + newLeft = MIN(newLeft, dviTotalPages-1); + newLeft = MAX(newLeft, 0); + + if (Leaves == 1) { + if (newLeft != pageOnLeaf[LEAF_LEFT]) { + buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL); + } + } else { + newRight = newLeft + 1; + + if (pageOnLeaf[LEAF_LEFT] != newLeft) { + if (newLeft == pageOnLeaf[LEAF_RIGHT]) { + swapLeaf(LEAF_RIGHT, LEAF_LEFT); + displayLeaf(LEAF_LEFT); + } else if (newRight == pageOnLeaf[LEAF_LEFT]) { + swapLeaf(LEAF_LEFT, LEAF_RIGHT); + displayLeaf(LEAF_RIGHT); + } + + if (pageOnLeaf[LEAF_LEFT] != newLeft) { + buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL); + } + + if (pageOnLeaf[LEAF_RIGHT] != newRight) { + buildLeaf(LEAF_RIGHT, newRight, SHRINK_NORMAL); + } + } + } + repaint = 0; + rebuild = 0; + arg = 0; +/* + * Only repaint it if we need to + */ + } + + if (repaint){ + displayLeaves(); + repaint = 0; + } + + continue; + + bad: + + arg = 0; /* throw away numeric argument */ + continue; + + } +} + +stop_output(sig) +{ + exit(sig); +} + +put_border(x, y, w, h, t) +int x, y, w, h, t; +{ + put_rectangle(x, y, w, t, highpix); + put_rectangle(x, y, t, h, highpix); + put_rectangle(x, y + h - t, w, t, highpix); + put_rectangle(x + w - t, y, t, h, highpix); +} + +put_rectangle(x, y, w, h, pix) +int x, y, w, h; +GC pix; +{ + if (buildToPixmap) { + XFillRectangle(DISP, pasteUpPixmap[currentShrink][currentLeaf], + pix, x, y, w, h); + } else { + XFillRectangle(DISP, win, + pix, x + currentLeaf * leaf_w[currentShrink], y, w, h); + } +} + + |