|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 34751 (0x87bf)
Types: TextFile
Names: »texsun.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./DVIware/laser-setters/umd-dvi/previewers/texsun.c«
/*
* 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);
}
}