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