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/texsun.c |
Initial commit
Diffstat (limited to 'dviware/umddvi/previewers/texsun.c')
-rw-r--r-- | dviware/umddvi/previewers/texsun.c | 1576 |
1 files changed, 1576 insertions, 0 deletions
diff --git a/dviware/umddvi/previewers/texsun.c b/dviware/umddvi/previewers/texsun.c new file mode 100644 index 0000000000..4eaa87e3e6 --- /dev/null +++ b/dviware/umddvi/previewers/texsun.c @@ -0,0 +1,1576 @@ +/* + * 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 <stdio.h> +#include <ctype.h> +#include <suntool/sunview.h> +#include <suntool/canvas.h> +#include <sunwindow/defaults.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sun/fbio.h> +#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 <images/hglass.cursor>; +}; +mpr_static(workingCursorPixrect, 16, 16, 1, workingCursorData); + +short readyCursorData[] = { +#include <images/bullseye.cursor>; +}; +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 <shrink>] [-ls <shrink>] [-dpi <dots>] \n", + ProgName); + fprintf(stderr, " [-l <leaves>] [-rv] [-tm <inches>] [-sm <inches>] 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); + } +} + + |