/* * 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 #include #include #include #include #include #include #include #include #include #include "dvistuff.h" /* * These constants may need to be changed on your implementation */ /* * Note that ROUNDUP evaluates Y twice. */ #define ROUNDUP(x,y) (((x)+(y)-1) / (y)) #define DEBUG printf #define INFORM (Debug > 2) #define TALK (Debug > 1) #define VERBOSE (Debug > 0) int Debug = 0; static int obscured = 1; /* * SunTools related variables */ static Window tool = 0; static Canvas ptubeWindow = 0; static Pixwin *ptube = 0; static int canvasHeight; static int canvasWidth; static int canvasNormalWidthOffset; static int canvasNormalHeightOffset; typedef int (*intFuncp)(); intFuncp memPixmapOps; static int foregroundMode = PIX_SRC | PIX_DST; static int clearMode = PIX_CLR; static int setMode = PIX_SET; static int copyMode = PIX_SRC; static int paintMode; static int cursorMode; static int globalArg = 0; static int globalNumber = 0; static int globalSign = 1; static int globalOtherLeaf = 0; static int globalLeafX; static int globalLeafY; static int globalDisplayState; static int globalDisplayLeaf; static int firstPage = 0; static char *dviFileName = 0; static Cursor workingCursor; static Cursor readyCursor; short workingCursorData[] = { #include ; }; mpr_static(workingCursorPixrect, 16, 16, 1, workingCursorData); short readyCursorData[] = { #include ; }; mpr_static(readyCursorPixrect, 16, 16, 1, readyCursorData); /* * TeX-Dvi related variables */ static int rawDviHeight; static int rawDviWidth; /* part of X interface, not dvistuff */ static int maxHeight; static int maxWidth; static int maxDepth; static int screenWidth, screenHeight; #define MAX_LEAVES 2 #define LEAF_LEFT 0 #define LEAF_RIGHT 1 #define DEFAULT_LEAVES 2 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]; typedef struct mpr_data MprData; static Pixrect **shrunkenPixrect[MAX_SHRINKS][MAX_FONTFAMILY]; static int reverse = 0; static double specialConv; #define TEXSUN_STATE_NAME "TEXSUN_STATE" #define maxStateLines 100 char *stateFileName; char **globalArgv; int globalArgc; char *malloc(), *calloc(), *index(); #define MAXFUNC(a,b) ((a) < (b)) ? (b) : (a) #define MINFUNC(a,b) ((a) < (b)) ? (a) : (b) stop_output() { /* * We must write the state before killing the window */ writeState(stateFileName); window_set(tool, FRAME_NO_CONFIRM, TRUE, 0); window_destroy (tool); exit (0); } main(argc, argv) int argc; char **argv; { int xargc=argc; char **xargv=argv; char *display = NULL; char option[120]; int optionEnd; char *poption; int bwidth = 2; char *geometry = NULL, def[32]; int bdrpix, mouspix; unsigned long xswattrs_mask; struct rect tool_rect; int ptubeSelected(); int repaintCanvas(); int resizeCanvas(); double atof(); char *getenv(); /* * Choose an explicit name so we always find the options. */ ProgName = "texsun"; argv++; argc--; dviFileName = NULL; strcpy(option, ProgName); sprintf(option,"/%s/", ProgName); optionEnd = strlen(option); option[optionEnd] = 0; reverse = (int) defaults_get_boolean(strcat(option,"ReverseVideo"), 0, 0); option[optionEnd] = 0; shrinkFactor[SHRINK_NORMAL] = defaults_get_integer(strcat(option,"NormalShrink"), 0, 0); option[optionEnd] = 0; shrinkFactor[SHRINK_LARGE] = defaults_get_integer(strcat(option,"LargeShrink"), 0, 0); option[optionEnd] = 0; dviDPI = defaults_get_integer(strcat(option,"Dpi"), DEFAULT_DPI, 0); option[optionEnd] = 0; Leaves = defaults_get_integer(strcat(option,"Leaves"), 0, 0); option[optionEnd] = 0; poption = defaults_get_string(strcat(option,"TopMargin"), 0, 0); dviVVMargin = DEFAULT_VVMARGIN * ( (poption == 0) ? 1.0 : atof(poption)); option[optionEnd] = 0; poption = defaults_get_string(strcat(option,"SideMargin"), 0, 0); dviHHMargin = DEFAULT_HHMARGIN * ( (poption == 0) ? 1.0 : atof(poption)); option[optionEnd] = 0; dviBlackness = defaults_get_integer(strcat(option,"Blackness"), DEFAULT_BLACKNESS, 0); option[optionEnd] = 0; stateFileName = defaults_get_string(strcat(option,"StateFile"), 0, 0); if (stateFileName == 0) { stateFileName = getenv(TEXSUN_STATE_NAME); } if (argc > 0 && strcmp(argv[0], "-new") == 0) { argv++; argc--; } else { readState(&argc, &argv, stateFileName); } globalArgc = argc; globalArgv = argv; while (argc) { if (strcmp(*argv, "-rv") == 0) { reverse = !reverse; /* * these two are for the state-saver */ } else if (strcmp(*argv, "-rvOn") == 0 ) { reverse = 1; } else if (strcmp(*argv, "-rvOff") == 0) { reverse = 0; } 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,"-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 (strcmp(*argv, "-bl") == 0 && argc > 1) { argv++; argc--; dviBlackness = atoi(*argv); } else if (strcmp(*argv, "-pg") == 0 && argc > 1) { argv++; argc--; firstPage = atoi(*argv); } else if (strcmp(*argv,"-debug") == 0 && argc > 1) { argv++; argc--; Debug = atoi(*argv); } else if (**argv != '-') { dviFileName = *argv; } else { usage: fprintf(stderr, "Usage: %s [-ns ] [-ls ] [-dpi ] \n", ProgName); fprintf(stderr, " [-l ] [-rv] [-tm ] [-sm ] dviFile\n"); exit(1); } argv++; argc--; } if (dviFileName == NULL) goto usage; if ((dviFile = fopen(dviFileName, "r")) == NULL) { int n = strlen(dviFileName); char *dvi_name; if (strcmp(dviFileName + n - sizeof(".dvi") + 1, ".dvi") == 0) { perror(dviFileName); exit(1); } dvi_name = malloc((unsigned) n + sizeof(".dvi")); sprintf(dvi_name, "%s.dvi", dviFileName); if ((dviFile = fopen(dvi_name, "r")) == NULL) { perror(dvi_name); exit(1); } dviFileName = dvi_name; } if (INFORM) { fprintf(stderr, "[texsun] call dviInit();\n"); } dviInit(); if (TALK) { fprintf(stderr,"page is %d wide, %d high\n", dviTallestPage, dviWidestPage); } if (((double) dviTallestPage * (double) dviWidestPage) > 4.0e7) { fprintf(stderr,"[%s] Warning: Your page size is %d wide and %d tall,\n", ProgName, dviTallestPage, dviWidestPage); fprintf(stderr,"which may be too big to be displayed\n"); } specialConv = (float) dviDPI / 1000.0; /* * If no shrink factor was chosen, pick one which will work out nicely * on their display */ if (INFORM) { fprintf(stderr, "[texsun] set screenSpecific\n"); } setScreenSpecifics(); rawDviHeight = dviTallestPage + 2 * dviVVMargin; rawDviWidth = dviWidestPage + 2 * dviHHMargin; if (Leaves == 0) { if (dviTotalPages == 1) { Leaves = 1; } else { Leaves = DEFAULT_LEAVES; } } if (INFORM) { fprintf(stderr, "[texsun] choose screenSpecific\n"); } 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] = MAXFUNC(sW, sH); shrinkFactor[SHRINK_NORMAL] = MAXFUNC(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 = MAXFUNC(sH2, sW2); shrink2 = MAXFUNC(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] = MINFUNC(shrinkFactor[SHRINK_LARGE], shrinkFactor[SHRINK_NORMAL]-1); shrinkFactor[SHRINK_LARGE] = MAXFUNC(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 cant 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]; tool_rect.r_left = 0; tool_rect.r_top = 0; tool_rect.r_width = 0; tool_rect.r_height = 0; cursorMode = PIX_SRC ^ PIX_DST; if (reverse) { paintMode = PIX_NOT(PIX_SRC); } else { paintMode = PIX_SRC; } if (INFORM) { fprintf(stderr,"[texsun] create the tool windows\n"); } /* create the tool */ tool = window_create (0, FRAME, FRAME_LABEL, "TeXsun", FRAME_OPEN_RECT, &tool_rect, 0); if (tool == 0) { fprintf(stderr,"Unable to create window\n"); exit(1); } ptubeWindow = window_create(tool, CANVAS, CANVAS_AUTO_SHRINK, TRUE, CANVAS_AUTO_EXPAND, TRUE, CANVAS_WIDTH, screenWidth, WIN_FIT_WIDTH, screenWidth, CANVAS_HEIGHT, screenHeight, WIN_FIT_HEIGHT, screenHeight, CANVAS_RETAINED, FALSE, CANVAS_REPAINT_PROC, repaintCanvas, CANVAS_RESIZE_PROC, resizeCanvas, WIN_EVENT_PROC, ptubeSelected, WIN_BOTTOM_MARGIN, 0, WIN_LEFT_MARGIN, 0, WIN_TOP_MARGIN, 0, WIN_RIGHT_MARGIN, 0, WIN_X, 0, WIN_Y, 0, 0); if (ptubeWindow == 0) { fprintf(stderr,"Unable to create canvas\n"); exit(1); } readyCursor = cursor_create(CURSOR_IMAGE, &readyCursorPixrect, CURSOR_OP, cursorMode, 0); workingCursor = cursor_create(CURSOR_IMAGE, &workingCursorPixrect, CURSOR_OP, cursorMode, 0); ptubeInit(); window_set(ptubeWindow, WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,0); signal (SIGINT, stop_output); signal (SIGQUIT, stop_output); signal (SIGIOT, stop_output); window_fit(ptubeWindow); window_fit(tool); if (INFORM) { fprintf(stderr,"[texsun] enter window loop\n"); } window_main_loop (tool); /* terminate tool */ stop_output(0); } /* * State-maintenance routines. * * The state is maintained in a file indicated by the environment * variable TEXSUN_STATE. * * The state is written as a sequence of options, the same options * which can be specified on the command line. * * When the state is used, the saved options are inserted in the * command line before any new options. Thus, new options will * over-ride the saved options, and both saved state and command * line options will over-ride the default options. */ readState(inOutArgc, inOutArgv, stateFileName) char ***inOutArgv; int *inOutArgc; char *stateFileName; { if (stateFileName != 0) { FILE *f; char **newArgv; char *p; int newArgc; char buffer[512]; char *bufp; int i; int argc = *inOutArgc; char **argv = *inOutArgv; newArgv = (char **) malloc( sizeof(char *) * (argc + maxStateLines)); f = fopen(stateFileName,"r"); /* * The program name has already been removed. */ newArgc = 0; if (f != 0) { while (!feof(f)) { p = fgets(buffer, 512, f); if (p != 0) { int lth; lth = strlen(buffer); p = malloc(lth + 1); strcpy(p, buffer); p[lth-1] = 0; /* kill the newline character */ newArgv[newArgc++] = p; } } for (i = 0 ; i < argc; i++ ) { newArgv[newArgc++] = argv[i]; } *inOutArgc = newArgc; *inOutArgv = newArgv; } } } writeState(stateFileName) char *stateFileName; { if (stateFileName != 0) { FILE *f; char *ptr; f = fopen(stateFileName,"w"); if (f != 0) { fprintf(f, "-rv%s\n", (reverse) ? "On" : "Off"); fprintf(f, "-l\n%d\n", Leaves); fprintf(f, "-ns\n%d\n", shrinkFactor[SHRINK_NORMAL]); fprintf(f, "-ls\n%d\n", shrinkFactor[SHRINK_LARGE]); fprintf(f, "-dpi\n%d\n", dviDPI); fprintf(f, "-tm\n%f\n", (double) ((double) dviVVMargin / (double) dviDPI)); fprintf(f, "-sm\n%f\n", (double) ((double) dviHHMargin / (double) dviDPI)); fprintf(f, "-bl\n%d\n", dviBlackness); fprintf(f, "-debug\n%d\n", Debug); fprintf(f, "-pg\n%d\n", pageOnLeaf[0]); fprintf(f, "%s\n", dviFileName); fclose(f); } } } /* * Sun Screen-specific things */ setScreenSpecifics() { struct fbtype FbType; int Fb; Fb = open("/dev/fb", O_RDONLY, 0); if (Fb < 0) { perror("open"); fprintf(stderr,"Unable to open /dev/fb\n"); exit(1); } if (ioctl(Fb, FBIOGTYPE, &FbType) == -1) { perror("ioctl"); fprintf(stderr,"Unable to determine screen size\n"); exit(1); } maxWidth = FbType.fb_width; maxHeight = FbType.fb_height; maxDepth = FbType.fb_depth; close(Fb); } resizeCanvas(canvas, width, height) { canvasWidth = width; canvasHeight = height; if (canvasWidth > (Leaves * leaf_w[SHRINK_NORMAL])) { canvasNormalWidthOffset = (canvasWidth - Leaves * leaf_w[SHRINK_NORMAL]); } if (canvasHeight > (Leaves * page_h[SHRINK_NORMAL])) { canvasNormalHeightOffset = (canvasHeight - Leaves * page_h[SHRINK_NORMAL]); } } repaintCanvas(canvas, pixwin, repaint_area) Canvas canvas; Pixwin *pixwin; Rectlist *repaint_area; { displayLeaves(); } /* * Pixmap manipulation routines */ static Pixrect *pasteUpPixmap[MAX_SHRINKS][MAX_LEAVES]; 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 = 0; static void clearPixmap(leaf, shrinkSize) int leaf; int shrinkSize; { Pixrect *w; 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); } w = pasteUpPixmap[shrinkSize][leaf]; pr_rop(w, 0, 0, leaf_w[shrinkSize], page_h[shrinkSize], clearMode, w, 0, 0); } /* * Clear the window. Actually, for a black-on-white display (normal) * this means we need to *set* the entire display using COLOR(1) color. */ static void clearWindow() { int localClear = PIX_COLOR(1) | clearMode; if (reverse) { localClear = PIX_NOT(localClear); } pw_writebackground(ptube, 0, 0, canvasWidth, canvasHeight, localClear); } allocatePixmaps() { int i; for (i = 0; i < Leaves; i++ ) { pasteUpPixmap[SHRINK_NORMAL][i] = (Pixrect *) mem_create(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); stop_output(); } } largePixmapsAllocated = 0; /* * 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] = (Pixrect *) mem_create(leaf_w[SHRINK_LARGE], page_h[SHRINK_LARGE], 1); clearPixmap(i, SHRINK_LARGE); } largePixmapsAllocated = 1; } /* * display the normal sized leaf */ static int displayLeaves() { if (globalDisplayState == SHRINK_LARGE) { /* * globalLeafX and globalLeafY point the part of the display * they want to see, scaled to the large shrink. * */ int leafX; int leafY; int leafW; int leafH; int canvasX; int canvasY; leafW = MINFUNC(leaf_w[SHRINK_LARGE], canvasWidth); leafH = MINFUNC(page_h[SHRINK_LARGE], canvasHeight); leafX = globalLeafX - (leafW / 2); /* find left side */ if (leafX < 0) { canvasX = -leafX; leafX = 0; } else { canvasX = 0; } if ((leafX + leafW) > leaf_w[SHRINK_LARGE]) { leafW = leaf_w[SHRINK_LARGE] - leafX; } leafY = globalLeafY - (leafH / 2); /* gind top side */ if (leafY < 0) { canvasY = -leafY; leafY = 0; } else { canvasY = 0; } if ((leafY + leafH) > page_h[SHRINK_LARGE]) { leafH = page_h[SHRINK_LARGE] - leafY; } #ifdef UNDEF if (leafW < canvasWidth) { leafX += (canvasWidth - leafW) / 2; } if (leafH < canvasHeight) { leafY += (canvasHeight - leafH) / 2; } #endif clearWindow(); pw_write(ptube, canvasX, canvasY, leafW, leafH, paintMode, pasteUpPixmap[SHRINK_LARGE][globalDisplayLeaf], leafX, leafY); } else { clearWindow(); pw_write(ptube, 0, 0, leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], paintMode, pasteUpPixmap[SHRINK_NORMAL][0], 0,0); pw_write(ptube, leaf_w[SHRINK_NORMAL], 0, leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], paintMode, pasteUpPixmap[SHRINK_NORMAL][1], 0,0); } } static void swapLeaf(from, to) int from; int to; { Pixrect *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; { 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); } window_set(ptubeWindow, WIN_CURSOR, workingCursor, 0); 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 = 1; } 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) { clearPixmap(leaf, SHRINK_NORMAL); /* * We save the pixmap from the *retained* image -- the tool may not * actually be up. This isn't optimal, but it saves us a lot of * hacking & having to determine when we're obscured. */ pr_rop(pasteUpPixmap[SHRINK_NORMAL][leaf], 0,0, leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], copyMode, ptube -> pw_prretained, leaf_w[SHRINK_NORMAL] * leaf, 0); } else if (shrinkSize == SHRINK_NORMAL) { /* null */ } } pageOnLeaf[leaf] = dviCurrentPage; window_set(ptubeWindow, WIN_CURSOR, readyCursor, 0); } /* * 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 (shrunkenPixrect[shrink][key] == 0) { int lth = sizeof(Pixrect *) * MAX_GLYPH; Pixrect **g; g = (Pixrect **) malloc( lth ); bzero(g, lth); shrunkenPixrect[shrink][key] = g; } } 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; Pixrect **thesePixrect; 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; } } } thesePixrect = shrunkenPixrect[shrink][key]; if (thesePixrect != 0) { for (i = 0; i < MAX_GLYPH; i++) { Pixrect *g; g = thesePixrect[i]; if (g != 0) { free(g -> pr_data); free(g); thesePixrect[i] = 0; } } } } } void applicationPutChar(hh, vv, charCode) int hh; int vv; int charCode; { register struct glyph *g; int x,y; int key; Pixrect *image; key = dviCurrentFont -> family; g = shrunkenGlyphs[currentShrink][key][charCode]; if (g == 0) { MprData *newMpr = (MprData *) malloc(sizeof(MprData)); Pixrect *newPixrect = (Pixrect *) malloc(sizeof(Pixrect)); extern struct pixrectops mem_ops; g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode], shrinkFactor[currentShrink], shrinkFactor[currentShrink]); shrunkenGlyphs[currentShrink][key][charCode] = g; newMpr -> md_linebytes = SHRUNK_GLYPH_BYTES_WIDE(g); newMpr -> md_image = (short *) g -> g_raster; newMpr -> md_offset.x = 0; newMpr -> md_offset.y = 0; newMpr -> md_primary = 0; newMpr -> md_flags = 0; newPixrect -> pr_ops = &mem_ops; newPixrect -> pr_size.x = g -> g_width; newPixrect -> pr_size.y = g -> g_height; newPixrect -> pr_depth =1; newPixrect -> pr_data = (caddr_t) newMpr; shrunkenPixrect[currentShrink][key][charCode] = newPixrect; } if (g == 0 || !HASRASTER(g)) return; hh /= shrinkFactor[currentShrink]; vv /= shrinkFactor[currentShrink]; x = hh - g -> g_xorigin; y = vv - g -> g_yorigin; image = shrunkenPixrect[currentShrink][key][charCode]; if (buildToPixmap) { pr_rop(pasteUpPixmap[currentShrink][currentLeaf], x,y, g->g_width, g->g_height, foregroundMode, image, 0,0); } else { x += currentLeaf * leaf_w[currentShrink]; pw_write(ptube, x, y, g->g_width, g->g_height, foregroundMode, image, 0,0); } } 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, setMode); } /* * 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 struct pr_pos pointList[MAX_POINTS]; static struct pr_brush specialBrush = {1}; 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) { int fx,fy; int tx,ty; int i; fx = pointList[0].x; fy = pointList[0].y; for (i = 0; i < pointListCount; i++) { tx = pointList[i].x; ty = pointList[i].y; if (buildToPixmap) { pr_vector(pasteUpPixmap[currentShrink][currentLeaf], fx, fy, tx, ty, foregroundMode, -1); } else { pw_vector(ptube, fx, fy, tx, ty, foregroundMode, -1); } fx = tx; fy = ty; } } pointListCount = 0; } else if (strcmp(com, "pn") == 0) { int penSize; sscanf(c," %d ", &penSize); penSize /= (shrinkFactor[currentShrink] * 2); /* looks good */ penSize = MAXFUNC(penSize,1); penSize = MINFUNC(penSize,99); /* * We dont do anything with this */ } else { /* * For now, lets just flush the special */ pointListCount = 0; fprintf(stderr, "[%s] special \"%s\" not implemented\n", ProgName, command); } } ptubeInit() { struct inputmask mask; ptube = canvas_pixwin(ptubeWindow); if (ptube == (Pixwin *) NULL) { fprintf(stderr,"Couldn't create ptube pixwin\n"); stop_output(0); } obscured = 1; /* SunTools does auto-save-unders */ globalDisplayState = SHRINK_NORMAL; resizeCanvas(ptube, (int) window_get(ptube, CANVAS_WIDTH), (int) window_get(ptube, CANVAS_HEIGHT)); allocatePixmaps(); dviCurrentPage = firstPage; buildLeaf(LEAF_LEFT, dviCurrentPage, SHRINK_NORMAL); if (Leaves == 2) { buildLeaf(LEAF_RIGHT, dviCurrentPage + 1, SHRINK_NORMAL); } globalArg = 0; globalNumber = 0; } /* respond to damage to ptube subwindow */ static int ptubeSighandler(sw) caddr_t sw; { displayLeaves(); } static int ptubeSelected(win, inputEvent, arg) Window *win; Event *inputEvent; caddr_t arg; { int ch; int repaint; int rebuild; #define BOGUSDIR -1 #define FOREWARD 0 #define BACKWARD 1 #define ABSOLUTE 2 int direction; Event *ie; repaint = 1; rebuild = 0; direction = BOGUSDIR; ie = inputEvent; switch(event_id(ie)) { case BUT(1) : case BUT(2) : case BUT(3): if (event_is_down(ie)) { /* button going down? */ int leaf; int normalLeafW = leaf_w[SHRINK_NORMAL]; int leafX; int leafY; int lastLeaf = -1; int x = event_x(ie); int y = event_y(ie); /* * Determine which leaf was pointed to & where we will display it */ leaf = x / normalLeafW; if (leaf < 0 || leaf >= Leaves) { leaf = Leaves - 1; } lastLeaf = leaf; if (Leaves == 1) { globalOtherLeaf = leaf; } else { globalOtherLeaf = 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]; } leafX = (x - (leaf * normalLeafW)); leafX = (leafX * shrinkFactor[SHRINK_NORMAL]) / shrinkFactor[SHRINK_LARGE]; leafY = (y * shrinkFactor[SHRINK_NORMAL]) / shrinkFactor[SHRINK_LARGE]; globalLeafX = leafX; globalLeafY = leafY; globalDisplayLeaf = leaf; globalDisplayState = SHRINK_LARGE; displayLeaves(); } else { globalDisplayState = SHRINK_NORMAL; displayLeaves(); } return; 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 (! globalArg) { globalArg = 1; globalSign = 1; globalNumber = 0; } globalNumber = 10*globalNumber + (event_id(ie) - '0'); return; case '-': if (! globalArg) { globalArg = 1; globalSign = -1; globalNumber = 0; repaint = 0; return; } else goto bad; default: goto bad; } if (rebuild && direction != BOGUSDIR) { int newLeft; int newRight; /* * canonicalize the request. globalArg is always > 0, were moving in * some direction. */ if (globalArg == 0 || globalNumber == 0) { globalNumber = 1; } globalNumber = globalNumber * globalSign; if (globalNumber < 0) { if (direction == FOREWARD) { direction = BACKWARD; } else if (direction == BACKWARD){ direction = FOREWARD; } globalNumber = -globalNumber; } /* * Turn pages */ if (direction == BACKWARD) { newLeft = pageOnLeaf[LEAF_LEFT] - globalNumber; } else if (direction == FOREWARD) { newLeft = pageOnLeaf[LEAF_LEFT] + globalNumber; } else { newLeft = globalNumber - 1; /* pages globalNumbered at 0 */ } newLeft = MINFUNC(newLeft, dviTotalPages-1); newLeft = MAXFUNC(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); } else if (newRight == pageOnLeaf[LEAF_LEFT]) { swapLeaf(LEAF_LEFT, LEAF_RIGHT); } if (pageOnLeaf[LEAF_LEFT] != newLeft) { buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL); } if (pageOnLeaf[LEAF_RIGHT] != newRight) { buildLeaf(LEAF_RIGHT, newRight, SHRINK_NORMAL); } } } /* * Only repaint it if we need to */ } displayLeaves(); globalArg = 0; globalNumber = 0; return; bad: globalArg = 0; /* throw away numeric globalArgument */ return; } put_border(x, y, w, h, t) int x, y, w, h, t; { put_rectangle(x, y, w, t, setMode); put_rectangle(x, y, t, h, setMode); put_rectangle(x, y + h - t, w, t, setMode); put_rectangle(x + w - t, y, t, h, setMode); } put_rectangle(x, y, w, h, pix) int x, y, w, h; int pix; { if (buildToPixmap) { pr_rop(pasteUpPixmap[currentShrink][currentLeaf], x,y, w,h, pix, pasteUpPixmap[currentShrink][currentLeaf], 0, 0); } else { pw_write(ptube, x + currentLeaf * leaf_w[currentShrink],y, w,h, pix, ptube, 0, 0); } }