summaryrefslogtreecommitdiff
path: root/dviware/umddvi/previewers/texsun.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi/previewers/texsun.c
Initial commit
Diffstat (limited to 'dviware/umddvi/previewers/texsun.c')
-rw-r--r--dviware/umddvi/previewers/texsun.c1576
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);
+ }
+}
+
+