summaryrefslogtreecommitdiff
path: root/dviware/dvipage
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/dvipage
Initial commit
Diffstat (limited to 'dviware/dvipage')
-rw-r--r--dviware/dvipage/args.c206
-rw-r--r--dviware/dvipage/dvi.h294
-rw-r--r--dviware/dvipage/dvipage.1416
-rw-r--r--dviware/dvipage/dvipage.c2421
-rw-r--r--dviware/dvipage/dvipage.h400
-rw-r--r--dviware/dvipage/findfile.c503
-rw-r--r--dviware/dvipage/fonts.c1335
-rw-r--r--dviware/dvipage/makefile97
-rw-r--r--dviware/dvipage/makefonts24
-rw-r--r--dviware/dvipage/message.c659
-rw-r--r--dviware/dvipage/readme129
-rw-r--r--dviware/dvipage/sample.c1245
-rw-r--r--dviware/dvipage/utils.c134
13 files changed, 7863 insertions, 0 deletions
diff --git a/dviware/dvipage/args.c b/dviware/dvipage/args.c
new file mode 100644
index 0000000000..f6ea461276
--- /dev/null
+++ b/dviware/dvipage/args.c
@@ -0,0 +1,206 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: args.c,v $
+ * Revision 1.1 88/11/28 18:39:09 hunt
+ * Initial revision
+ *
+ * Stripped from dvipage.c 1.4.
+ */
+
+#include <stdio.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include "dvipage.h"
+
+static char * a_arg_ptr = NULL;
+static int a_arg_index = 0;
+static bool a_escape_seen;
+
+char * a_prog_name = "Anonymous";
+
+/*
+ * a_next:
+ * Returns the next flag in the command line,
+ * or A_ARG if it is not a flag,
+ * or A_END if there are no more args.
+ */
+
+char
+a_next(argc, argv)
+int argc;
+char **argv;
+{
+ char opt;
+
+ /*
+ * Checks.
+ */
+ if(argv == NULL || argc < 1)
+ {
+ fprintf(stderr, "a_next: bad arguments\n");
+ exit(2);
+ }
+
+ /*
+ * Get program name on first call.
+ */
+ if(a_arg_index == 0)
+ {
+ a_prog_name = argv[0];
+ a_arg_index = 1;
+ }
+
+ /*
+ * If there is part of the previous word left, then return it.
+ */
+ if(a_arg_ptr && *a_arg_ptr)
+ return *a_arg_ptr++;
+
+ /*
+ * Return A_END after the end of the list.
+ */
+ if(a_arg_index >= argc)
+ return A_END;
+
+ /*
+ * Look at the next word.
+ */
+ a_arg_ptr = argv[a_arg_index++];
+
+ /*
+ * If we have seen the escape "--",
+ * or if the first char of the word * is not a '-',
+ * or if this is an isolated "-",
+ * then return ARG.
+ */
+ if(a_escape_seen || a_arg_ptr[0] != '-' || a_arg_ptr[1] == '\0')
+ return A_ARG;
+
+ /*
+ * Look at the next char.
+ */
+ a_arg_ptr++;
+ opt = *a_arg_ptr++;
+
+ /*
+ * If the next char is '-', then this is the escape.
+ * start over...
+ */
+ if(opt == '-')
+ {
+ a_escape_seen = TRUE;
+ return a_next(argc, argv);
+ }
+
+ /*
+ * Otherwise, return this option.
+ */
+ return opt;
+}
+
+/*
+ * a_arg:
+ * Returns the next argument in the command line,
+ * or NULL if there are no more args.
+ */
+
+char *
+a_arg(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+
+ /*
+ * Checks.
+ */
+ if(argv == NULL || argc < 1)
+ {
+ fprintf(stderr, "a_arg: bad arguments\n");
+ exit(2);
+ }
+
+ /*
+ * Get program name on first call.
+ */
+ if(a_arg_index == 0)
+ {
+ a_prog_name = argv[0];
+ a_arg_index = 1;
+ }
+
+ /*
+ * If there is part of the previous word left, then return it.
+ */
+ if(a_arg_ptr && *a_arg_ptr)
+ {
+ arg = a_arg_ptr;
+ a_arg_ptr = NULL;
+ return arg;
+ }
+
+ /*
+ * Return NULL after the end of the list.
+ */
+ if(a_arg_index >= argc)
+ return NULL;
+
+ /*
+ * Return the next word.
+ */
+ return argv[a_arg_index++];
+}
+
+/*
+ * a_number:
+ * Interpret the next word or part word as a number.
+ */
+
+double
+a_number(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+
+ if((arg = a_arg(argc, argv)) == NULL)
+ return 0.0;
+ else
+ return atof(arg);
+}
+
+/*
+ * a_integer:
+ * Interpret the next word or part word as an integer.
+ */
+
+int
+a_integer(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+
+ if((arg = a_arg(argc, argv)) == NULL)
+ return 0;
+ else
+ return atoi(arg);
+}
diff --git a/dviware/dvipage/dvi.h b/dviware/dvipage/dvi.h
new file mode 100644
index 0000000000..dc38da7e44
--- /dev/null
+++ b/dviware/dvipage/dvi.h
@@ -0,0 +1,294 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * From the dvisun manual page entry:
+ * Mark Senn wrote the early versions of [dvisun] for the
+ * BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
+ * Furuta, James Schaad and Robert Wells improved it. Norm
+ * Hutchinson ported the program to the Sun. Further bug fixes
+ * by Rafael Bracho at Schlumberger.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: dvi.h,v $
+ * Revision 1.2 88/11/28 18:41:42 hunt
+ * Major rewrite for 4.0 and sparc architecture.
+ * Split up into multiple files for easier maintenance.
+ * Reads GF files as well as PXL files now.
+ *
+ * Revision 1.1 88/08/30 09:06:40 hunt
+ * Initial revision
+ *
+ * HISTORY
+ *
+ * 12 April 1988 - Neil Hunt
+ * Version 2.0 released for use.
+ *
+ * Earlier history unavailable.
+ */
+
+#define SETC_000 0
+#define SETC_001 1
+#define SETC_002 2
+#define SETC_003 3
+#define SETC_004 4
+#define SETC_005 5
+#define SETC_006 6
+#define SETC_007 7
+#define SETC_008 8
+#define SETC_009 9
+#define SETC_010 10
+#define SETC_011 11
+#define SETC_012 12
+#define SETC_013 13
+#define SETC_014 14
+#define SETC_015 15
+#define SETC_016 16
+#define SETC_017 17
+#define SETC_018 18
+#define SETC_019 19
+#define SETC_020 20
+#define SETC_021 21
+#define SETC_022 22
+#define SETC_023 23
+#define SETC_024 24
+#define SETC_025 25
+#define SETC_026 26
+#define SETC_027 27
+#define SETC_028 28
+#define SETC_029 29
+#define SETC_030 30
+#define SETC_031 31
+#define SETC_032 32
+#define SETC_033 33
+#define SETC_034 34
+#define SETC_035 35
+#define SETC_036 36
+#define SETC_037 37
+#define SETC_038 38
+#define SETC_039 39
+#define SETC_040 40
+#define SETC_041 41
+#define SETC_042 42
+#define SETC_043 43
+#define SETC_044 44
+#define SETC_045 45
+#define SETC_046 46
+#define SETC_047 47
+#define SETC_048 48
+#define SETC_049 49
+#define SETC_050 50
+#define SETC_051 51
+#define SETC_052 52
+#define SETC_053 53
+#define SETC_054 54
+#define SETC_055 55
+#define SETC_056 56
+#define SETC_057 57
+#define SETC_058 58
+#define SETC_059 59
+#define SETC_060 60
+#define SETC_061 61
+#define SETC_062 62
+#define SETC_063 63
+#define SETC_064 64
+#define SETC_065 65
+#define SETC_066 66
+#define SETC_067 67
+#define SETC_068 68
+#define SETC_069 69
+#define SETC_070 70
+#define SETC_071 71
+#define SETC_072 72
+#define SETC_073 73
+#define SETC_074 74
+#define SETC_075 75
+#define SETC_076 76
+#define SETC_077 77
+#define SETC_078 78
+#define SETC_079 79
+#define SETC_080 80
+#define SETC_081 81
+#define SETC_082 82
+#define SETC_083 83
+#define SETC_084 84
+#define SETC_085 85
+#define SETC_086 86
+#define SETC_087 87
+#define SETC_088 88
+#define SETC_089 89
+#define SETC_090 90
+#define SETC_091 91
+#define SETC_092 92
+#define SETC_093 93
+#define SETC_094 94
+#define SETC_095 95
+#define SETC_096 96
+#define SETC_097 97
+#define SETC_098 98
+#define SETC_099 99
+#define SETC_100 100
+#define SETC_101 101
+#define SETC_102 102
+#define SETC_103 103
+#define SETC_104 104
+#define SETC_105 105
+#define SETC_106 106
+#define SETC_107 107
+#define SETC_108 108
+#define SETC_109 109
+#define SETC_110 110
+#define SETC_111 111
+#define SETC_112 112
+#define SETC_113 113
+#define SETC_114 114
+#define SETC_115 115
+#define SETC_116 116
+#define SETC_117 117
+#define SETC_118 118
+#define SETC_119 119
+#define SETC_120 120
+#define SETC_121 121
+#define SETC_122 122
+#define SETC_123 123
+#define SETC_124 124
+#define SETC_125 125
+#define SETC_126 126
+#define SETC_127 127
+#define SET1 128
+#define SET2 129
+#define SET3 130
+#define SET4 131
+#define SET_RULE 132
+#define PUT1 133
+#define PUT2 134
+#define PUT3 135
+#define PUT4 136
+#define PUT_RULE 137
+#define NOP 138
+#define BOP 139
+#define EOP 140
+#define PUSH 141
+#define POP 142
+#define RIGHT1 143
+#define RIGHT2 144
+#define RIGHT3 145
+#define RIGHT4 146
+#define W0 147
+#define W1 148
+#define W2 149
+#define W3 150
+#define W4 151
+#define X0 152
+#define X1 153
+#define X2 154
+#define X3 155
+#define X4 156
+#define DOWN1 157
+#define DOWN2 158
+#define DOWN3 159
+#define DOWN4 160
+#define Y0 161
+#define Y1 162
+#define Y2 163
+#define Y3 164
+#define Y4 165
+#define Z0 166
+#define Z1 167
+#define Z2 168
+#define Z3 169
+#define Z4 170
+#define FONT_00 171
+#define FONT_01 172
+#define FONT_02 173
+#define FONT_03 174
+#define FONT_04 175
+#define FONT_05 176
+#define FONT_06 177
+#define FONT_07 178
+#define FONT_08 179
+#define FONT_09 180
+#define FONT_10 181
+#define FONT_11 182
+#define FONT_12 183
+#define FONT_13 184
+#define FONT_14 185
+#define FONT_15 186
+#define FONT_16 187
+#define FONT_17 188
+#define FONT_18 189
+#define FONT_19 190
+#define FONT_20 191
+#define FONT_21 192
+#define FONT_22 193
+#define FONT_23 194
+#define FONT_24 195
+#define FONT_25 196
+#define FONT_26 197
+#define FONT_27 198
+#define FONT_28 199
+#define FONT_29 200
+#define FONT_30 201
+#define FONT_31 202
+#define FONT_32 203
+#define FONT_33 204
+#define FONT_34 205
+#define FONT_35 206
+#define FONT_36 207
+#define FONT_37 208
+#define FONT_38 209
+#define FONT_39 210
+#define FONT_40 211
+#define FONT_41 212
+#define FONT_42 213
+#define FONT_43 214
+#define FONT_44 215
+#define FONT_45 216
+#define FONT_46 217
+#define FONT_47 218
+#define FONT_48 219
+#define FONT_49 220
+#define FONT_50 221
+#define FONT_51 222
+#define FONT_52 223
+#define FONT_53 224
+#define FONT_54 225
+#define FONT_55 226
+#define FONT_56 227
+#define FONT_57 228
+#define FONT_58 229
+#define FONT_59 230
+#define FONT_60 231
+#define FONT_61 232
+#define FONT_62 233
+#define FONT_63 234
+#define FNT1 235
+#define FNT2 236
+#define FNT3 237
+#define FNT4 238
+#define XXX1 239
+#define XXX2 240
+#define XXX3 241
+#define XXX4 242
+#define FNT_DEF1 243
+#define FNT_DEF2 244
+#define FNT_DEF3 245
+#define FNT_DEF4 246
+#define PRE 247
+#define POST 248
+#define POST_POST 249
diff --git a/dviware/dvipage/dvipage.1 b/dviware/dvipage/dvipage.1
new file mode 100644
index 0000000000..a05bf4b50d
--- /dev/null
+++ b/dviware/dvipage/dvipage.1
@@ -0,0 +1,416 @@
+.\"
+.\" dvipage: DVI Previewer Program for Suns
+.\"
+.\" This program is based, in part, upon the program dvisun,
+.\" distributed by the UnixTeX group, extensively modified by
+.\" Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+.\" of Schlumberger Technologies, Inc.
+.\"
+.\" From the dvisun manual page entry:
+.\" Mark Senn wrote the early versions of [dvisun] for the
+.\" BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
+.\" Furuta, James Schaad and Robert Wells improved it. Norm
+.\" Hutchinson ported the program to the Sun. Further bug fixes
+.\" by Rafael Bracho at Schlumberger.
+.\"
+.\" Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+.\" Anyone can use this software in any manner they choose,
+.\" including modification and redistribution, provided they make
+.\" no charge for it, and these conditions remain unchanged.
+.\"
+.\" This program is distributed as is, with all faults (if any), and
+.\" without any warranty. No author or distributor accepts responsibility
+.\" to anyone for the consequences of using it, or for whether it serves any
+.\" particular purpose at all, or any other reason.
+.\"
+.\" HISTORY
+.\"
+.\" $Log: dvipage.1,v $
+.\" Revision 1.3 88/12/15 19:02:01 hunt
+.\" Version 3.0 released.
+.\"
+.\" 21 April 1988 - Neil Hunt.
+.\" Fixed a couple of typos.
+.\"
+.\" 12 April 1988 - Neil Hunt.
+.\" Version 2.0 released for use.
+.\"
+.\" Earlier history unavailable.
+.\"
+.TH DVIPAGE 1 "4 February 1988"
+.SH NAME
+dvipage \- display DVI files from TeX and LaTeX.
+.SH SYNOPSIS
+.B dvipage
+.RB "[\|" \-H "\|]"
+.RB "[\|" \-v
+.IR mode "\|]"
+.RB "[\|" \-m "\|]"
+.RB "[\|" \-p "\|]"
+.RB "[\|" \-q "\|]"
+.RB "[\|" \-f "\|]"
+.RB "[\|" \-r
+.IR res "\|]"
+.RB "[\|" \-s
+.IR sample "\|]"
+.RB "[\|" \-x
+.IR x "\|]"
+.RB "[\|" \-y
+.IR y "\|]"
+.RB "[\|" \-X
+.IR X "\|]"
+.RB "[\|" \-Y
+.IR Y "\|]"
+.RB "[\|" \-w
+.IR w "\|]"
+.RB "[\|" \-h
+.IR h "\|]"
+.RB "[\|" \-W... "\|]"
+.RI "[\|" dvifile "[\|" .dvi "\|]\|]"
+.SH DESCRIPTION
+.IX dvipage "" "\fLdvipage\fR \(em display DVI files from TeX and LaTeX."
+.I Dvipage
+displays DVI files produced by TeX or LaTeX on a SunView window.
+A new window is created, and the first page of the document is displayed.
+The image of the page can be scrolled around in the window by
+grabbing it with the middle mouse button, or by the keystrokes
+.I "l r u d" (left, right, up, down).
+The
+.I space
+key or the keys
+.I RET
+.I n
+or
+.I +
+advance the display to the next page,
+while the
+.I LF
+.I p
+and
+.I -
+keys go back to the previous page.
+The right mouse button invokes a menu with options to
+move forward or backward one page, to go to the first or last page
+in the document,
+to reopen the same, or a different, DVI file,
+to print either one page, or the whole document,
+or to exit.
+Various other key and menu options are described below.
+.PP
+On a monochrome display,
+.I dvipage
+uses a set of low resolution fonts, (typically 118 dots per inch),
+to display the text.
+When a colour display is available,
+high resolution fonts are used, (typically 300 dpi),
+the page is rendered onto an internal ``page'',
+and image processing functions are invoked to
+low pass filter the data and sample it down to a lower resolution.
+The sampled data has substituted grey scale resolution for
+spatial resolution, and retains much better readability than
+simple binary fonts at the same scale of display.
+On a colour display, four levels of sampling are possible,
+with linear scales of 1, 2, 3 and 4.
+The default is a sampling factor of 4.
+(Sampling factor 3 actually obtains three samples for each eight
+pixels horizontally and nine rows vertically, thus changing
+the aspect ratio slightly.)
+.PP
+When a non unity sampling factor is used (the default on a colour display),
+a magnifier is available to inspect a local region of the high resolution
+unsampled data, by pressing the left mouse button.
+The magnifier my be dragged around the page by moving the mouse with the
+button down.
+.PP
+Dvipage understands both the old format PXL font files,
+the new GF packed font files, and the most efficient PK font files.
+It searches for font files in a list of standard places
+(by default: ``/usr/local/lib/tex/fonts/pkb:/usr/local/lib/tex/fonts/pk'')
+accepting either PK files, GF files or PXL files, whichever is found.
+If the exact font specified is not found,
+dvipage searches all the font directories
+for the closest font match.
+A warning is issued indicating the missing font
+and its substitution.
+The list of standard places for finding font files
+can be overridden by the -p option (see below),
+or by an environment variable
+.B FONT_PATH.
+.SH OPTIONS
+.PP
+.TP
+.B \-H
+Prints a simple help message.
+.TP
+.BI \-v " mode"
+Sets a verboseness level for debugging (wizards only).
+.TP
+.B \-m
+Makes
+.B dvipage
+think that it is running on a monochrome machine even if it finds
+a colour display.
+.TP
+.BI \-p " font-area"
+Overrides the list of standard places where
+.B dvipage
+looks for font files.
+The argument is a colon separated
+list of directories which contain either font files,
+or subdirectories grouping fonts by family.
+Either PXL, PK, or GF type files can be used.
+If the environment variable
+.B FONT_AREA,
+is set, it also specifies a colon separated
+list of filenames which override the
+default font areas.
+.TP
+.BI \-P " flag"
+If
+.I flag
+is 0, use of PXL files is suppressed.
+Default is non zero, enabling the use of PXL files.
+.TP
+.BI \-K " flag"
+If
+.I flag
+is 0, use of PK files is suppressed.
+Default is non zero, enabling the use of PK files.
+.TP
+.BI \-G " flag"
+If
+.I flag
+is 0, use of GF files is suppressed.
+Default is non zero, enabling the use of GF files.
+.TP
+.B \-l
+Normally
+.B dvipage
+seeks to the end of the DVI file and reads the cached font data located
+there.
+The
+.B \-l
+option suppresses this behaviour, causing the font data to be obtained
+from the inline locations.
+This is much slower, especially when skipping pages.
+.TP
+.B \-q
+Certain errors detected by
+.B dvipage
+are displayed in a pop up message window.
+The
+.B \-q
+flag suppresses the generation of these windows.
+.TP
+.B \-f
+TeX has a concept of a rendering window with margins one inch
+inside the edges of the paper;
+the DVI coordinate system is relative to this frame.
+Although it is possible (and even normal) to print outside
+the boundaries of this frame, sometimes it is useful
+to see its location on the page.
+The
+.B \-f
+option causes the rendering frame to be shown on the page display.
+.TP
+.BI \-r " res"
+Causes
+.B dvipage
+to use fonts at a resolution of
+.I res
+dots per inch.
+If this is not a suitable size, it will generate many
+error messages as it fails to find font files at the specified
+resolution.
+Common sizes are 118 and 300 dots per inch.
+If this option is ommitted,
+.B dvipage
+will select the either the high resolution fonts (on a colour machine)
+or the low resolution fonts (on a monochrome machine).
+.TP
+.BI \-s " sample"
+Causes
+.B dvipage
+to use a sampling factor of
+.I sample.
+If this is not one of (1, 2, 3, or 4) a blank page will result.
+This option is ignored if running on a monochrome machine.
+.TP
+.BI \-x " x " \-y " y"
+The position of the top left hand corner of the page
+from the top left hand corner of the display window,
+measured in inches,
+is set to be
+.I "(x, y)"
+at the ``home'' position (the position at which each new page is displayed
+before moving it around with the mouse).
+.TP
+.BI \-X " X " \-Y " Y"
+Normally the origin of the rendering window is set to be one inch
+from the corner of the page.
+This can be overriden by this option to match the actual behaviour of
+your local printer.
+.TP
+.BI \-w " w " \-h " h"
+Sets the width and height of the paper on which the image is rendered;
+the default is 8 by 11 \(12 inches. Useful for viewing legal size or A4 size
+documents.
+.SH COMMANDS
+.PP
+The following keystrokes typed to the display window execute
+various commands.
+Some of these can be performed from a menu option.
+Many of the commands can be preceeded by a number,
+indicated by
+.B #
+in the description below.
+.TP
+.B MS_MIDDLE
+The middle mouse button drags the page beneath the window to pan or scroll.
+.TP
+.B MS_LEFT
+The left mouse button invokes a magnifier on the page near the mouse,
+when running in sampled mode on a colour display.
+.TP
+.B MS_RIGHT
+The right mouse button invokes a menu, which contains items for most
+of the other commands listed below.
+.TP
+.B space, RET, n, or +
+Advance to the next page in the document.
+.TP
+.B NL, p, or -
+Go back to the previous page.
+.TP
+.BR _ " (underscore)"
+Go to the first page in the document.
+.TP
+.B # g
+Go to page number
+.B #.
+(If
+.B #
+is ommitted, go to the last page in the document.)
+.TP
+.B # G
+Go to sheet number
+.B #.
+(If
+.B #
+is ommitted, go to the last page in the document.)
+.TP
+.B h
+Return the page to the home position.
+.TP
+.B l, r, u or d
+Move the page left, right, up or down in the window by a small increment.
+.TP
+.B m
+Mark the current page position as the new home page position for subsequent
+new pages and
+.B h
+commands.
+.TP
+.B S
+Pops up a window in which a sampling factor can be typed.
+This should be 1, 2, 3 or 4.
+Close the window by mousing the
+.B Abort
+button or the
+.B OK
+button,
+or by typing
+.B "^C"
+(for abort)
+or
+.B "ESC"
+(for OK).
+.TP
+.B # s
+Set a scaling factor of
+.B #.
+.TP
+.B # R
+Reopen the current DVI file on page
+.B #.
+(If
+.B #
+is ommitted, reopen on the current page.)
+.TP
+.B P
+Print the DVI file on the default printer.
+This requires site dependent printer commands to have
+been specified when
+.B dvipage
+was installed. This is not implemented at DL.
+.TP
+.B "^P"
+Attempts to print the current page on the default printer.
+This requires site dependent printer commands to have
+been specified when
+.B dvipage
+was installed. This is not implemented at DL.
+
+.TP
+.B w
+Toggles the display of the rendering frame window.
+.B # x
+Sets the width of the magnifier (in pixels).
+.B # y
+Sets the height of the magnifier (in pixels).
+.B # b
+Sets the width of the border drawn around the magnifier.
+Use
+.B 0 b
+to have no border. displayed.
+.TP
+.B # v
+Sets verbose mode
+.B #.
+.TP
+.B Q
+.B dvipage
+quits.
+.SH SEE ALSO
+dvips(1)
+.SH BUGS
+.PP
+The command to print the current page is rather
+crude. It needs special magic at installation time
+to make it work.
+.B Dvipage
+does not change directories before printing,
+so relative pathnames for included PostScript files (for example)
+may not work if dvipage is invoked in one directory,
+and opens a document in a different directory.
+.PP
+.B Dvipage
+checks the modification time of the dvi file before tackling each page,
+and refuses to proceed if you have reformatted the document, until you
+instruct it to reopen the file.
+However, if you reformat \fIwhile\fP it is in the process of reading a page,
+it will probably crash messily.
+.PP
+Dvipage does not preview PostScript (or other) files included in a document.
+A blank space is left where the included data would appear.
+.SH AUTHOR
+.PP
+The original idea for this program came from
+.B dvisun
+developed by Mark Senn, Stephan Bechtolsheim, Bob Brown,
+Richard Furuta, James Schaad, Robert Wells, and Norm Hutchinson,
+with some bug fixes by Rafael Bracho at Schlumberger;
+and from the program
+.B suntroff
+developed by Malcolm Slaney at Schlumberger.
+.PP
+.B Dvipage
+was put together by
+Neil Hunt at Schlumberger Palo Alto Research,
+.B hunt@spar.slb.com,
+using code borrowed from
+.B dvisun
+and greatly extended.
+In particular the filtering and sampling concept
+and the fast code to implement it, and the magnifier,
+came from Neil Hunt.
diff --git a/dviware/dvipage/dvipage.c b/dviware/dvipage/dvipage.c
new file mode 100644
index 0000000000..272118cf59
--- /dev/null
+++ b/dviware/dvipage/dvipage.c
@@ -0,0 +1,2421 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * From the dvisun manual page entry:
+ * Mark Senn wrote the early versions of [dvisun] for the
+ * BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
+ * Furuta, James Schaad and Robert Wells improved it. Norm
+ * Hutchinson ported the program to the Sun. Further bug fixes
+ * by Rafael Bracho at Schlumberger.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: dvipage.c,v $
+ * Revision 1.6 88/12/15 09:08:03 hunt
+ * Added iteration to gobble inputs in panning and magnifier.
+ *
+ * Revision 1.5 88/11/28 18:39:21 hunt
+ * Major rewrite for 4.0 and sparc architecture.
+ * Split up into multiple files for easier maintenance.
+ * Reads GF files as well as PXL files now.
+ *
+ * Revision 1.4 88/11/26 11:10:53 hunt
+ * Used varargs with *_prompt() functions for correct behaviour on a sun4.
+ *
+ * Revision 1.3 88/08/30 13:04:13 hunt
+ * Changed default cmap for darker looking letters.
+ *
+ * Revision 1.2 88/08/30 09:26:29 hunt
+ * Fixed problem pointed out by pell@rainier.UUCP
+ * (pell@rainier.se, enea!rainier!pell@uunet.UU.NET)
+ * so that opened files are closed on exec, and do not clutter up
+ * space in print spoolers which may be invoked
+ * to print the document.
+ *
+ * Revision 1.1 88/08/30 09:05:19 hunt
+ * Initial revision
+ *
+ * HISTORY
+ *
+ * 12 April 1988 - Neil Hunt
+ * Version 2.0 released for use.
+ *
+ * 11 April 1988 - Neil Hunt
+ * Applied fixes supplied by Rafael Bracho (Schlumberger Austin)
+ * for operation on Sun-4 workstations.
+ *
+ * Earlier history unavailable.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <varargs.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <sys/stat.h>
+#include <suntool/sunview.h>
+#include <suntool/canvas.h>
+#include <suntool/panel.h>
+#include <suntool/icon.h>
+#include "dvipage.h"
+#include "dvi.h"
+
+#define GOBBLE_PAN
+#define GOBBLE_MAGNIFY
+
+/*
+ * Forward functions.
+ * =================
+ */
+
+forward int main();
+
+forward Notify_value page_paint();
+forward Notify_value page_event();
+forward int page_menu();
+forward void page_magnify();
+forward void page_pan();
+forward bool goto_sheet();
+forward bool goto_page();
+
+forward bool init_dvi_file();
+forward void close_dvi_file();
+forward bool check_dvi_file();
+
+forward bool read_postamble();
+forward bool find_postamble_ptr();
+
+forward bool process_page();
+
+forward void set_font_num();
+forward void set_char();
+forward void set_rule();
+forward void move_down();
+forward void move_over();
+
+forward char * a_prog_name;
+forward char a_next();
+forward char * a_arg();
+forward double a_number();
+forward int a_integer();
+
+/*
+ * Internal data structures.
+ * ========================
+ */
+
+struct stack_entry /* stack entry */
+{
+ int h, v, w, x, y, z; /* what's on stack */
+};
+
+/*
+ * Globals.
+ * =======
+ */
+
+int hconv, vconv; /* converts DVI units to pixels */
+int num; /* numerator specified in preamble */
+int den; /* denominator specified in preamble */
+int mag; /* magnification specified in preamble */
+
+struct font_entry *fontptr; /* font_entry pointer */
+struct font_entry *hfontptr=NULL;/* font_entry pointer */
+
+double page_w = PAGE_WIDTH; /* page width (inches) */
+double page_h = PAGE_HEIGHT; /* page width (inches) */
+
+int h; /* current horizontal position */
+int hh; /* current horizontal position in pixels */
+int v; /* current vertical position */
+int vv; /* current vertical position in pixels */
+
+bool pre_load = TRUE; /* preload the font descriptions? */
+bool silent = FALSE; /* suppress messages */
+bool show_page_frame = FALSE; /* show page window */
+
+long postambleptr; /* Pointer to the postamble */
+
+char *font_path; /* Font path name for search */
+bool use_gf = USE_GF; /* Enable the use of GF fonts. */
+bool use_pxl = USE_PXL; /* Enable the use of PXL fonts. */
+bool use_pk = USE_PK; /* Enable the use of PK fonts. */
+
+FILE *dvifp = NULL; /* File pointer */
+
+struct stat stat_buf; /* For checking file changes. */
+time_t mtime = 0;
+
+char label[STRSIZE];
+
+char pathname[STRSIZE] = ""; /* Complete path */
+char directory[STRSIZE] = ""; /* Directory */
+char filename[STRSIZE] = ""; /* File name */
+char print_spooler[STRSIZE] = PRINT_SPOOLER; /* Print commands. */
+char print_page_spooler[STRSIZE] = PRINT_PAGE_SPOOLER;
+
+int last_sheet = 0; /* Sheet number of last page in file */
+int file_sheet = 1; /* Position of file pointer */
+int disp_sheet = 0; /* Current displayed page */
+int disp_page = 0; /* Real Page number */
+int sheet_page[MAX_SHEETS]; /* Page number of each sheet. */
+long sheet_table[MAX_SHEETS]; /* pointers to start of each page in file */
+int last_known_sheet = 0; /* Points to table at next unread sheet */
+
+int resolution = 0; /* Assumed screen resolution for rendering */
+int sampling = 0; /* Sample down sampling factor */
+bool mono; /* Monochrome screen */
+
+Frame disp_frame; /* Frame for display window. */
+Canvas disp_canvas; /* Canvas for display window. */
+
+struct mem_pixrect page_mpr; /* Page bitmap. */
+struct pixrect *page_pr;
+struct mem_pixrect sample_mpr; /* Sampled/filtered bitmap. */
+struct pixrect *sample_pr;
+
+int origin_x; /* Nominal origin of the dvi on the page */
+int origin_y; /* Nominal origin of the dvi on the page */
+
+int offset_x; /* Offsets of page in window. */
+int offset_y; /* Offsets of page in window. */
+
+int start_x; /* Starting position of page in the window */
+int start_y; /* Starting position of page in the window */
+
+int verbose; /* Flags for debugging. */
+
+int mag_size_x = DEFAULT_MAG_SIZE_X; /* Magnifier parameters. */
+int mag_size_y = DEFAULT_MAG_SIZE_Y;
+int mag_border = DEFAULT_MAG_BORDER;
+
+forward uchar cmap_red[];
+forward uchar cmap_green[];
+forward uchar cmap_blue[];
+
+short icon_image[] =
+{
+/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
+ */
+ 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x00C0,0x0001,0x8000,0x0000,0x0338,0x0001,
+ 0x8000,0x0000,0x0447,0x0001,0x8000,0x0000,0x1911,0xE001,
+ 0x8000,0x0000,0x2888,0x9E01,0x8000,0x0000,0xC222,0x23C1,
+ 0x8000,0x0001,0x4444,0x4479,0x8000,0x0007,0x1111,0x1117,
+ 0x8000,0x0008,0x8888,0x8889,0x8000,0x0032,0x2222,0x2223,
+ 0x8000,0x0044,0x4444,0x4445,0x8000,0x0191,0x1111,0x1111,
+ 0x8000,0x0288,0x8888,0x888B,0x8000,0x0C22,0x2222,0x2225,
+ 0x8000,0x1444,0x4444,0x4447,0x8000,0x6111,0x1111,0x1119,
+ 0x8000,0xC888,0x8888,0x889B,0x8000,0xB222,0x2222,0x2235,
+ 0x8000,0xCE44,0x4444,0x446B,0x8000,0x91D1,0x1111,0x11D5,
+ 0x8000,0x88B8,0x8888,0x88AB,0x8000,0xAC2E,0x2222,0x2355,
+ 0x8000,0xC345,0xC444,0x46AB,0x8000,0x9CD1,0x3111,0x1555,
+ 0x8000,0xB338,0x8E88,0x8AA5,0x8000,0xE0C6,0x23E2,0x3559,
+ 0x8000,0xC039,0x8474,0x56B1,0x8000,0xC006,0x611F,0x2D41,
+ 0x8000,0x9001,0x9C89,0xDEA1,0x8001,0x0C00,0x6322,0xFD41,
+ 0x8002,0x43E0,0x1CC4,0xBE81,0x8004,0x2C18,0x0331,0xFD01,
+ 0x8008,0x3606,0x00C8,0xBB01,0x8031,0xC781,0x0032,0xF601,
+ 0x8040,0x4CC1,0x0014,0xAC01,0x818C,0x9840,0xC021,0xD801,
+ 0x8602,0xB208,0xB048,0xA801,0x9861,0x6788,0x4CC2,0xD001,
+ 0xB011,0xCCD9,0xC0C4,0xA001,0xA30D,0x1817,0x60B1,0xC001,
+ 0x9883,0x3E1C,0x590E,0xC001,0x8463,0x6270,0x4101,0x8001,
+ 0x821F,0xC1D0,0xC100,0x0001,0x813F,0xB310,0xB200,0x0001,
+ 0x81FC,0x5831,0x0200,0x0001,0x87F8,0x4021,0x0400,0x0001,
+ 0x9F8C,0x3006,0xC400,0x0001,0x9E07,0x0C18,0x0800,0x0001,
+ 0x8C00,0x83E8,0x1000,0x0001,0x8000,0x6106,0x2000,0x0001,
+ 0x8000,0x18C0,0x4000,0x0001,0x8000,0x0430,0x8000,0x0001,
+ 0x8000,0x0309,0x0000,0x0001,0x8000,0x0081,0x0000,0x0001,
+ 0x8000,0x0062,0x0000,0x0001,0x8000,0x0014,0x0000,0x0001,
+ 0x8000,0x0008,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
+};
+
+DEFINE_ICON_FROM_IMAGE(icon, icon_image);
+
+short hand[] =
+{
+ 0x0C00,0x1200,0x1200,0x1380,0x1240,0x7270,0x9248,0x924E,
+ 0x9249,0x9249,0x9009,0x8001,0x4002,0x4002,0x2004,0x2004
+};
+mpr_static(hand_pr, 16, 16, 1, hand);
+Cursor hand_cursor;
+
+/*
+ * Functions.
+ * =========
+ */
+
+/*
+ * main:
+ * Interpret args, open windows, loop forever.
+ */
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int f;
+ char opt;
+ char *slash;
+ char *extension;
+ Pixwin *pw;
+ bool fake_mono;
+ char *printer;
+ double set_origin_x;
+ double set_origin_y;
+ double set_start_x;
+ double set_start_y;
+
+ /*
+ * local initialisations.
+ */
+ fake_mono = FALSE;
+ set_origin_x = 0.0;
+ set_origin_y = 0.0;
+ set_start_x = 0.0;
+ set_start_y = 0.0;
+
+ /*
+ * Customise this part for your local printer environment.
+ * ======================================================
+ */
+#ifdef SPAR_HACKS
+
+ /*
+ * Set local printer hacks.
+ */
+ printer = getenv("PRINTER");
+ if(printer && strncmp(printer, "lw", 2) == 0)
+ {
+ sprintf(print_spooler,
+ "dvips -P%s %%s >/dev/null 2>/dev/null",
+ printer);
+ sprintf(print_page_spooler,
+ "dvips -P%s -f %%d -t %%d %%s >/dev/null 2>/dev/null",
+ printer);
+ }
+ else if(printer && strncmp(printer, "im", 2) == 0)
+ {
+ sprintf(print_spooler,
+ "dviimp -P%s %%s >/dev/null 2>/dev/null",
+ printer);
+ sprintf(print_page_spooler,
+ "dviimp -P%s -S %%d -E %%d %%s >/dev/null 2>/dev/null",
+ printer);
+ }
+ else
+ {
+ fprintf(stderr, "PRINTER environment not recognised:\n");
+ fprintf(stderr, " using `%s' to print files\n",
+ print_spooler);
+ fprintf(stderr, " using `%s' to print pages\n",
+ print_page_spooler);
+ }
+
+ if(verbose & DEBUG_PRINTER)
+ {
+ fprintf(stderr, "Using `%s' to print files\n",
+ print_spooler);
+ fprintf(stderr, "Using `%s' to print pages\n",
+ print_page_spooler);
+ }
+
+#endif SPAR_HACKS
+
+ /*
+ * Find font path environment.
+ */
+ if((font_path = getenv(FONT_PATH)) == NULL)
+ font_path = FONT_AREA;
+
+ /*
+ * Get cursor.
+ */
+ hand_cursor = cursor_create(
+ CURSOR_IMAGE, &hand_pr,
+ CURSOR_XHOT, 5,
+ CURSOR_YHOT, 0,
+ CURSOR_OP, PIX_SRC ^ PIX_DST,
+ 0);
+
+ /*
+ * Create a disp_frame.
+ */
+ disp_frame = window_create(0, FRAME,
+ WIN_X, 300,
+ WIN_Y, 50,
+ WIN_WIDTH,
+ (int)(page_w * DEFAULT_COLOUR_RES /
+ DEFAULT_COLOUR_SAMPLING) + 10,
+ WIN_HEIGHT,
+ (int)(page_h * DEFAULT_COLOUR_RES /
+ DEFAULT_COLOUR_SAMPLING) + 20,
+ FRAME_ARGC_PTR_ARGV, &argc, argv,
+ FRAME_LABEL, DVIPAGE_LABEL,
+ FRAME_ICON, &icon,
+ 0);
+
+ /*
+ * Create the disp_canvas.
+ */
+ disp_canvas = window_create(disp_frame, CANVAS,
+ CANVAS_RETAINED, FALSE,
+ CANVAS_AUTO_CLEAR, FALSE,
+ CANVAS_FIXED_IMAGE, TRUE,
+ WIN_CURSOR, hand_cursor,
+ WIN_CONSUME_PICK_EVENTS,
+ WIN_NO_EVENTS,
+ LOC_DRAG,
+ WIN_MOUSE_BUTTONS,
+ LOC_WINENTER, /* Otherwise misses first event */
+ LOC_WINEXIT,
+ 0,
+ WIN_CONSUME_KBD_EVENTS,
+ WIN_NO_EVENTS,
+ WIN_ASCII_EVENTS,
+ WIN_LEFT_KEYS, /* For Expose, Hide, Close etc. */
+ KBD_USE, /* Otherwise click to type doesn't work */
+ KBD_DONE,
+ 0,
+ CANVAS_REPAINT_PROC, page_paint,
+ WIN_EVENT_PROC, page_event,
+ WIN_WIDTH, WIN_EXTEND_TO_EDGE,
+ WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
+ 0);
+
+ /*
+ * Interpret args.
+ */
+ f = 0;
+ while((opt = a_next(argc, argv)) != A_END)
+ {
+ switch(opt)
+ {
+ default:
+ fprintf(stderr, "%s: illegal flag -%c\n",
+ a_prog_name, opt);
+ /* FALLTHROUGH */
+ case 'H':
+ fprintf(stderr,
+ "Usage: %s \\\n", a_prog_name);
+ fprintf(stderr,
+ " [-v mode] # Verbose mode (for debugging) \\\n");
+ fprintf(stderr,
+ " [-m] # Force monochrome mode \\\n");
+ fprintf(stderr,
+ " [-p font-file-path] # List of font directories \\\n");
+ fprintf(stderr,
+ " [-P flag] # Enable or disable the use of PXL files \\\n");
+ fprintf(stderr,
+ " [-K flag] # Enable or disable the use of PK files \\\n");
+ fprintf(stderr,
+ " [-G flag] # Enable or disable the use of GF files \\\n");
+ fprintf(stderr,
+ " [-l] # Don't preload font data \\\n");
+ fprintf(stderr,
+ " [-q] # Quiet: no warning messages \\\n");
+ fprintf(stderr,
+ " [-f] # Show rendering frame on page \\\n");
+ fprintf(stderr,
+ " [-r res] # Use `res' dpi fonts \\\n");
+ fprintf(stderr,
+ " [-s sample] # Reduce by factor of `sample' \\\n");
+ fprintf(stderr,
+ " [-x x] [-y y] # Initial pos of sheet in inches \\\n");
+ fprintf(stderr,
+ " [-X ox] [-Y oy] # Pos of (0, 0) on page in inches \\\n");
+ fprintf(stderr,
+ " [-w width] [-h height] # Total size of page in inches \\\n");
+ fprintf(stderr,
+ " [dvifile[.dvi]]\n");
+ exit(1);
+
+ case 'v':
+ verbose = a_integer(argc, argv);
+ break;
+
+ case 'm':
+ fake_mono = TRUE;
+ break;
+
+ case 'p':
+ font_path = a_arg(argc, argv);
+ break;
+
+ case 'P':
+ use_pxl = a_integer(argc, argv);
+ break;
+
+ case 'K':
+ use_pk = a_integer(argc, argv);
+ break;
+
+ case 'G':
+ use_gf = a_integer(argc, argv);
+ break;
+
+ case 'l':
+ pre_load = ! pre_load;
+ break;
+
+ case 'q':
+ silent = ! silent;
+ break;
+
+ case 'f':
+ show_page_frame = ! show_page_frame;
+ break;
+
+ case 'r':
+ resolution = a_integer(argc, argv);
+ break;
+
+ case 's':
+ sampling = a_integer(argc, argv);
+ break;
+
+ case 'x':
+ set_start_x = a_number(argc, argv);
+ break;
+
+ case 'y':
+ set_start_y = a_number(argc, argv);
+ break;
+
+ case 'X':
+ set_origin_x = a_number(argc, argv);
+ break;
+
+ case 'Y':
+ set_origin_y = a_number(argc, argv);
+ break;
+
+ case 'w':
+ page_w = a_number(argc, argv);
+ break;
+
+ case 'h':
+ page_h = a_number(argc, argv);
+ break;
+
+ case A_ARG:
+ switch(f++)
+ {
+ case 0:
+ /*
+ * Get the whole pathname.
+ */
+ strcpy(pathname, a_arg(argc, argv));
+
+ /*
+ * Get the filename and directory
+ */
+ strcpy(directory, pathname);
+ if((slash = rindex(directory, '/')) != NULL)
+ {
+ strcpy(filename, slash+1);
+ *++slash = '\0';
+ }
+ else
+ {
+ directory[0] = '\0';
+ strcpy(filename, pathname);
+ }
+
+ /*
+ * If the filename has no extension, or if it
+ * has an extension and it is not '.dvi' then
+ * cat .dvi onto the filename.
+ */
+ if((extension = rindex(pathname, '.')) == NULL ||
+ strcmp(extension, ".dvi") != 0)
+ strcat(pathname, ".dvi");
+
+ break;
+
+ default:
+ fprintf(stderr,
+ "%s: too many dvi files\n", a_prog_name);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ pw = canvas_pixwin(disp_canvas);
+
+ /*
+ * Now that we know whether we are on a colour machine or a monochrome,
+ * we can set the defaults for the resolution and sampling, unless
+ * they have already been set from the args.
+ */
+ if(fake_mono || (pw->pw_pixrect->pr_depth == 1))
+ {
+ /*
+ * Monochrome
+ */
+ mono = TRUE;
+
+ if(resolution == 0)
+ resolution = DEFAULT_MONO_RES;
+ if(sampling == 0)
+ sampling = DEFAULT_MONO_SAMPLING;
+ }
+ else
+ {
+ /*
+ * Colour
+ */
+ mono = FALSE;
+
+ if(resolution == 0)
+ resolution = DEFAULT_COLOUR_RES;
+ if(sampling == 0)
+ sampling = DEFAULT_COLOUR_SAMPLING;
+
+ /*
+ * Compute and set a colour map
+ */
+ make_cmap();
+ pw_setcmsname(pw, "dvipage-greys");
+ pw_putcolormap(pw, 0, 64, cmap_red, cmap_green, cmap_blue);
+ }
+
+ /*
+ * Now that we know the resolution and sampling, we can set
+ * the margin and origin properly.
+ */
+ if(set_origin_x != 0.0)
+ origin_x = (int)(set_origin_x * resolution);
+ else
+ origin_x = (int)(DEFAULT_ORIGIN_X * resolution);
+
+ if(set_origin_y != 0.0)
+ origin_y = (int)(set_origin_y * resolution);
+ else
+ origin_y = (int)(DEFAULT_ORIGIN_Y * resolution);
+
+ if(set_start_x != 0.0)
+ start_x = (int)(set_start_x * resolution);
+ else
+ start_x = (int)(DEFAULT_START_X * resolution);
+
+ if(set_start_y != 0.0)
+ start_y = (int)(set_start_y * resolution);
+ else
+ start_y = (int)(DEFAULT_START_Y * resolution);
+
+ /*
+ * Insert the window into the heap now, so that if a message is
+ * generated by the init_dvi_file below, it is displayed after the
+ * window, and is therefore on top of it. If we display the window
+ * after doing the initialisation of the dvi file, it would obscure
+ * any error messages which might have been generated.
+ */
+ window_set(disp_frame,
+ WIN_SHOW, TRUE,
+ 0);
+
+ /*
+ * If we don't run the notifier at this time, the window will
+ * not be painted, and the effect will be a gross area of the
+ * screen which is not painted, through which the previous windows
+ * are still visible.
+ */
+ notify_dispatch();
+
+ /*
+ * If there was a filename specified, then open it
+ * and prepare the first page.
+ */
+ if(f >= 1)
+ {
+ /*
+ * Init the file.
+ */
+ if(init_dvi_file())
+ {
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(disp_canvas, pw, 0);
+ }
+ }
+ else
+ getwd(directory);
+
+ /*
+ * Loop forever in the notifier.
+ */
+ notify_start();
+}
+
+/*
+ * Window Functions.
+ * ================
+ */
+
+/*
+ * page_paint:
+ * Called whenever the window is to be painted.
+ * Just maps the sampled pixrect into the screen at the appropriate
+ * offset position.
+ */
+
+Notify_value
+page_paint(canvas, pw, area)
+Canvas canvas;
+Pixwin *pw;
+Rectlist *area;
+{
+ if(sample_pr == NULL)
+ {
+ pw_rop(pw, 0, 0,
+ (int)window_get(canvas, WIN_WIDTH),
+ (int)window_get(canvas, WIN_HEIGHT),
+ PIX_CLR, NULL, 0, 0);
+
+ sprintf(label, "%s: No File", DVIPAGE_LABEL);
+ window_set(disp_frame,
+ FRAME_LABEL, label,
+ 0);
+ }
+ else
+ {
+ pw_cover(pw, 0, 0,
+ (int)window_get(canvas, WIN_WIDTH),
+ (int)window_get(canvas, WIN_HEIGHT),
+ PIX_SRC, sample_pr, -offset_x, -offset_y);
+
+ sprintf(label, "%s: File \"%s\" %s %d",
+ DVIPAGE_LABEL, filename,
+ (last_sheet && disp_sheet >= last_sheet-1)?
+ "Last page" : "Page",
+ disp_page);
+ window_set(disp_frame,
+ FRAME_LABEL, label,
+ 0);
+ }
+}
+
+/*
+ * page_event:
+ * Called whenever an input event arrives at the window.
+ * Controls panning of the page, turning to the next page,
+ * and reloading a new file.
+ */
+
+Notify_value
+page_event(canvas, event, arg)
+Window canvas;
+Event *event;
+caddr_t arg;
+{
+ Pixwin *pw;
+ int e;
+ int pp;
+ bool page_or_sheet;
+ static int num = 0;
+ static bool valid_num = FALSE;
+ bool keep_num;
+ char *extension;
+ char command[STRSIZE];
+ double x, y;
+
+ if(event_is_up(event))
+ return;
+
+ pw = canvas_pixwin(canvas);
+
+ keep_num = FALSE;
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "page_event: num = %d @ %d\n", num, valid_num);
+
+ /*
+ * If there is a call for a menu, then translate that into
+ * a command character.
+ */
+ if((e = event_id(event)) == MS_RIGHT)
+ if((e = page_menu(canvas, pw, event)) == 0)
+ return;
+
+ switch(e)
+ {
+ case MS_LEFT:
+ page_magnify(canvas, pw, event);
+ break;
+
+ case MS_MIDDLE:
+ page_pan(canvas, pw, event);
+ break;
+
+ default:
+ if(e >= '0' && e <= '9')
+ num = num * 10 + e - '0';
+ else if(e == DEL || e == Control('H'))
+ num = num / 10;
+ else
+ break;
+
+ keep_num = TRUE;
+ valid_num = TRUE;
+
+ break;
+
+ case '\r': /* Next page */
+ case 'n':
+ case ' ':
+ case '+':
+ if(! valid_num)
+ num = 1;
+ if(! goto_sheet(disp_sheet + num))
+ break;
+
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+
+ break;
+
+ case '\n': /* Previous page */
+ case 'p':
+ case '-':
+ if(! valid_num)
+ num = 1;
+ if(! goto_sheet(disp_sheet - num))
+ break;
+
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+
+ break;
+
+ case '_':
+ num = 1;
+ valid_num = TRUE;
+ /* FALLTHROUGH */
+
+ case 'G':
+ if(! valid_num)
+ num = LAST_PAGE;
+
+ if(! goto_sheet(num))
+ break;
+
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+
+ break;
+
+ case 'g':
+ if(! valid_num)
+ num = LAST_PAGE;
+
+ if(! goto_page(num))
+ break;
+
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+
+ break;
+
+ case 'h': /* Home page */
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'l': /* Left page */
+ offset_x -= 200;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'r': /* Right page */
+ offset_x += 200;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'u': /* Up page */
+ offset_y -= 300;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'd': /* Down page */
+ offset_y += 300;
+ page_paint(canvas, pw, 0);
+ break;
+
+
+ case 'm': /* Mark margins */
+ start_x = offset_x * sampling;
+ start_y = offset_y * sampling;
+ break;
+
+ case 'M': /* Set margins */
+ x = ((double)start_x / resolution);
+ y = ((double)start_y / resolution);
+ if(! doubles_prompt(1152/2, 900/2,
+ "left margin: (inches) ", &x,
+ "top margin: (inches) ", &y,
+ 0))
+ break;
+ start_x = (int)(x * resolution);
+ start_y = (int)(y * resolution);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case '*':
+ case '!':
+ case '@':
+ case '#':
+ case '$':
+ case '%':
+ case '^':
+ valid_num = TRUE;
+ if(e == '*')
+ num = (mono ?
+ DEFAULT_MONO_SAMPLING : DEFAULT_COLOUR_SAMPLING);
+ else if(e == '!')
+ num = 1;
+ else if(e == '@')
+ num = 2;
+ else if(e == '#')
+ num = 3;
+ else if(e == '$')
+ num = 4;
+ else if(e == '%')
+ num = 5;
+ else
+ valid_num = FALSE;
+ /* FALLTHROUGH */
+
+ case 's':
+ if(mono)
+ break;
+ if(! valid_num || (num < 1 || num > 5))
+ sampling = DEFAULT_COLOUR_SAMPLING;
+ else
+ sampling = num;
+
+ sample_page();
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'S':
+ if(mono)
+ break;
+ if(! integers_prompt(1152/2, 900/2,
+ "sampling: (1, 2, 3, 4) ", &sampling,
+ 0))
+ break;
+ if(sampling < 1 || sampling > 5)
+ sampling = DEFAULT_COLOUR_SAMPLING;
+
+ sample_page();
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ break;
+
+ case 'x':
+ if(valid_num)
+ mag_size_x = num;
+ else
+ mag_size_x = DEFAULT_MAG_SIZE_X;
+ break;
+
+ case 'y':
+ if(valid_num)
+ mag_size_y = num;
+ else
+ mag_size_y = DEFAULT_MAG_SIZE_Y;
+ break;
+
+ case 'X':
+ case 'Y':
+ if(mono)
+ break;
+ if(! integers_prompt(1152/2, 900/2,
+ "magnifier size (x) : ", &mag_size_x,
+ "magnifier size (y) : ", &mag_size_y,
+ 0))
+ break;
+ break;
+
+ case '[':
+ mag_size_x = 128;
+ mag_size_y = 64;
+ break;
+
+ case ']':
+ mag_size_x = 128;
+ mag_size_y = 128;
+ break;
+
+ case '{':
+ mag_size_x = 256;
+ mag_size_y = 128;
+ break;
+
+ case '}':
+ mag_size_x = 256;
+ mag_size_y = 256;
+ break;
+
+ case '(':
+ mag_size_x = 512;
+ mag_size_y = 256;
+ break;
+
+ case ')':
+ mag_size_x = 512;
+ mag_size_y = 512;
+ break;
+
+ case 'b':
+ if(valid_num)
+ mag_border = num;
+ else
+ mag_border = DEFAULT_MAG_BORDER;
+ break;
+
+ case 'F':
+ if(! strings_prompt(1152/2, 900/2,
+ "Directory: ", directory,
+ "Filename: ", filename,
+ 0))
+ break;
+
+ /*
+ * Build the whole pathname.
+ */
+ if(directory[0] != '\0')
+ {
+ strcpy(pathname, directory);
+ if(pathname[strlen(pathname)-1] != '/')
+ strcat(pathname, "/");
+ strcat(pathname, filename);
+ }
+ else
+ strcpy(pathname, filename);
+
+ /*
+ * If the filename has no extension, or if it
+ * has an extension and it is not '.dvi' then
+ * cat .dvi onto the filename.
+ */
+ if((extension = rindex(pathname, '.')) == NULL ||
+ strcmp(extension, ".dvi") != 0)
+ strcat(pathname, ".dvi");
+
+ sprintf(label, "%s: Opening file \"%s\"",
+ DVIPAGE_LABEL, filename);
+ window_set(disp_frame,
+ FRAME_LABEL, label,
+ 0);
+ close_dvi_file();
+ if(init_dvi_file())
+ {
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ }
+ break;
+
+ case 'R': /* Reopen file */
+ sprintf(label, "%s: Reopening file \"%s\"",
+ DVIPAGE_LABEL, filename);
+ window_set(disp_frame,
+ FRAME_LABEL, label,
+ 0);
+ if(valid_num)
+ {
+ pp = num;
+ page_or_sheet = TRUE;
+ }
+ else
+ {
+ pp = disp_sheet;
+ page_or_sheet = FALSE;
+ }
+ close_dvi_file();
+ if(init_dvi_file())
+ {
+ if(page_or_sheet)
+ {
+ if(! goto_page(pp))
+ (void)goto_sheet(1);
+ }
+ else
+ {
+ if(! goto_sheet(pp))
+ (void)goto_sheet(1);
+ }
+
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ }
+ break;
+
+ case 'P':
+ sprintf(command, print_page_spooler,
+ disp_page, disp_page, pathname);
+ if(verbose & DEBUG_PRINTER)
+ fprintf(stderr, "Printer command '%s'\n", command);
+ system(command);
+ break;
+
+ case Control('P'):
+ sprintf(command, print_spooler, pathname);
+ if(verbose & DEBUG_PRINTER)
+ fprintf(stderr, "Printer command '%s'\n", command);
+ system(command);
+ break;
+
+ case 'w':
+ show_page_frame = ! show_page_frame;
+
+ if(goto_sheet(disp_sheet))
+ {
+ process_page(RASTERISE);
+ offset_x = start_x / sampling;
+ offset_y = start_y / sampling;
+ page_paint(canvas, pw, 0);
+ }
+
+ break;
+
+ case 'v':
+ if(valid_num)
+ verbose = num;
+ else
+ verbose = 0;
+ break;
+
+ case 'Q':
+ exit();
+ }
+
+ if(! keep_num)
+ {
+ num = 0;
+ valid_num = FALSE;
+ }
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "end__event: num = %d @ %d\n", num, valid_num);
+}
+
+/*
+ * page_menu:
+ * Displays a menu in response to MS_RIGHT, returns a character
+ * code to calling function to effect action.
+ */
+
+int
+page_menu(canvas, pw, event)
+Canvas canvas;
+Pixwin *pw;
+Event *event;
+{
+ static Menu menu = NULL;
+ int action;
+
+ if(! menu)
+ {
+ /*
+ * Return values from this menu are passed to the
+ * event procedure, and the codes here must match
+ * codes in that function.
+ */
+ menu = menu_create(
+ MENU_ITEM,
+ MENU_STRING, "Next Page",
+ MENU_VALUE, 'n',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Previous Page",
+ MENU_VALUE, 'p',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "First Page",
+ MENU_VALUE, '_',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Last Page",
+ MENU_VALUE, 'G',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Sampling",
+ MENU_PULLRIGHT, menu_create(
+ MENU_ITEM,
+ MENU_STRING, "Default Sampling",
+ MENU_VALUE, '%',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "No Sampling",
+ MENU_VALUE, '!',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "2:1 Sampling",
+ MENU_VALUE, '@',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "3:1 Sampling",
+ MENU_VALUE, '#',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "4:1 Sampling",
+ MENU_VALUE, '$',
+ 0,
+ 0),
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Magnifier",
+ MENU_PULLRIGHT, menu_create(
+ MENU_ITEM,
+ MENU_STRING, "128 x 64",
+ MENU_VALUE, '[',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "128 x 128",
+ MENU_VALUE, ']',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "256 x 128",
+ MENU_VALUE, '{',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "256 x 256",
+ MENU_VALUE, '}',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "512 x 256",
+ MENU_VALUE, '(',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "512 x 512",
+ MENU_VALUE, ')',
+ 0,
+ 0),
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Reopen DVI file",
+ MENU_VALUE, 'R',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "New DVI file",
+ MENU_VALUE, 'F',
+ 0,
+/* MENU_ITEM,
+ MENU_STRING, "Print Page",
+ MENU_VALUE, 'P',
+ 0,
+ MENU_ITEM,
+ MENU_STRING, "Print Document",
+ MENU_VALUE, Control('P'),
+ 0, */
+ MENU_ITEM,
+ MENU_STRING, "Quit",
+ MENU_VALUE, 'Q',
+ 0,
+ 0);
+ }
+
+ return (int)menu_show(menu, canvas, event, 0);
+}
+
+/*
+ * page_magnify:
+ * Pops up magnified region (only if sampling != 1).
+ * Currently unimplemented.
+ */
+
+void
+page_magnify(canvas, pw, event)
+Canvas canvas;
+Pixwin *pw;
+Event *event;
+{
+ Rect r;
+ int w, h;
+ double scale_x, scale_y;
+ int sample_w, sample_h;
+ int new_sample_x, new_sample_y;
+ int delta_x, delta_y;
+ int sample_x, sample_y;
+ int dst_x, dst_y;
+ int page_x, page_y;
+ int old_cursor_op;
+ bool first_time = TRUE;
+ int win_x, win_y;
+#ifdef GOBBLE_MAGNIFY
+ int ninputs, canvasfd;
+#endif GOBBLE_MAGNIFY
+
+ if(sampling == 1 || sample_pr == NULL)
+ return;
+
+ if(mag_size_x < 4)
+ mag_size_x = 4;
+ if(mag_size_y < 4)
+ mag_size_y = 4;
+ if(mag_size_x > sample_pr->pr_width)
+ mag_size_x = sample_pr->pr_width;
+ if(mag_size_y > sample_pr->pr_height)
+ mag_size_y = sample_pr->pr_height;
+ if(mag_border < 0)
+ mag_border = 0;
+ if(mag_border > 8)
+ mag_border = 8;
+
+ /*
+ * Get Lock rect.
+ */
+ r.r_left = 0;
+ r.r_top = 0;
+ r.r_width = (int)window_get(canvas, WIN_WIDTH);
+ r.r_height = (int)window_get(canvas, WIN_HEIGHT);
+
+ /*
+ * Precompute some window sizes.
+ */
+ w = sample_pr->pr_width;
+ h = sample_pr->pr_height;
+ switch(sampling)
+ {
+ case 2:
+ scale_x = 2.0;
+ scale_y = 2.0;
+ break;
+
+ case 3:
+ scale_x = 8.0 / 3.0;
+ scale_y = 3.0;
+ break;
+
+ case 4:
+ scale_x = 4.0;
+ scale_y = 4.0;
+ break;
+
+ case 5:
+ scale_x = 8.0/3.0;
+ scale_y = 4.0;
+ break;
+
+ default:
+ return;
+ }
+ sample_w = mag_size_x / scale_x;
+ sample_h = mag_size_y / scale_y;
+
+ if(verbose & DEBUG_MAGNIFY)
+ fprintf(stderr, "page_magnify: scale %lf %lf; %d %d -> %d %d\n",
+ scale_x, scale_y, sample_w, sample_h, mag_size_x, mag_size_y);
+
+ /*
+ * Remove the cursor
+ */
+ old_cursor_op = (int)cursor_get(hand_cursor, CURSOR_OP);
+ cursor_set(hand_cursor, CURSOR_OP, PIX_DST, 0);
+ window_set(canvas, WIN_CURSOR, hand_cursor, 0);
+
+ /*
+ * Grab all input
+ */
+ window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0);
+#ifdef GOBBLE_MAGNIFY
+ canvasfd = (int)window_get(canvas, WIN_FD);
+#endif GOBBLE_MAGNIFY
+
+ /*
+ * Loop until up mouse.
+ */
+ sample_x = MAXINT;
+ sample_y = MAXINT;
+ while(! event_is_up(event))
+ {
+ /*
+ * Compute the region which will be magnified.
+ */
+ new_sample_x =
+ Range(0, event_x(event)-offset_x-sample_w/2, w-sample_w);
+ new_sample_y =
+ Range(0, event_y(event)-offset_y-sample_h/2, h-sample_h);
+
+ /*
+ * See how this differs from last magnified region.
+ */
+ delta_x = new_sample_x - sample_x;
+ delta_y = new_sample_y - sample_y;
+
+ /*
+ * Lock
+ */
+ pw_lock(pw, &r);
+
+ if(! first_time)
+ {
+ if(verbose & DEBUG_MAGNIFY)
+ fprintf(stderr, " covering with %d %d\n",
+ delta_x, delta_y);
+
+ /*
+ * Paint those portions of the image which were
+ * covered by the last magnifier, and exposed now.
+ * We could just paint the entire patch, but this
+ * gives unpleasant flashing when moving the window.
+ */
+ if(delta_x > 0)
+ pw_cover(pw, win_x, win_y,
+ delta_x, mag_size_y,
+ PIX_SRC, sample_pr, dst_x, dst_y);
+ else if(delta_x < 0)
+ pw_cover(pw, win_x+mag_size_x+delta_x, win_y,
+ -delta_x, mag_size_y,
+ PIX_SRC, sample_pr,
+ dst_x+mag_size_x+delta_x, dst_y);
+ if(delta_y > 0)
+ pw_cover(pw, win_x, win_y,
+ mag_size_x, delta_y,
+ PIX_SRC, sample_pr, dst_x, dst_y);
+ else if(delta_y < 0)
+ pw_cover(pw, win_x, win_y+mag_size_y+delta_y,
+ mag_size_x, -delta_y,
+ PIX_SRC, sample_pr,
+ dst_x, dst_y+mag_size_y+delta_y);
+ }
+ else
+ first_time = FALSE;
+
+ /*
+ * Compute the new destination and window positions
+ * for the new magnified region.
+ */
+ sample_x = new_sample_x;
+ sample_y = new_sample_y;
+ dst_x = sample_x - (mag_size_x - sample_w)/2;
+ dst_y = sample_y - (mag_size_y - sample_h)/2;
+ win_x = dst_x + offset_x;
+ win_y = dst_y + offset_y;
+ page_x = sample_x * scale_x;
+ page_y = sample_y * scale_y;
+
+ if(verbose & DEBUG_MAGNIFY)
+ fprintf(stderr, " painting at %d %d from %d %d\n",
+ dst_x, dst_y, page_x, page_y);
+
+ /*
+ * Display the magnified region.
+ */
+ pw_write(pw, win_x, win_y, mag_size_x, mag_size_y,
+ PIX_SRC, page_pr, page_x, page_y);
+ if(mag_border)
+ pw_rect(pw, win_x, win_y, mag_size_x, mag_size_y,
+ mag_border, PIX_SRC, -1);
+
+ /*
+ * Unlock
+ */
+ pw_unlock(pw);
+
+ /*
+ * Read another event.
+ */
+ window_read_event(canvas, event);
+#ifdef GOBBLE_MAGNIFY
+ if(ioctl(canvasfd, FIONREAD, &ninputs) == 0)
+ while(ninputs >= sizeof(Event) &&
+ window_read_event(canvas, event) == 0 &&
+ ! event_is_up(event))
+ ninputs -= sizeof(Event);
+#endif GOBBLE_MAGNIFY
+ }
+
+ /*
+ * Ungrab all input.
+ */
+ window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0);
+
+ /*
+ * Repaint
+ */
+ pw_cover(pw, win_x, win_y, mag_size_x, mag_size_y,
+ PIX_SRC, sample_pr, dst_x, dst_y);
+
+ /*
+ * Restore the cursor.
+ */
+ cursor_set(hand_cursor, CURSOR_OP, old_cursor_op, 0);
+ window_set(canvas, WIN_CURSOR, hand_cursor, 0);
+}
+
+/*
+ * page_pan:
+ * Pans page within screen.
+ */
+
+void
+page_pan(canvas, pw, event)
+Canvas canvas;
+Pixwin *pw;
+Event *event;
+{
+ int x, y;
+ int dx, dy;
+#ifdef GOBBLE_PAN
+ int ninputs, canvasfd;
+#endif GOBBLE_PAN
+
+
+ if(sample_pr == NULL)
+ return;
+
+ window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0);
+#ifdef GOBBLE_PAN
+ canvasfd = (int)window_get(canvas, WIN_FD);
+#endif GOBBLE_PAN
+
+ do
+ {
+ x = event_x(event);
+ y = event_y(event);
+
+ window_read_event(canvas, event);
+#ifdef GOBBLE_PAN
+ if(ioctl(canvasfd, FIONREAD, &ninputs) == 0)
+ while(ninputs >= sizeof(Event) &&
+ window_read_event(canvas, event) == 0 &&
+ ! event_is_up(event))
+ ninputs -= sizeof(Event);
+#endif GOBBLE_PAN
+
+ dx = event_x(event) - x;
+ dy = event_y(event) - y;
+
+ if(dx != 0 || dy != 0)
+ {
+ offset_x += dx;
+ offset_y += dy;
+
+ pw_cover(pw, 0, 0,
+ (int)window_get(canvas, WIN_WIDTH),
+ (int)window_get(canvas, WIN_HEIGHT),
+ PIX_SRC, sample_pr, -offset_x, -offset_y);
+ }
+ }
+ while(! event_is_up(event));
+
+ window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0);
+}
+
+/*
+ * goto_sheet:
+ * Opens requested sheet on screen.
+ */
+
+bool
+goto_sheet(new_sheet)
+int new_sheet;
+{
+ if(! check_dvi_file())
+ return FALSE;
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "goto_sheet(%d)\n", new_sheet);
+
+ /*
+ * Check against page limits.
+ */
+ if(new_sheet <= 0)
+ {
+ message("Attempt to go to sheet %d.", new_sheet);
+ return FALSE;
+ }
+
+ /*
+ * Are we already at the desired page ?
+ */
+ if(file_sheet == new_sheet)
+ return TRUE;
+
+ /*
+ * Do we already know where the page is ?
+ */
+ if(new_sheet < MAX_SHEETS && new_sheet <= last_known_sheet)
+ {
+ fseek(dvifp, sheet_table[new_sheet], 0);
+ file_sheet = new_sheet;
+ return TRUE;
+ }
+
+ /*
+ * Can't find it directly in the table:
+ * Go to the last known sheet...
+ */
+ file_sheet = last_known_sheet;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+
+ /*
+ * Skip through the rest of the pages to the new page.
+ */
+ while(file_sheet < new_sheet)
+ {
+ /*
+ * Check for last page:
+ * Last page is always returned.
+ */
+ if(last_sheet && file_sheet >= last_sheet)
+ {
+ file_sheet = last_sheet - 1;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+ return TRUE;
+ }
+
+ /*
+ * Otherwise, skip this page and look at the next.
+ */
+ process_page(SKIP);
+ }
+ return TRUE;
+}
+
+/*
+ * goto_page:
+ * Opens requested page on screen.
+ */
+
+bool
+goto_page(new_page)
+int new_page;
+{
+ int sheet;
+
+ if(! check_dvi_file())
+ return FALSE;
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "goto_page(%d)\n", new_page);
+
+ /*
+ * Search for page in the table.
+ */
+ for(sheet = 1; sheet < last_known_sheet; sheet++)
+ {
+ if(sheet_page[sheet] == new_page)
+ {
+ file_sheet = sheet;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+ return TRUE;
+ }
+ }
+
+ /*
+ * Can't find it directly in the table:
+ * Go to the last known sheet...
+ */
+ file_sheet = last_known_sheet;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+
+ /*
+ * Skip through the rest of the pages to the new page.
+ */
+ for( ; ; )
+ {
+ /*
+ * Check for last page:
+ */
+ if(last_sheet && file_sheet >= last_sheet)
+ {
+ if(new_page == LAST_PAGE)
+ {
+ file_sheet = last_sheet - 1;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ /*
+ * Otherwise, examine this page.
+ */
+ sheet = file_sheet;
+ process_page(SKIP);
+
+ /*
+ * If this was the page, go back,
+ * and return it.
+ */
+ if(sheet_page[sheet] == new_page)
+ {
+ file_sheet = sheet;
+ fseek(dvifp, sheet_table[file_sheet], 0);
+ return TRUE;
+ }
+ }
+}
+
+/*
+ * DVI file functions.
+ * ==================
+ */
+
+/*
+ * init_dvi_file:
+ * Opens the dvi file, and checks for valid codes etc.
+ * Reads the postamble (if enabled)
+ * Leaves the file pointer at the start of the first page.
+ */
+
+bool
+init_dvi_file()
+{
+ int i;
+
+ /*
+ * Open the file; close-on-exec.
+ */
+ if((dvifp = fopen(pathname, "r")) == NULL)
+ {
+ message("Cant open file %s", pathname);
+ return FALSE;
+ }
+ fcntl(fileno(dvifp), F_SETFD, 1);
+
+ /*
+ * Read the magic number and version number
+ */
+ if((i = get_unsigned(dvifp, 1)) != PRE)
+ {
+ message("%s: not a dvi file.", filename);
+ fclose(dvifp);
+ return FALSE;
+ }
+ if((i = get_signed(dvifp, 1)) != DVIFORMAT)
+ {
+ message("%s: dvi format %d not supported.", filename, i);
+ fclose(dvifp);
+ return FALSE;
+ }
+
+ /*
+ * Make a note of the access time.
+ */
+ if(fstat(fileno(dvifp), &stat_buf) == 0)
+ {
+ mtime = stat_buf.st_mtime;
+ }
+ else
+ {
+ message("%s: dvifile stat failed.", filename);
+ mtime = 0;
+ }
+
+ if(pre_load)
+ {
+ /*
+ * Load font information from postable.
+ */
+ if(! read_postamble())
+ {
+ fclose(dvifp);
+ return FALSE;
+ }
+
+ /*
+ * Return to start of first page.
+ */
+ fseek(dvifp, (long)14, 0);
+ }
+ else
+ {
+ /*
+ * Read basic data from preamble.
+ */
+ num = get_unsigned(dvifp, 4);
+ den = get_unsigned(dvifp, 4);
+ mag = get_unsigned(dvifp, 4);
+ hconv = vconv = do_convert(num, den, resolution);
+ }
+
+ /*
+ * Skip i more bytes of preamble.
+ */
+ i = get_unsigned(dvifp, 1);
+ fseek(dvifp, (long)i, 1);
+
+ /*
+ * Allocate buffer for the page.
+ */
+ if(! (page_pr = pr_alloc(&page_mpr,
+ (int)(page_w * resolution), (int)(page_h * resolution), 1)))
+ {
+ message("Out of memory for image allocation.");
+ fclose(dvifp);
+ return FALSE;
+ }
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "Allocated buffer (%d x %d)\n",
+ page_pr->pr_width, page_pr->pr_height);
+
+ /*
+ * Set up the page fseek pointer table.
+ * We are now at page 0.
+ */
+ for(i = 0; i < MAX_SHEETS; i++)
+ {
+ sheet_table[i] = 0;
+ sheet_page[i] = BAD_PAGE;
+ }
+ file_sheet = 1;
+ last_sheet = 0; /* last page == unknown */
+ last_known_sheet = 1;
+ sheet_table[last_known_sheet] = ftell(dvifp);
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "sheet_table[%d] = %d\n",
+ last_known_sheet, ftell(dvifp));
+
+ return TRUE;
+}
+
+/*
+ * close_dvi_file:
+ * Cleans up after reading a file.
+ */
+
+void
+close_dvi_file()
+{
+ if(dvifp == NULL)
+ return;
+
+ /*
+ * Get rid of image memory.
+ */
+ sample_pr = pr_free(&sample_mpr);
+ page_pr = pr_free(&page_mpr);
+
+ /*
+ * close the dvifile.
+ */
+ fclose(dvifp);
+ dvifp = NULL;
+ mtime = 0;
+
+ /*
+ * Hack the sheet numbers to prevent access to the file.
+ */
+ last_sheet = -1;
+ last_known_sheet = -1;
+
+ /*
+ * Close the fonts and free up memory.
+ */
+ close_fonts();
+}
+
+/*
+ * check_dvi_file:
+ * Checks that this is the same file -- has not been modified since
+ * it was opened.
+ */
+
+bool
+check_dvi_file()
+{
+ if(dvifp == NULL)
+ {
+ message("No dvifile open");
+ return FALSE;
+ }
+
+ if(fstat(fileno(dvifp), &stat_buf) != 0)
+ {
+ message("%s: dvifile fstat failed.", filename);
+ return FALSE;
+ }
+
+ if(stat_buf.st_mtime != mtime)
+ {
+ message("%s: dvifile modified", filename);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * read_postamble:
+ * This routine is used to read in the postamble values. It
+ * initializes the magnification and checks the stack height prior to
+ * starting printing the document.
+ * Returns TRUE unless document cannot be processed.
+ */
+
+bool
+read_postamble()
+{
+ if(! check_dvi_file())
+ return FALSE;
+
+ if(! find_postamble_ptr (&postambleptr))
+ return FALSE;
+
+ if(get_unsigned(dvifp, 1) != POST)
+ {
+ message("%s: bad dvi file: no POST at head of postamble.",
+ filename);
+ return FALSE;
+ }
+
+ (void)get_unsigned(dvifp, 4); /* discard last page pointer */
+ num = get_unsigned(dvifp, 4);
+ den = get_unsigned(dvifp, 4);
+ mag = get_unsigned(dvifp, 4);
+ hconv = vconv = do_convert(num, den, resolution);
+
+ (void)get_unsigned(dvifp, 4); /* height-plus-depth of tallest page */
+ (void)get_unsigned(dvifp, 4); /* width of widest page */
+
+ if(get_unsigned(dvifp, 2) >= STACKSIZE)
+ {
+ message("%s: bad dvi file: stack is too large.",
+ filename);
+ return FALSE;
+ }
+
+ /* last_sheet = */ get_unsigned(dvifp, 2);
+
+ if(! get_font_def())
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * find_postamble_ptr
+ * Move to the end of the dvifile and find the start of the postamble.
+ */
+
+bool
+find_postamble_ptr(postambleptr)
+long *postambleptr;
+{
+ int i;
+
+ fseek(dvifp, (long) 0, 2);
+ *postambleptr = ftell(dvifp) - 4;
+ fseek(dvifp, *postambleptr, 0);
+
+ for( ; ; )
+ {
+ fseek(dvifp, --(*postambleptr), 0);
+ if(((i = get_unsigned(dvifp, 1)) != 223) && (i != DVIFORMAT))
+ {
+ message("%s: Bad dvi file: bad end of file", filename);
+ return FALSE;
+ }
+ if(i == DVIFORMAT)
+ break;
+ }
+
+ fseek(dvifp, (*postambleptr) - 4, 0);
+ *postambleptr = get_unsigned(dvifp, 4);
+ fseek(dvifp, *postambleptr, 0);
+
+ return TRUE;
+}
+
+/*
+ * process_page:
+ * Rasterises the next page in the dvifile into page_mpr.
+ * Leaves the file pointer at the start of the next page.
+ *
+ * If skip mode is true, then nothing is actually drawn, the commands
+ * are interpreted only for the side effect of moving the filepointer
+ * to the next page.
+ */
+
+bool
+process_page(skip_mode)
+register bool skip_mode;
+{
+ int command; /* current command */
+ register int i; /* command parameter; loop index */
+ int k; /* temporary parameter */
+ int val, val2; /* temporarys to hold command information*/
+ int w; /* current horizontal spacing */
+ int x; /* current horizontal spacing */
+ int y; /* current vertical spacing */
+ int z; /* current vertical spacing */
+ int counter[10];
+ int sp; /* stack pointer */
+ static struct stack_entry stack[STACKSIZE]; /* stack */
+
+ if(! check_dvi_file())
+ return FALSE;
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "sheet %d starts at %d\n",
+ file_sheet, ftell(dvifp));
+
+ while((command = get_unsigned(dvifp, 1)) != EOP)
+ {
+ switch(command)
+ {
+
+ case SET1:
+ case SET2:
+ case SET3:
+ case SET4:
+ val = get_unsigned(dvifp, command-SET1+1);
+ if(! skip_mode)
+ set_char(val, command);
+ break;
+
+ case SET_RULE:
+ val = get_unsigned(dvifp, 4);
+ val2 = get_unsigned(dvifp, 4);
+ if(! skip_mode)
+ set_rule(val, val2, 1);
+ break;
+
+ case PUT1:
+ case PUT2:
+ case PUT3:
+ case PUT4:
+ val = get_unsigned(dvifp,command-PUT1+1);
+ if(! skip_mode)
+ set_char(val, command);
+ break;
+
+ case PUT_RULE:
+ val = get_unsigned(dvifp, 4);
+ val2 = get_unsigned(dvifp, 4);
+ if(! skip_mode)
+ set_rule(val, val2, 0);
+ break;
+
+ case NOP:
+ break;
+
+ case BOP:
+ /*
+ * These are the 10 counters.
+ * Discard previous page pointer.
+ */
+ for(i=0; i<10; i++)
+ counter[i] = get_unsigned(dvifp, 4);
+ (void)get_unsigned(dvifp, 4);
+
+ /*
+ * The first counter is the page number.
+ */
+ disp_page = counter[0];
+ if(file_sheet < MAX_SHEETS)
+ sheet_page[file_sheet] = disp_page;
+
+ /*
+ * Show what is happening.
+ */
+ sprintf(label, "%s: File \"%s\" Page %d %s",
+ DVIPAGE_LABEL, filename,
+ disp_page, (skip_mode) ? "Skipping" : "Processing");
+ window_set(disp_frame,
+ FRAME_LABEL, label,
+ 0);
+
+ if(! skip_mode)
+ {
+ /*
+ * Clear the page
+ */
+ pr_rop(page_pr, 0, 0,
+ page_pr->pr_width, page_pr->pr_height,
+ PIX_CLR, NULL, 0, 0);
+
+ /*
+ * Mark the edges of the page
+ */
+ pr_rect(page_pr, 0, 0,
+ (int)(page_w * resolution),
+ (int)(page_h * resolution),
+ 3, PIX_SET, 1);
+
+ /*
+ * Mark the nominal page window.
+ */
+ if(show_page_frame)
+ {
+ pr_rect(page_pr, 0+origin_x, 0+origin_y,
+ (int)(page_w*resolution) - 2*origin_x,
+ (int)(page_h*resolution) - 2*origin_y,
+ 1, PIX_SET, 1);
+ }
+ }
+
+ h = v = w = x = y = z = 0;
+ sp = 0;
+ fontptr = NULL;
+ break;
+
+ case PUSH:
+ if (sp >= STACKSIZE)
+ {
+ message("%s: Bad dvi file: stack overflow",
+ filename);
+ return FALSE;
+ }
+ stack[sp].h = h;
+ stack[sp].v = v;
+ stack[sp].w = w;
+ stack[sp].x = x;
+ stack[sp].y = y;
+ stack[sp].z = z;
+ sp++;
+ break;
+
+ case POP:
+ --sp;
+ if (sp < 0)
+ {
+ message("%s: Bad dvi file: stack underflow",
+ filename);
+ return FALSE;
+ }
+ h = stack[sp].h;
+ v = stack[sp].v;
+ w = stack[sp].w;
+ x = stack[sp].x;
+ y = stack[sp].y;
+ z = stack[sp].z;
+ break;
+
+ case RIGHT1:
+ case RIGHT2:
+ case RIGHT3:
+ case RIGHT4:
+ val = get_signed(dvifp,command-RIGHT1+1);
+ if(! skip_mode)
+ move_over(val);
+ break;
+
+ case W0:
+ if(! skip_mode)
+ move_over(w);
+ break;
+
+ case W1:
+ case W2:
+ case W3:
+ case W4:
+ w = get_signed(dvifp,command-W1+1);
+ if(! skip_mode)
+ move_over(w);
+ break;
+
+ case X0:
+ if(! skip_mode)
+ move_over(x);
+ break;
+
+ case X1:
+ case X2:
+ case X3:
+ case X4:
+ x = get_signed(dvifp,command-X1+1);
+ if(! skip_mode)
+ move_over(x);
+ break;
+
+ case DOWN1:
+ case DOWN2:
+ case DOWN3:
+ case DOWN4:
+ val = get_signed(dvifp,command-DOWN1+1);
+ if(! skip_mode)
+ move_down(val);
+ break;
+
+ case Y0:
+ if(! skip_mode)
+ move_down(y);
+ break;
+
+ case Y1:
+ case Y2:
+ case Y3:
+ case Y4:
+ y = get_signed(dvifp,command-Y1+1);
+ if(! skip_mode)
+ move_down(y);
+ break;
+
+ case Z0:
+ if(! skip_mode)
+ move_down(z);
+ break;
+
+ case Z1:
+ case Z2:
+ case Z3:
+ case Z4:
+ z = get_signed(dvifp,command-Z1+1);
+ if(! skip_mode)
+ move_down(z);
+ break;
+
+ case FNT1:
+ case FNT2:
+ case FNT3:
+ case FNT4:
+ if(! skip_mode)
+ set_font_num(
+ get_unsigned(dvifp,command-FNT1+1));
+ break;
+
+ case XXX1:
+ case XXX2:
+ case XXX3:
+ case XXX4:
+ k = get_unsigned(dvifp,command-XXX1+1);
+ while(k--)
+ get_unsigned(dvifp, 1);
+ break;
+
+ case FNT_DEF1:
+ case FNT_DEF2:
+ case FNT_DEF3:
+ case FNT_DEF4:
+ if(pre_load)
+ skip_font_def(
+ get_unsigned(dvifp, command-FNT_DEF1+1));
+ else
+ if(! read_font_def(
+ get_unsigned(dvifp, command-FNT_DEF1+1)))
+ return FALSE;
+ break;
+
+ case PRE:
+ message(
+ "%s: Bad dvi file: preamble found within main section.",
+ filename);
+ return FALSE;
+
+ case POST:
+ fseek(dvifp, (long) -1, 1);
+ last_sheet = file_sheet;
+
+ /*
+ * We have done nothing, so there is no need to
+ * resample the page or increment the page counter.
+ */
+ return FALSE;
+
+ case POST_POST:
+ message(
+ "%s: Bad dvi file: postpostamble found within main section.",
+ filename);
+ return FALSE;
+
+ default:
+ if(command >= FONT_00 && command <= FONT_63)
+ {
+ if(! skip_mode)
+ set_font_num(command - FONT_00);
+ }
+ else if(command >= SETC_000 && command <= SETC_127)
+ {
+ if(! skip_mode)
+ set_char(command - SETC_000, command);
+ }
+ else
+ {
+ message(
+ "%s: Bad dvi file: undefined command (%d) found.",
+ filename, command);
+ return FALSE;
+ }
+ }
+ }
+
+ /*
+ * End of page.
+ */
+ if(! skip_mode)
+ {
+ /*
+ * Sample the page.
+ */
+ sample_page();
+ disp_sheet = file_sheet;
+ }
+
+ /*
+ * The file is now at the start of the next page.
+ */
+ file_sheet++;
+ if(file_sheet > last_known_sheet)
+ {
+ if(file_sheet < MAX_SHEETS)
+ {
+ last_known_sheet = file_sheet;
+ sheet_table[file_sheet] = ftell(dvifp);
+ }
+
+ if(verbose & DEBUG_SHEET)
+ fprintf(stderr, "sheet %d starts at %d\n",
+ file_sheet, ftell(dvifp));
+ }
+
+ return TRUE;
+}
+
+/*
+ * Draw and Move Functions.
+ * ========================
+ */
+
+/*
+ * set_font_num:
+ * This routine is used to specify the font to be used in printing future
+ * chars.
+ */
+
+void
+set_font_num(k)
+int k;
+{
+ for(fontptr = hfontptr; fontptr != NULL; fontptr = fontptr->next)
+ {
+ if(fontptr->k == k)
+ {
+ fontptr->use_count++;
+ return;
+ }
+ }
+
+ fprintf(stderr, "I have lost a font; this cant happen\n");
+ exit(1);
+}
+
+/*
+ * set_char:
+ */
+
+void
+set_char(c, command)
+int c, command;
+{
+ register struct char_entry *ptr;
+
+ ptr = &(fontptr->ch[c]);
+ hh = Pix_round(h, hconv);
+ vv = Pix_round(v, vconv);
+
+ if(! ptr->where.isloaded)
+ if(! load_char(fontptr, ptr))
+ return;
+
+ if(ptr->where.address.pixrectptr)
+ pr_rop(page_pr, hh - ptr->xOffset + origin_x,
+ vv - ptr->yOffset + origin_y,
+ ptr->width, ptr->height, PIX_SRC | PIX_DST,
+ ptr->where.address.pixrectptr, 0, 0);
+
+ if(command <= SET4)
+ h += ptr->tfmw;
+
+ return;
+}
+
+/*
+ * set_rule:
+ * This routine will draw a rule on the screen
+ */
+
+void
+set_rule(a, b, Set)
+int a, b;
+bool Set;
+{
+ int ehh, evv;
+
+ hh = Pix_round(h, hconv);
+ vv = Pix_round(v - a, vconv);
+ ehh = Pix_round(h + b, hconv);
+ evv = Pix_round(v, vconv);
+
+ if(hh == ehh)
+ ehh++;
+ if(vv == evv)
+ vv--;
+ if((a > 0) && (b > 0))
+ pr_rop(page_pr, hh+origin_x, vv+origin_y,
+ ehh-hh, evv-vv, PIX_SET, NULL, 0, 0);
+ if(Set)
+ {
+ h += b;
+/* v += a; */
+ }
+}
+
+/*
+ * move_down:
+ */
+
+void
+move_down(a)
+int a;
+{
+ v += a;
+}
+
+
+/*
+ * move_over:
+ */
+
+void
+move_over(b)
+int b;
+{
+ h += b;
+}
diff --git a/dviware/dvipage/dvipage.h b/dviware/dvipage/dvipage.h
new file mode 100644
index 0000000000..5f920a4c3f
--- /dev/null
+++ b/dviware/dvipage/dvipage.h
@@ -0,0 +1,400 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * From the dvisun manual page entry:
+ * Mark Senn wrote the early versions of [dvisun] for the
+ * BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
+ * Furuta, James Schaad and Robert Wells improved it. Norm
+ * Hutchinson ported the program to the Sun. Further bug fixes
+ * by Rafael Bracho at Schlumberger.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: dvipage.h,v $
+ * Revision 1.2 88/12/15 17:22:36 hunt
+ * Reduced MAXOPEN to 12; leaves enough fds for popups and prompts in worst
+ * case: complete set of fonts, message window and popup window.
+ *
+ * Revision 1.1 88/11/28 18:42:06 hunt
+ * Initial revision
+ *
+ */
+
+/*
+ * Switches and flags;
+ * ==================
+ *
+ * Some of these constants will be customised for different installations.
+ */
+
+/*
+ * Define USEGLOBALMAG to see effect of mag changes in previewer;
+ * Best left commented out.
+ */
+/* #define USEGLOBALMAG 1 /* Use dvi global magnification ??? */
+
+/*
+ * FONT_PATH is the environment variable searched for a font path spec.
+ * FONT_AREA is the default font path; a colon separated list of possible
+ * directories in which pxl and gf files reside.
+ */
+#define FONT_PATH "FONT_PATH"
+
+#ifndef FONT_AREA
+#ifdef sparc
+#define FONT_AREA \
+ "/usr/local/lib/tex/fonts/pkb:/usr/local/lib/tex/fonts/pk"
+#else !sparc
+#define FONT_AREA \
+ "/usr/local/lib/tex/fonts/pkb:/usr/local/lib/tex/fonts/pk"
+#endif sparc
+#endif FONT_AREA
+
+/*
+ * These constants set flag defaults; if the flag is 0, that type of
+ * font file will not be read.
+ */
+#define USE_GF 1
+#define USE_PXL 1
+#define USE_PK 1
+
+/*
+ * Define a command which will print the whole document.
+ */
+#ifndef PRINT_SPOOLER
+#define PRINT_SPOOLER "lpr -d %s >/dev/null 2>/dev/null"
+#endif PRINT_SPOOLER
+
+/*
+ * Define a command which will print the specified page of the document.
+ */
+#ifndef PRINT_PAGE_SPOOLER
+#define PRINT_PAGE_SPOOLER \
+ "texpagefilter -f %d -t %d %s | lpr -d >/dev/null 2>/dev/null"
+#endif PRINT_PAGE_SPOOLER
+
+/*
+ * The default size of page which will be used
+ */
+#define PAGE_WIDTH (8.3) /* Inches */
+#define PAGE_HEIGHT (11.7) /* Inches */
+
+/*
+ * The default origin on the paper; this corresponds to the
+ * normal TeX standard; change it only if your printer or dvi processor is
+ * broken and you must match
+ */
+#define DEFAULT_ORIGIN_X (1) /* inches */
+#define DEFAULT_ORIGIN_Y (1) /* inches */
+
+/*
+ * default starting display... makes better use of screen.
+ */
+
+#define DEFAULT_START_X (0) /* inches */
+#define DEFAULT_START_Y (0) /* inches */
+
+/*
+ * These are the defaults for resolution and sampling factors
+ * of fonts for colour and mono screens.
+ */
+#define DEFAULT_MONO_RES 118
+#define DEFAULT_COLOUR_RES 300
+
+#define DEFAULT_MONO_SAMPLING 1 /* Must be 1 */
+#define DEFAULT_COLOUR_SAMPLING 4
+
+/*
+ * This is the default magnifier size and border width.
+ */
+#define DEFAULT_MAG_SIZE_X (256)
+#define DEFAULT_MAG_SIZE_Y (128)
+#define DEFAULT_MAG_BORDER (2)
+
+/*
+ * Some limits in the program. Change for extraordinary TeX files.
+ */
+#ifdef NOFILE
+#define MAXOPEN NOFILE-6 /* leave room for stdio, */
+ /* window, message,popup */
+#else
+#define MAXOPEN 12 /* Max number of open font files. */
+#endif
+#define STACKSIZE 100 /* dvi stack max length */
+#define STRSIZE MAXPATHLEN /* Max string length */
+#define MAX_SHEETS 512 /* Pages remembered in table */
+
+/*
+ * This identifies the version number of the previewer.
+ */
+#define DVIPAGE_LABEL "DVI Previewer 3.0" /* Frame label */
+
+/*
+ * Standard definitions.
+ * ====================
+ */
+
+#ifndef _TYPES_
+typedef unsigned int uint;
+typedef unsigned short ushort;
+#endif _TYPES_
+typedef unsigned char uchar;
+#ifdef bool
+#undef bool
+#endif bool
+typedef unsigned int bool;
+
+#define DEL '\177'
+#define ESC '\033'
+#define Control(c) ((c) - 0x40)
+
+#define A_ARG 0
+#define A_END (-1)
+
+#define forward extern
+
+#define Range(min, x, max) (((x) < (min))? \
+ (min) : (((x) > (max))? (max) : (x)) \
+ )
+
+#define MAXINT 2147483647
+#define NEGMAXINT (-2147483648)
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif TRUE
+
+/*
+ * System wide constants.
+ * =====================
+ */
+
+#define NONEXISTENT (-1) /* Offset when font file not found */
+#define NO_FILE ((FILE *)-1)
+
+#define NFNTCHARS 256
+
+#define PXLID 1001
+
+#define DVIFORMAT 2
+
+#define SKIP TRUE /* Flags for process_page() */
+#define RASTERISE FALSE
+
+#define DEBUG_FONTS 1
+#define DEBUG_CHARS 2
+#define DEBUG_PRINTER 4
+#define DEBUG_IMSIZE 8
+#define DEBUG_SHEET 16
+#define DEBUG_MAGNIFY 32
+
+#define BAD_PAGE NEGMAXINT
+#define LAST_PAGE MAXINT
+
+/*
+ * Macros:
+ * return rounded number of pixels
+ */
+
+#define Pix_round(x, conv) ((int)(((x) + ((conv) >> 1)) / (conv)))
+
+/*
+ * Data Structures
+ * ===============
+ */
+
+/*
+ * Character information.
+ * Width in pixels.
+ * Height in pixels.
+ * X offset in pixels.
+ * Y offset in pixels.
+ * Location of bits
+ * Flag for bits have been loaded into memory.
+ * offset to position in file.
+ * pointer to the bits.
+ * width.
+ */
+
+struct char_entry
+{
+ ushort width;
+ ushort height;
+ short xOffset;
+ short yOffset;
+ struct
+ {
+ int isloaded;
+ union
+ {
+ int fileOffset;
+ struct pixrect *pixrectptr;
+ } address;
+ int flags;
+ } where;
+ int tfmw;
+};
+
+/*
+ * Font information.
+ */
+
+struct font_entry
+{
+ struct font_entry *next; /* Linked list of fonts in use. */
+ FILE *font_file_fd; /* FP (0 if not open, -1 if unavail) */
+ int use_count; /* Count of number of uses of font */
+ int k; /* Internal font descriptor */
+ int c; /* checksum from DVI file */
+ int s; /* space size from DVI file */
+ int d; /* design size from DVI file */
+ int a; /* area length for font name */
+ int l; /* device length */
+ char n[STRSIZE]; /* FNT_DEF command parameters */
+ int font_space; /* computed from FNT_DEF s parameter */
+ int font_gf_mag; /* computed from s and d parameters */
+ int font_pxl_mag; /* computed from s and d parameters */
+ char psname[STRSIZE];/* ps name of font file */
+ char name[STRSIZE]; /* full name of font file */
+ int type; /* PXL or GF */
+ int magnification; /* magnification read from font file */
+ int designsize; /* design size read from font file */
+ struct char_entry ch[NFNTCHARS];/* character information */
+};
+
+#define TYPE_PXL 1
+#define TYPE_GF 2
+#define TYPE_PK 3
+
+/*
+ * mem_pixrect:
+ * A statically allocatable pixrect structure.
+ * Contains the pixrect data and the mpr_data.
+ */
+
+struct mem_pixrect
+{
+ struct pixrect mpr_pr;
+ struct mpr_data mpr_data;
+};
+
+/*
+ * Globals.
+ * =======
+ */
+
+extern struct font_entry *fontptr;
+extern struct font_entry *hfontptr;
+
+extern bool silent;
+
+extern char pathname[STRSIZE];
+extern char directory[STRSIZE];
+extern char filename[STRSIZE];
+
+extern char *font_path;
+extern bool use_gf;
+extern bool use_pxl;
+extern bool use_pk;
+
+extern FILE *dvifp;
+
+extern int resolution;
+extern int sampling;
+extern bool mono;
+
+extern struct mem_pixrect page_mpr;
+extern struct pixrect *page_pr;
+extern struct mem_pixrect sample_mpr;
+extern struct pixrect *sample_pr;
+
+extern int verbose;
+
+/*
+ * External Functions.
+ * ==================
+ */
+
+extern int abs();
+extern char * getenv();
+extern double atof();
+
+/*
+ * Interfaces.
+ * ==========
+ */
+
+/*
+ * In sample.c:
+ */
+extern void pw_cover();
+extern void pw_rect();
+extern void pr_rect();
+forward struct pixrect * pr_alloc();
+forward struct pixrect * pr_free();
+forward struct pixrect * pr_check();
+forward struct pixrect * pr_link();
+extern void sample_page();
+forward struct pixrect * pr_sample_4();
+forward struct pixrect * pr_sample_34();
+forward struct pixrect * pr_sample_3();
+forward struct pixrect * pr_sample_2();
+extern void make_cmap();
+forward void pw_cover();
+forward void pr_rect();
+forward void pw_rect();
+
+/*
+ * In fonts.c:
+ */
+extern bool get_font_def();
+extern void skip_font_def();
+extern bool read_font_def();
+extern void close_fonts();
+extern bool load_char();
+
+/*
+ * In findfile.c:
+ */
+extern bool find_font_file();
+
+/*
+ * In message.c:
+ */
+extern void message();
+extern bool strings_prompt();
+extern bool integers_prompt();
+extern bool doubles_prompt();
+
+/*
+ * In utils.c:
+ */
+forward unsigned int get_unsigned();
+forward int get_signed();
+forward double actual_factor();
+forward int do_convert();
+
+/*
+ * In args.c:
+ */
+extern char * a_prog_name;
+extern char a_next();
+extern char * a_arg();
+extern int a_integer();
+extern double a_number();
diff --git a/dviware/dvipage/findfile.c b/dviware/dvipage/findfile.c
new file mode 100644
index 0000000000..21d85cd4e1
--- /dev/null
+++ b/dviware/dvipage/findfile.c
@@ -0,0 +1,503 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: findfile.c,v $
+ * Revision 1.1 88/11/28 18:40:44 hunt
+ * Initial revision
+ *
+ * Based upon `mitdrivers/findfile.c'
+ * Copyright 1985 Massachusetts Institute of Technology
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include "dvipage.h"
+
+forward bool find_file_in_path();
+forward bool find_best_file_in_path();
+forward bool scandir();
+forward bool scanpdir();
+forward int strdiff();
+
+
+/*
+ * find_file:
+ * Seaches for a font file in various places.
+ * dirpath is a colon separated list of possible pathnames.
+ * Returns TRUE if a usable file was found.
+ */
+
+bool find_font_file(dir_path, fontptr)
+char *dir_path;
+struct font_entry *fontptr;
+{
+ int min_df, min_dp, min_dm;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "find_font_file(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Search for exact match.
+ */
+ if(find_file_in_path(dir_path, fontptr))
+ return TRUE;
+
+ /*
+ * Search for nearest match.
+ */
+ min_df = min_dp = min_dm = MAXINT;
+ if(find_best_file_in_path(dir_path, fontptr,
+ &min_df, &min_dp, &min_dm))
+ {
+ message("Substituted font %s for %s.%d.",
+ fontptr->name, fontptr->n, fontptr->type == TYPE_PXL ?
+ fontptr->font_pxl_mag : fontptr->font_gf_mag);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * find_file_in_path:
+ * Searches path for a font file.
+ * Returns TRUE if a suitable match has been found.
+ */
+
+bool
+find_file_in_path(dirpath, fontptr)
+char *dirpath;
+struct font_entry *fontptr;
+{
+ char *p;
+ char dir[MAXPATHLEN];
+
+ while(*dirpath)
+ {
+ /*
+ * Copy first/next path prefix to dir[].
+ * Skip over the ':'.
+ */
+ for(p = dir; *dirpath; )
+ {
+ if(*dirpath == ':' || *dirpath == ';')
+ {
+ dirpath++;
+ break;
+ }
+ else
+ *p++ = *dirpath++;
+ }
+ *p = '\0';
+
+ if(use_pk)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dpk",
+ dir, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PK;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dpk",
+ dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PK;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+
+ if(use_gf)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dgf",
+ dir, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_GF;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dgf",
+ dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_GF;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+
+ if(use_pxl)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dpxl",
+ dir, fontptr->n, fontptr->font_pxl_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PXL;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dpxl",
+ dir, fontptr->n, fontptr->n, fontptr->font_pxl_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PXL;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * find_best_file_in_path:
+ * Finds the best match to the desired font.
+ * Returns TRUE if a suitable match is found.
+ */
+
+bool
+find_best_file_in_path(dirpath, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dirpath;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ register char *p;
+ char dir[MAXPATHLEN];
+ bool status = FALSE;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "find_best_font_file(%s .%dgf or %dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Scan over directories in dirpath.
+ */
+ while(*dirpath)
+ {
+ /*
+ * Copy first/next path prefix to dir[].
+ * Skip over the ':'.
+ */
+ for(p = dir; *dirpath != '\0'; )
+ {
+ if(*dirpath == ':' || *dirpath == ';')
+ {
+ dirpath++;
+ break;
+ }
+ else
+ *p++ = *dirpath++;
+ }
+ *p = '\0';
+
+ /*
+ * Scan the directory.
+ */
+ if(scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+
+ /*
+ * Scan any subdirectories.
+ */
+ if(scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+ }
+
+ return status;
+}
+
+/*
+ * scandir:
+ * Scan directory looking for plausible names,
+ * then recurse to subdirectories for plausible point sizes.
+ * Returns TRUE if found a more plausible candidate than previous best.
+ */
+
+bool
+scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dir;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ DIR *dirstream;
+ struct direct *dirrecord;
+ char pdir[MAXPATHLEN];
+ bool status = FALSE;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " scandir(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ if(! (dirstream = opendir(dir)))
+ return FALSE;
+
+ while(dirrecord = readdir(dirstream))
+ {
+ if(dirrecord->d_name[0] != '.')
+ continue;
+
+ if(strdiff(fontptr->n, dirrecord->d_name) <= *p_min_df)
+ {
+ sprintf(pdir, "%s/%s", dir, dirrecord->d_name);
+
+ if(scanpdir(pdir, fontptr,
+ p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+ }
+ }
+
+ closedir(dirstream);
+
+ return status;
+}
+
+/*
+ * scanpdir:
+ * Scan directory looking for plausible names and point sizes.
+ * Returns TRUE if found a more plausible candidate than previous best.
+ */
+
+bool
+scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dir;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ DIR *dirstream;
+ struct direct *dirrecord;
+ char qfamily[MAXPATHLEN];
+ char qtype[MAXPATHLEN];
+ int qpoint, qmag, df, dp, dm;
+ bool status = FALSE;
+ char family[MAXPATHLEN];
+ int point;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " scanpdir(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Split out family name, point size and magnification.
+ */
+ if(sscanf(fontptr->n, "%[^0123456789.]%d", family, &point) != 2)
+ {
+ message("Font name \"%s\" appears garbled.", fontptr->n);
+ return FALSE;
+ }
+
+ if(! (dirstream = opendir(dir)))
+ return FALSE;
+
+ while(dirrecord = readdir(dirstream))
+ {
+ if(sscanf(dirrecord->d_name, "%[^0123456789.]%d.%d%s",
+ qfamily, &qpoint, &qmag, qtype) != 4)
+ continue;
+
+ /*
+ * Is this a GF file.
+ */
+ if(use_gf && strcmp(qtype, "gf") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_gf_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_GF;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+
+ /*
+ * Is this a PXL file.
+ */
+ if(use_pxl && strcmp(qtype, "pxl") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_pxl_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_PXL;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+
+ /*
+ * Is this a PK file.
+ */
+ if(use_pk && strcmp(qtype, "pk") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_gf_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_PK;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+ }
+
+ closedir(dirstream);
+
+ return status;
+}
+
+/*
+ * strdiff:
+ * Quantify differences in font names.
+ */
+
+int
+strdiff(s1, s2)
+char *s1, *s2;
+{
+ register int diff = 0;
+
+ while(*s1 && *s2)
+ diff += abs(*s1++ - *s2++);
+ while(*s1)
+ diff += *s1++;
+ while(*s2)
+ diff += *s2++;
+
+ return diff;
+}
diff --git a/dviware/dvipage/fonts.c b/dviware/dvipage/fonts.c
new file mode 100644
index 0000000000..35b00f71fc
--- /dev/null
+++ b/dviware/dvipage/fonts.c
@@ -0,0 +1,1335 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: fonts.c,v $
+ * Revision 1.1 88/11/28 18:40:54 hunt
+ * Initial revision
+ *
+ * Stripped out of dvipage 1.4,
+ * with additions from mitdrivers from TeX 1988 distribution tape.
+ */
+
+#include <stdio.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <fcntl.h>
+#include <suntool/sunview.h>
+#include "dvipage.h"
+#include "dvi.h"
+
+forward FILE * open_font_file();
+
+forward bool init_font_file();
+forward bool read_font_char();
+
+static int nopen = 0; /* number of open FNT files */
+
+/*
+ * get_font_def:
+ * Read the font definitions as they are in the postamble of the DVI file.
+ * Returns TRUE unless the document can not be processed further.
+ */
+
+bool
+get_font_def()
+{
+ char *calloc ();
+ unsigned char byte;
+
+ while(((byte = get_unsigned(dvifp, 1)) >= FNT_DEF1) &&
+ (byte <= FNT_DEF4))
+ {
+ switch (byte)
+ {
+ case FNT_DEF1:
+ if(! read_font_def(get_unsigned(dvifp, 1)))
+ return FALSE;
+ break;
+
+ case FNT_DEF2:
+ if(! read_font_def(get_unsigned(dvifp, 2)))
+ return FALSE;
+ break;
+
+ case FNT_DEF3:
+ if(! read_font_def(get_unsigned(dvifp, 3)))
+ return FALSE;
+ break;
+
+ case FNT_DEF4:
+ if(! read_font_def(get_unsigned(dvifp, 4)))
+ return FALSE;
+ break;
+
+ default:
+ message(
+ "%s: Bad dvi file: bad font specification.", filename);
+ return FALSE;
+ }
+ }
+ if(byte != POST_POST)
+ {
+ message(
+ "%s: Bad dvi file: no postpostamble after fontdefs.", filename);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * skip_font_def:
+ * Ignore font definition when fonts have been read from the postamble.
+ */
+
+/* ARGSUSED */
+void
+skip_font_def(k)
+int k;
+{
+ int a, l;
+
+ (void)get_unsigned(dvifp, 4);
+ (void)get_unsigned(dvifp, 4);
+ (void)get_unsigned(dvifp, 4);
+ a = get_unsigned(dvifp, 1);
+ l = get_unsigned(dvifp, 1);
+ fseek(dvifp, (long)a+l, 1);
+}
+
+/*
+ * read_font_def:
+ * Reads font def, and attempts to open font file and read data.
+ * Returns TRUE unless a fatal error has occurred so that
+ * document processing cannot proceed.
+ */
+
+bool
+read_font_def(k)
+int k;
+{
+ int i;
+ struct char_entry *tcharptr;
+ FILE *font_fp;
+
+ /*
+ * Allocate and link new font entry.
+ */
+ if((fontptr =
+ (struct font_entry *)calloc(1, sizeof(struct font_entry))) == NULL)
+ {
+ message(
+ "Out of memory for font entries; try a larger machine.");
+ return FALSE;
+ }
+ fontptr->next = hfontptr;
+ hfontptr = fontptr;
+
+ /*
+ * Fill in new font entry.
+ */
+ fontptr->font_file_fd = NULL;
+ fontptr->k = k;
+ fontptr->c = get_unsigned(dvifp, 4); /* checksum */
+ fontptr->s = get_unsigned(dvifp, 4); /* space size */
+ fontptr->d = get_unsigned(dvifp, 4); /* design size */
+ fontptr->a = get_unsigned(dvifp, 1); /* area length for font name */
+ fontptr->l = get_unsigned(dvifp, 1); /* device length */
+ fread(fontptr->n, 1, fontptr->a+fontptr->l, dvifp);
+ fontptr->n[fontptr->a+fontptr->l] = '\0';
+ fontptr->font_space = fontptr->s/6; /* never used */
+ fontptr->font_gf_mag = (int)((actual_factor((int)(((float)fontptr->s/
+ (float)fontptr->d)*1000.0 + 0.5)) *
+#ifdef USEGLOBALMAG
+ actual_factor(mag) *
+#endif
+ (float)resolution) + 0.5);
+ fontptr->font_pxl_mag = (int)((actual_factor((int)(((float)fontptr->s/
+ (float)fontptr->d)*1000.0 + 0.5)) *
+#ifdef USEGLOBALMAG
+ actual_factor(mag) *
+#endif
+ (float)resolution * 5.0) + 0.5);
+
+ /*
+ * Try to find the font file to match.
+ */
+ if(! find_font_file(font_path, fontptr) ||
+ (font_fp = open_font_file(fontptr)) == NO_FILE)
+ {
+ message("Cant find or open font file \"%s\" .%dgf or .%dpxl",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ "Cant find font file %s %s .%dgf or .%dpxl\n",
+ font_path, fontptr->n,
+ fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ fontptr->font_file_fd = NO_FILE;
+ fontptr->magnification = 0;
+ fontptr->designsize = 0;
+ for(i = 0; i < NFNTCHARS; i++)
+ {
+ tcharptr = &(fontptr->ch[i]);
+ tcharptr->width = 0;
+ tcharptr->height = 0;
+ tcharptr->xOffset = 0;
+ tcharptr->yOffset = 0;
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset = NONEXISTENT;
+ tcharptr->tfmw = 0;
+ }
+
+ return TRUE;
+ }
+ else
+ return init_font_file(font_fp, fontptr);
+}
+
+/*
+ * open_font_file:
+ * Called with fontptr; opens a file for this font.
+ * May have to close another to do it.
+ * Returns a FILE * pointer, or NO_FILE.
+ */
+
+FILE *
+open_font_file(fontptr)
+struct font_entry *fontptr;
+{
+ register struct font_entry *tfontptr, *lufontptr;
+ register int used;
+
+ if(nopen >= MAXOPEN)
+ {
+ used = MAXINT;
+ lufontptr = NULL;
+ for(tfontptr = hfontptr; tfontptr; tfontptr = tfontptr->next)
+ {
+ if(tfontptr->font_file_fd == NO_FILE ||
+ tfontptr->font_file_fd == NULL ||
+ tfontptr == fontptr)
+ continue;
+
+ if(tfontptr->use_count < used)
+ {
+ used = tfontptr->use_count;
+ lufontptr = tfontptr;
+ }
+ }
+
+ if(lufontptr == NULL)
+ {
+ fprintf(stderr, "Cant have no least used font\n");
+ exit(1);
+ }
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "Closing (%x) font '%s'\n",
+ lufontptr->font_file_fd, lufontptr->name);
+ fclose(lufontptr->font_file_fd);
+ lufontptr->font_file_fd = NULL;
+ --nopen;
+ }
+
+ /*
+ * Open the file; close-on-exec.
+ */
+ if((fontptr->font_file_fd = fopen(fontptr->name, "r")) == NULL)
+ {
+ message("Cant open font file %s", fontptr->name);
+ fontptr->font_file_fd = NO_FILE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "Opened (%x) font '%s'\n",
+ fontptr->font_file_fd, fontptr->name);
+ fcntl(fileno(fontptr->font_file_fd), F_SETFD, 1);
+ nopen++;
+ }
+
+ return fontptr->font_file_fd;
+}
+
+/*
+ * close_fonts:
+ * Closes all the font files, and frees up all the memory.
+ */
+
+void
+close_fonts()
+{
+ register struct font_entry *pf, *next;
+ register struct pixrect *pr;
+ register int i;
+
+ for(pf = hfontptr; pf; pf = next)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "Freeing font %s\n", pf->name);
+
+ /*
+ * Close the file if still open.
+ */
+ if(pf->font_file_fd != NO_FILE && pf->font_file_fd != NULL)
+ {
+ fclose(pf->font_file_fd);
+ --nopen;
+ }
+ pf->font_file_fd = NULL;
+
+ /*
+ * Free the pixrects.
+ */
+ for(i = 0; i < NFNTCHARS; i++)
+ {
+ if(pf->ch[i].where.isloaded == TRUE)
+ {
+ if(pr = pf->ch[i].where.address.pixrectptr)
+ pr_destroy(pr);
+ }
+ }
+
+ /*
+ * Get the next.
+ */
+ next = pf->next;
+
+ free(pf);
+ }
+
+ hfontptr = NULL;
+ fontptr = NULL;
+
+ if(nopen != 0)
+ {
+ fprintf(stderr, "Mislaid some font files; cant happen\n");
+ exit(1);
+ }
+}
+
+/*
+ * load_char:
+ * Reads in a character from the font file.
+ * Returns TRUE unless document cannot be processed.
+ */
+
+bool
+load_char(fontptr, ptr)
+struct font_entry *fontptr;
+struct char_entry *ptr;
+{
+ register FILE *font_fp;
+
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr, "Load char %d of font %s at offset %d\n",
+ (ptr - &fontptr->ch[0]), fontptr->name,
+ ptr->where.address.fileOffset);
+
+ /*
+ * If the font file is currently unopen, then open it.
+ */
+ if((font_fp = fontptr->font_file_fd) == NULL)
+ font_fp = open_font_file(fontptr);
+
+ /*
+ * If the font file is unavailable, forget it.
+ */
+ if(font_fp == NO_FILE)
+ {
+ ptr->where.isloaded = TRUE;
+ return TRUE;
+ }
+
+ /*
+ * Read the font character.
+ */
+ return read_font_char(font_fp, fontptr, ptr);
+}
+
+/*
+ * Generic Font reading functions.
+ * ==============================
+ */
+
+forward bool init_gf_font_file();
+forward bool init_pxl_font_file();
+forward bool init_pk_font_file();
+forward bool read_gf_font_char();
+forward bool read_pxl_font_char();
+forward bool read_pk_font_char();
+
+/*
+ * init_font_file:
+ * Reads general data from font file.
+ * Returns TRUE unless processing cannot continue.
+ */
+
+bool
+init_font_file(font_fp, fontptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+{
+ switch(fontptr->type)
+ {
+ case TYPE_GF:
+ return init_gf_font_file(font_fp, fontptr);
+
+ case TYPE_PXL:
+ return init_pxl_font_file(font_fp, fontptr);
+
+ case TYPE_PK:
+ return init_pk_font_file(font_fp, fontptr);
+
+ default:
+ fprintf(stderr, "Unknown type of font file; cant happen\n");
+ exit(1);
+ }
+}
+
+/*
+ * read_font_char:
+ * Reads character from font file.
+ * Returns TRUE unless document cannot be processed.
+ */
+
+bool
+read_font_char(font_fp, fontptr, ptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+struct char_entry *ptr;
+{
+ switch(fontptr->type)
+ {
+ case TYPE_GF:
+ return read_gf_font_char(font_fp, fontptr, ptr);
+
+ case TYPE_PXL:
+ return read_pxl_font_char(font_fp, fontptr, ptr);
+
+ case TYPE_PK:
+ return read_pk_font_char(font_fp, fontptr, ptr);
+
+ default:
+ fprintf(stderr, "Unknown type of font file; cant happen\n");
+ exit(1);
+ }
+}
+
+/*
+ * GF font reading functions.
+ * ==========================
+ */
+
+#define false 0
+#define true 1
+
+/* The following macros describe gf file format */
+
+#define paint_0 0
+#define last_paint 63
+#define paint1 64
+#define paint2 65
+#define paint3 66
+#define boc 67
+#define boc1 68
+#define eoc 69
+#define skip0 70
+#define skip1 71
+#define skip2 72
+#define skip3 73
+#define new_row_0 74
+#define last_new_row 238
+#define xxx1 239
+#define xxx2 240
+#define xxx3 241
+#define xxx4 242
+#define yyy 243
+#define no_op 244
+#define char_loc 245
+#define char_loc0 246
+#define pre 247
+#define post 248
+#define postpost 249
+#define undefined_cases 250: case 251: case 252: case 253: case 254: case 255
+#define gf_version 131
+
+/*
+ * init_gf_font_file:
+ * Reads font data from file.
+ * If the file is unavailable, its fp is set to NO_FILE.
+ * Returns TRUE unless processing cannot continue.
+ */
+
+bool
+init_gf_font_file(font_fp, fontptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+{
+ register int b, c;
+ register struct char_entry *tcharptr;
+
+ long checksum; /* should match TFM file and DVI file */
+ long hppp, vppp; /* horizontal and vertical pixels/point scaled
+ * 1<<16 */
+ int font_min_m, font_max_m, font_min_n, font_max_n;
+ int char_wd; /* character width in pixels, rounded if
+ * necessary */
+
+ /*
+ * Seek to the postamble part of the GF file.
+ */
+ fseek(font_fp, -5L, 2); /* skip four 223's */
+ do
+ {
+ c = get_unsigned(font_fp, 1);
+ fseek(font_fp, -2L, 1);
+ } while(c == 223);
+
+ if(c != gf_version)
+ {
+ message("Bad GF font version number (%d) in %s.",
+ c, fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ }
+
+ fseek(font_fp, -3L, 1); /* back up to the pointer */
+ if(fseek(font_fp, (long)get_unsigned(font_fp, 4), 0) < 0 ||
+ get_unsigned(font_fp, 1) != post)
+ {
+ message("Bad GF font file format in %s.", fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ }
+
+ (void)get_unsigned(font_fp, 4); /* ignore back pointer to font-wide xxx
+ * commands */
+ fontptr->designsize = get_unsigned(font_fp, 4);
+ checksum = get_unsigned(font_fp, 4);
+ hppp = get_unsigned(font_fp, 4);
+ vppp = get_unsigned(font_fp, 4);
+ font_min_m = get_unsigned(font_fp, 4);
+ font_max_m = get_unsigned(font_fp, 4);
+ font_min_n = get_unsigned(font_fp, 4);
+ font_max_n = get_unsigned(font_fp, 4);
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "Initialising font %s\n", fontptr->name);
+
+ for(tcharptr = &fontptr->ch[0]; tcharptr < &fontptr->ch[NFNTCHARS];
+ tcharptr++)
+ {
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset = -1;
+ tcharptr->tfmw = 0;
+ }
+ for(;;)
+ {
+ b = get_unsigned(font_fp, 1);
+ c = get_unsigned(font_fp, 1);
+
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr, "Finding char %d type %d\n", c, b);
+
+ if(b == char_loc0)
+ char_wd = get_unsigned(font_fp, 1);
+ else if(b == char_loc)
+ {
+ char_wd = (get_unsigned(font_fp, 4) + 0100000) >> 16;
+ get_unsigned(font_fp, 4); /* skip dy */
+ }
+ else
+ break;
+
+ tcharptr = &(fontptr->ch[c % NFNTCHARS]);
+ tcharptr->tfmw =
+ ((float)get_unsigned(font_fp, 4) * (float)fontptr->s) /
+ (float)(1 << 20);
+ tcharptr->where.address.fileOffset = get_unsigned(font_fp, 4);
+ }
+
+ if((fontptr->c != 0) && (checksum != 0) && (fontptr->c != checksum))
+ message("Bad font checksum %d != %d, font %s.",
+ checksum, fontptr->c, fontptr->name);
+
+ /*
+ * Return leaving font file open for use.
+ */
+ return TRUE;
+}
+
+/*
+ * read_font_char:
+ * Reads character from font file.
+ * Returns TRUE unless document cannot be processed.
+ */
+
+bool
+read_gf_font_char(font_fp, fontptr, ptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+register struct char_entry *ptr;
+{
+ register int i, b, c;
+ register int x, y;
+ register struct pixrect *pr;
+ int min_m, max_m, min_n, max_n;
+ int bytes, lines, paint_switch;
+ long backpointer;
+ long charfam;
+
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr, "Reading char %d of font %s\n",
+ (ptr - &fontptr->ch[0]), fontptr->name);
+
+ /*
+ * Seek to start of char.
+ */
+ fseek(font_fp, (long)ptr->where.address.fileOffset, 0);
+
+ /*
+ * Sync with char
+ */
+ do
+ {
+ switch(i = get_unsigned(font_fp, 1))
+ {
+ case yyy:
+ (void)get_unsigned(font_fp, 1);
+ /* FALLTHROUGH */
+ case paint3:
+ case skip3:
+ (void)get_unsigned(font_fp, 1);
+ /* FALLTHROUGH */
+ case paint2:
+ case skip2:
+ (void)get_unsigned(font_fp, 1);
+ /* FALLTHROUGH */
+ case paint1:
+ case skip1:
+ (void)get_unsigned(font_fp, 1);
+ break;
+
+ case boc:
+ case boc1:
+ break;
+
+ case pre:
+ if((c = get_unsigned(font_fp, 1)) != gf_version)
+ {
+ message(
+ "Bad GF font version number (%d); font %s.",
+ c, fontptr->name);
+ return TRUE;
+ }
+ fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
+ break;
+
+ case xxx1:
+ fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
+ break;
+
+ case xxx2:
+ fseek(font_fp, (long)get_unsigned(font_fp, 2), 1);
+ break;
+
+ case xxx3:
+ fseek(font_fp, (long)get_unsigned(font_fp, 3), 1);
+ break;
+
+ case xxx4:
+ fseek(font_fp, (long)get_unsigned(font_fp, 4), 1);
+ break;
+
+ case post:
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "gettochar: found POST\n");
+ return TRUE;
+
+ case char_loc:
+ case char_loc0:
+ case postpost:
+ case undefined_cases:
+ message(
+ "Bad GF font file format (%d); font %s.",
+ i, fontptr->name);
+ return TRUE;
+
+ default: /* do nothing */ ;
+ break;
+ }
+
+ if(i != boc && i != boc1 &&
+ verbose & DEBUG_FONTS)
+ fprintf(stderr, "gettochar iterates with %d\n", i);
+ }
+ while(i != boc && i != boc1);
+
+ /*
+ * Read character code and raster sizes.
+ */
+ switch(i)
+ {
+ case boc:
+ c = get_unsigned(font_fp, 4);
+ backpointer = get_unsigned(font_fp, 4);
+ min_m = get_unsigned(font_fp, 4);
+ max_m = get_unsigned(font_fp, 4);
+ min_n = get_unsigned(font_fp, 4);
+ max_n = get_unsigned(font_fp, 4);
+ charfam = c < 0 ? -((-c) >> 8) : c >> 8;
+ break;
+
+ case boc1:
+ c = get_unsigned(font_fp, 1);
+ x = get_unsigned(font_fp, 1); /* del_m */
+ max_m = get_unsigned(font_fp, 1);
+ min_m = max_m - x;
+ x = get_unsigned(font_fp, 1); /* del_n */
+ max_n = get_unsigned(font_fp, 1);
+ min_n = max_n - x;
+ break;
+
+ default:
+ fprintf(stderr,
+ "Font BOC code has corrupted in memory; cant happen.\n");
+ exit(1);
+ }
+ ptr->width = max_m - min_m + 1;
+ ptr->height = max_n - min_n + 1;
+ ptr->xOffset = -min_m;
+ ptr->yOffset = max_n;
+
+ /*
+ * Create Pixrect for char.
+ * Clear to zero.
+ */
+ pr = mem_create(ptr->width, ptr->height, 1);
+ ptr->where.address.pixrectptr = pr;
+ pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(0),
+ NULL, 0, 0);
+#ifdef NEVER
+ pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(1),
+ NULL, 0, 0);
+ pr_rop(pr, 1, 1, ptr->width-2, ptr->height-2, PIX_SRC | PIX_COLOR(0),
+ NULL, 0, 0);
+#endif NEVER
+ x = 0;
+ y = 0;
+ paint_switch = 0;
+
+ for(;;)
+ {
+ switch(b = get_unsigned(font_fp, 1))
+ {
+ case paint1:
+ bytes = get_unsigned(font_fp, 1);
+ goto paint;
+
+ case paint2:
+ bytes = get_unsigned(font_fp, 2);
+ goto paint;
+
+ case paint3:
+ bytes = get_unsigned(font_fp, 3);
+ goto paint;
+
+ case skip0:
+ lines = 0;
+ goto skip;
+
+ case skip1:
+ lines = get_unsigned(font_fp, 1);
+ goto skip;
+
+ case skip2:
+ lines = get_unsigned(font_fp, 2);
+ goto skip;
+
+ case skip3:
+ lines = get_unsigned(font_fp, 3);
+ goto skip;
+
+ case xxx1:
+ fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
+ continue;
+
+ case xxx2:
+ fseek(font_fp, (long)get_unsigned(font_fp, 2), 1);
+ continue;
+
+ case xxx3:
+ fseek(font_fp, (long)get_unsigned(font_fp, 3), 1);
+ continue;
+
+ case xxx4:
+ fseek(font_fp, (long)get_unsigned(font_fp, 4), 1);
+ continue;
+
+ case yyy:
+ get_unsigned(font_fp, 4);
+ continue;
+
+ case no_op:
+ continue;
+
+ case eoc:
+ ptr->where.isloaded = TRUE;
+ return TRUE;
+
+ default:
+ if(b >= paint_0 && b <= last_paint)
+ {
+ bytes = b - paint_0;
+
+paint:; /*
+ * Paint the specified number of bytes black
+ * or white.
+ * Toggle the paint colour.
+ * Advance the current position.
+ */
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr,
+ " Paint %d line %d, %d for %d\n", paint_switch, y, x, bytes);
+ if(bytes > 0 && paint_switch)
+ pr_rop(pr, x, y, bytes, 1,
+ PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
+ paint_switch = ! paint_switch;
+ x += bytes;
+ continue;
+ }
+ else if(b >= new_row_0 && b <= last_new_row)
+ {
+ /*
+ * Special shortcut; skip to new row,
+ * and paint some white bytes.
+ * Leave switch ready for next black bytes.
+ */
+ y++;
+ x = b - new_row_0;
+ paint_switch = 1;
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr,
+ " Jump to line %d, paint white to %d\n", y, x);
+ continue;
+ }
+ else
+ {
+ message(
+ "Bad GF file format code %d; char %d font %s.",
+ b, (ptr - &fontptr->ch[0]), fontptr->name);
+ return TRUE;
+ }
+
+skip:; /*
+ * Skip to the start of the line.th next line.
+ * Start at beginnning of line, ready to paint white.
+ */
+ y += lines + 1;
+ x = 0;
+ paint_switch = 0;
+ if(verbose & DEBUG_CHARS)
+ fprintf(stderr,
+ " Jump to line %d at start\n", y);
+ continue;
+ }
+ }
+}
+
+/*
+ * PXL font reading functions.
+ * ==========================
+ */
+
+#define NPXLCHARS 128
+
+/*
+ * init_pxl_font_file:
+ * Reads font data from file.
+ * If the file is unavailable, its fp is set to NO_FILE.
+ * Returns TRUE unless processing cannot continue.
+ */
+
+bool
+init_pxl_font_file(font_fp, fontptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+{
+ int t, i;
+ register struct char_entry *tcharptr;
+
+ /*
+ * Read the PXL file
+ */
+ if((t = get_unsigned(font_fp, 4)) != PXLID)
+ {
+ message("Bad font file version %d; font %s.",
+ t, fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ }
+ fseek(font_fp, -20L, 2);
+ t = get_unsigned(font_fp, 4);
+ if((fontptr->c != 0) && (t != 0) && (fontptr->c != t))
+ message("Bad font checksum %d != %d; font %s.",
+ t, fontptr->c, fontptr->name);
+
+ fontptr->magnification = get_unsigned(font_fp, 4);
+ fontptr->designsize = get_unsigned(font_fp, 4);
+
+ fseek(font_fp, (long)get_unsigned(font_fp, 4) * 4, 0);
+
+ for(i = 0; i < NPXLCHARS; i++)
+ {
+ tcharptr = &(fontptr->ch[i]);
+ tcharptr->width = get_unsigned(font_fp, 2);
+ tcharptr->height = get_unsigned(font_fp, 2);
+ tcharptr->xOffset= get_signed(font_fp, 2);
+ tcharptr->yOffset = get_signed(font_fp, 2);
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset =
+ get_unsigned(font_fp, 4) * 4;
+ tcharptr->tfmw =
+ ((float)get_unsigned(font_fp, 4)*(float)fontptr->s) /
+ (float)(1<<20);
+ }
+
+ /*
+ * Return leaving font file open for access.
+ */
+ return TRUE;
+}
+
+static u_char bit_mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+/*
+ * read_font_char:
+ * Reads character from font file.
+ * Returns TRUE unless document cannot be processed.
+ */
+
+/* ARGSUSED */
+bool
+read_pxl_font_char(font_fp, fontptr, ptr)
+FILE *font_fp;
+struct font_entry *fontptr;
+register struct char_entry *ptr;
+{
+ register struct pixrect *pr;
+ register int i, j, nints, nbytes, bp;
+ u_int buf;
+
+ /*
+ * Seek to start of char.
+ */
+ fseek(font_fp, (long)ptr->where.address.fileOffset, 0);
+
+ /*
+ * Create a mem pixrect.
+ * Read the char.
+ */
+ pr = mem_create(ptr->width, ptr->height, 1);
+ nints = (ptr->width + 31) >> 5;
+ pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_CLR, NULL, 0, 0);
+ bp = 0;
+ for (i=0; i < ptr->height; i++) {
+ nbytes = nints * 4;
+ for (j=0; j<ptr->width; j++) {
+ if(!(bp & 7)) {
+ buf = getc(font_fp);
+ nbytes--;
+ }
+ pr_put(pr, j, i, (buf & bit_mask[bp&7])?1:0);
+ bp++;
+ }
+ while (nbytes--)
+ getc(font_fp);
+ bp = 0;
+ }
+
+ ptr->where.address.pixrectptr = pr;
+ ptr->where.isloaded = TRUE;
+
+ return TRUE;
+}
+
+/*
+ * PK font reading functions
+ */
+
+/* ID byte value at the beginning of PK files */
+#define PK_ID 89
+
+/* PK op codes */
+#define PK_XXX1 240
+#define PK_XXX2 241
+#define PK_XXX3 242
+#define PK_XXX4 243
+#define PK_YYY 244
+#define PK_POST 245
+#define PK_NOP 246
+#define PK_PRE 247
+
+#define PK_REPEAT 0xe /* Repeat last row - repeat count in next nibble */
+#define PK_AGAIN 0xf /* Repeat only once */
+#define PK_LARGE 0x0 /* Long run vaule coming up */
+
+
+/*
+ * the macros that read pk values need these variables.
+ */
+static u_short _nyb_buf,
+ _nyb_flag,
+ _pk_repeat;
+
+
+/*
+ * get the next nybble of the file. This macro requires
+ * that 2 integers named _nyb_buf and _nyb_flag be allocated elsewhere in
+ * the program. In addition, _nyb_flag must be initialized to 0.
+ */
+#define GET_NYB ((_nyb_flag ^= 1) ? \
+ ((_nyb_buf = (unsigned)getc(font_fp)) >> 4) : \
+ (_nyb_buf & 0xf))
+
+/*
+ * The quantity to be packed into nybbles may require an odd number of
+ * nybbles which will cause the nybble fetching macro to get out of
+ * sync. The following macro ``clears'' the state of the nybble fetching
+ * routine and should be executed whenever transitioning from nybble to
+ * byte (or other) quantities.
+ */
+#define CLEAR_NYB _nyb_flag = 0;
+
+/*
+ * this macro gets a PK ``packed number'' from fp and puts it into x.
+ * It is an adaption of an algorithm presented in Tugboat V. 6, No. 3.
+ */
+#define GET_PACKED(x) x = get_packed(font_fp, dyn_f)
+
+static u_int
+get_packed(font_fp, dyn_f)
+ register FILE *font_fp;
+ register u_int dyn_f;
+{
+ register int i, j;
+
+ i = GET_NYB;
+ if (i == 0) {
+ /*
+ * we have an arbitrarily long number. scan to
+ * find the first non-zero nybble which is the
+ * count of the nybbles in this value.
+ */
+ do {
+ j = GET_NYB;
+ i++;
+ } while (j == 0);
+
+ while (--i >= 0)
+ j = (j << 4) + GET_NYB;
+
+ return (j + 193 - 15 * dyn_f);
+ } else if (i <= dyn_f) {
+ /* this nybble is the number we want. */
+ return (i);
+ } else if (i < 14) {
+ return (i + 15 * (i - dyn_f - 1) + GET_NYB);
+ } else if (i == 14) {
+ _pk_repeat = get_packed (font_fp, dyn_f);
+ } else {
+ _pk_repeat = 1;
+ }
+ return (i);
+}
+
+
+bool
+init_pk_font_file (font_fp, fontptr)
+ register FILE *font_fp;
+ register struct font_entry *fontptr;
+{
+ register unsigned c, cc;
+ long pl, addr;
+ register u_int i;
+ u_int hppp, vppp;
+ int checksum;
+ u_int tfmw;
+ double cscale;
+
+ fseek (font_fp, 0L, 0); /* make sure at the beginning of pk file */
+
+ if (get_unsigned(font_fp, 1) != PK_PRE) {
+ message("pk font file %s doesn't start with PRE\n",
+ fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ }
+
+ if (get_unsigned(font_fp, 1) != PK_ID) {
+ message("pk font file %s wrong version\n",
+ fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ }
+
+ fseek (font_fp, (long) get_unsigned(font_fp, 1), 1); /* skip comment */
+ fontptr->designsize = get_unsigned(font_fp, 4); /* ds[4] */
+ checksum = get_unsigned(font_fp, 4); /* checksum[4] */
+ hppp = get_unsigned(font_fp, 4); /* hppp[4] */
+ vppp = get_unsigned(font_fp, 4); /* vppp[4] */
+ cscale = (double) fontptr->s / (double)(1 << 20);
+
+ while ((c = get_unsigned(font_fp, 1)) != EOF) {
+ if (c >= PK_XXX1) { /* commands are just skipped */
+ switch (c) {
+ case PK_XXX1: /* pk_xxx1 k[1] x[k] */
+ fseek (font_fp, (long)get_unsigned(font_fp,1), 1);
+ break;
+ case PK_XXX2: /* pk_xxx2 k[2] x[k] */
+ fseek (font_fp, (long)get_unsigned(font_fp,2), 1);
+ break;
+ case PK_XXX3: /* pk_xxx3 k[3] x[k] */
+ fseek (font_fp, (long)get_unsigned(font_fp,3), 1);
+ break;
+ case PK_XXX4: /* pk_xxx4 k[4] x[4] */
+ fseek (font_fp, (long)get_signed(font_fp,4), 1);
+ break;
+ case PK_YYY: /* pk_yyy y[4] */
+ (void) get_unsigned(font_fp, 4);
+ break;
+ case PK_POST:
+ return TRUE;
+ case PK_PRE:
+ message("pk font file %s has extra PRE\n",
+ fontptr->name);
+ fclose(fontptr->font_file_fd);
+ fontptr->font_file_fd = NO_FILE;
+ return TRUE;
+ default: /* do nothing */ ;
+ }
+ } else { /* flag byte */
+ switch (c & 0x07) { /* check flag byte */
+ case 0:/* short form */
+ case 1:
+ case 2:
+ case 3:
+ /* length */
+ pl = (long) get_unsigned(font_fp, 1)
+ + (long) ((c & 0x03) << 8);
+ cc = get_unsigned(font_fp,1); /* char. code */
+ tfmw = get_unsigned(font_fp,3); /* tfm width */
+ (void) get_unsigned(font_fp,1); /* x-escapement */
+ fontptr->ch[cc].width = get_unsigned(font_fp, 1);
+ fontptr->ch[cc].height = get_unsigned(font_fp, 1);
+ fontptr->ch[cc].xOffset = get_signed(font_fp, 1);
+ fontptr->ch[cc].yOffset = get_signed(font_fp, 1);
+ addr = ftell (font_fp);
+ pl -= 8;
+ break;
+
+ case 4:/* extended short form */
+ case 5:
+ case 6:
+ pl = (long) get_unsigned(font_fp, 2)
+ + (long) ((c & 0x03) << 16);
+ cc = get_unsigned(font_fp,1); /* char. code */
+ tfmw = get_unsigned(font_fp,3); /* tfm width */
+ (void) get_unsigned(font_fp,2); /* x-escapement */
+ fontptr->ch[cc].width = get_unsigned(font_fp, 2);
+ fontptr->ch[cc].height = get_unsigned(font_fp, 2);
+ fontptr->ch[cc].xOffset = get_signed(font_fp, 2);
+ fontptr->ch[cc].yOffset = get_signed(font_fp, 2);
+ addr = ftell (font_fp);
+ pl -= 13;
+ break;
+
+ case 7:/* long form */
+ pl = get_unsigned(font_fp,4);
+ cc = get_unsigned(font_fp,4); /* char. code */
+ tfmw = get_unsigned(font_fp,4);
+ (void) get_unsigned(font_fp,4); /* x-escapement */
+ fontptr->ch[cc].width = get_unsigned(font_fp, 4);
+ fontptr->ch[cc].height = get_unsigned(font_fp, 4);
+ fontptr->ch[cc].xOffset = get_signed(font_fp, 4);
+ fontptr->ch[cc].yOffset = get_signed(font_fp, 4);
+ addr = ftell (font_fp);
+ pl -= 24;
+ break;
+ }
+ fontptr->ch[cc].tfmw = (int)(((double)tfmw * cscale) + 0.5);
+ fontptr->ch[cc].where.isloaded = 0;
+ fontptr->ch[cc].where.flags = c;
+ fontptr->ch[cc].where.address.fileOffset = addr;;
+ fseek (font_fp, pl, 1); /* skip until next flag byte */
+ }
+ }
+ if((fontptr->c != 0) && (checksum != 0) && (fontptr->c != checksum))
+ message("Bad font checksum %d != %d; font %s.",
+ checksum, fontptr->c, fontptr->name);
+ return TRUE;
+}
+
+
+/*
+ * load a PK character into memory.
+ */
+bool
+read_pk_font_char(font_fp, fontptr, ptr)
+ register FILE *font_fp;
+ register struct font_entry *fontptr;
+ register struct char_entry *ptr;
+{
+ register struct pixrect *pr;
+ int cw; /* character width */
+ int ch; /* character height */
+ u_int dyn_f; /* dynamic factor, part of a PK word. */
+ register int i, j;
+ register int black, bits, bp, rc;
+ int rowp;
+
+ if (ptr->width == 0 || ptr->height == 0) {
+ ptr->where.address.pixrectptr = (struct pixrect *) 0;
+ return;
+ }
+ fseek(font_fp, (long)ptr->where.address.fileOffset, 0);
+
+ pr = mem_create(ptr->width, ptr->height, 1);
+ ptr->where.address.pixrectptr = pr;
+
+ cw = ptr->width; ch = ptr->height;
+ pr_rop(pr, 0, 0, cw, ch, PIX_CLR, NULL, 0, 0);
+
+ /*
+ * what remains is the data for the image. It can be packaged
+ * either as a run-encoding where successive values are the
+ * number of adjacent pixels to paint in the opposite color of
+ * the previous painting, or simply as a bitmap with no padding
+ * except (possibly) for the very last nybble to round up to a
+ * byte value.
+ *
+ * the data for the character is stored in successive bits with
+ * each new horizontal row at a long boundary. See the PXL
+ * file format.
+ */
+
+ /*
+ * grab the dyn_f out of the flag for this character.
+ */
+ dyn_f = (ptr->where.flags >> 4) & 0xf;
+ /*
+ * the data returned by calloc is zeroed; we depend on that
+ * because we only turn on bits that are supposed to be
+ * black.
+ */
+ if (dyn_f == 14) {
+ /*
+ * we have a bitmap rather than a run-encoding.
+ */
+ u_int buf;
+ bp = 0;
+ for (i=0; i < ch; i++) {
+ for (j=0; j<cw; j++) {
+ if(!(bp & 7))
+ buf = getc(font_fp);
+ pr_put(pr, j, i, (buf & bit_mask[bp&7])?1:0);
+ bp++;
+ }
+ }
+ } else {
+ bp = _pk_repeat = rc = rowp = 0;
+ black = ptr->where.flags & (1 << 3);
+ bits = cw * ch;
+ CLEAR_NYB;
+ while (bp < bits) {
+ GET_PACKED(j);
+
+ if (_pk_repeat != 0) {
+ rc = _pk_repeat;
+ rowp = bp / cw;
+ _pk_repeat = 0;
+ continue;
+ }
+
+ /*
+ * we have a run count in j.
+ */
+ if (black) {
+ register int k,l,m;
+
+ l = bp / cw; /* starting row */
+ m = (bp + j) / cw; /* ending row */
+ k = bp % cw; /* start bit offset */
+ i = (bp + j) % cw; /* ending bit offset */
+
+ if (j <= cw && (k < i || i == 0)) {
+ /* we're changing less than a row */
+ pr_rop(pr, k, l, j, 1, PIX_SET,
+ NULL, 0, 0);
+ } else {
+ /* fill any fragment in the current row */
+ pr_rop(pr, k, l, cw-k, 1, PIX_SET,
+ NULL, 0, 0);
+
+ /* fill some number of full rows */
+ pr_rop(pr, 0, l+1, cw, (j-(cw-k))/cw,
+ PIX_SET, NULL, 0, 0);
+
+ /* fill any fragment in the last row */
+ if (i)
+ pr_rop(pr, 0, m, i, 1, PIX_SET,
+ NULL, 0, 0);
+ }
+ }
+ bp += j;
+
+ /*
+ * if there's a repeat count and we hit the end of
+ * a row, do the copy.
+ */
+ if (rc && (bp - (rowp*cw)) >= cw) {
+ i = rowp+1;
+ j = rowp+1+rc;
+ if ((i*cw) != bp) {
+ pr_rop(pr, 0, j, cw, 1, PIX_SRC,
+ pr, 0, i);
+ }
+ j = rc;
+ while(j--) {
+ pr_rop(pr, 0, i, cw, 1, PIX_SRC,
+ pr, 0, rowp);
+ i++;
+ }
+ bp += rc * cw;
+ rc = 0;
+ }
+ black = !black;
+ }
+ }
+
+ ptr->where.isloaded = TRUE;
+ return TRUE;
+}
diff --git a/dviware/dvipage/makefile b/dviware/dvipage/makefile
new file mode 100644
index 0000000000..473c0ba528
--- /dev/null
+++ b/dviware/dvipage/makefile
@@ -0,0 +1,97 @@
+#
+# dvipage: DVI Previewer Program for Suns
+#
+# Neil Hunt (hunt@spar.slb.com)
+#
+# This program is based, in part, upon the program dvisun,
+# distributed by the UnixTeX group, extensively modified by
+# Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+# of Schlumberger Technologies, Inc.
+#
+# From the dvisun manual page entry:
+# Mark Senn wrote the early versions of [dvisun] for the
+# BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
+# Furuta, James Schaad and Robert Wells improved it. Norm
+# Hutchinson ported the program to the Sun. Further bug fixes
+# by Rafael Bracho at Schlumberger.
+#
+# Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+# Anyone can use this software in any manner they choose,
+# including modification and redistribution, provided they make
+# no charge for it, and these conditions remain unchanged.
+#
+# This program is distributed as is, with all faults (if any), and
+# without any warranty. No author or distributor accepts responsibility
+# to anyone for the consequences of using it, or for whether it serves any
+# particular purpose at all, or any other reason.
+#
+# HISTORY
+#
+# 14/2/92: Makefile hacked, especially to add defines. d.love@dl.ac.uk
+#
+# $Log: Makefile,v $
+# Revision 1.3 88/12/15 18:20:02 hunt
+# Version 3.0. Split into more files, fixed for Sun4, reads GF fonts.
+#
+# Revision 1.2 88/11/26 11:12:51 hunt
+# Added alternate font file location for sun4 machines at Spar.
+#
+# Revision 1.1 88/08/30 09:05:42 hunt
+# Initial revision
+#
+# 12 April 1988 - Neil Hunt
+# Version 2.0 released for use.
+#
+# Earlier history unavailable.
+#
+
+# where to find the pixel files (only looking for .pks here)
+FONT_AREA=\"/usr/local/lib/tex/fonts/pkb:/usr/local/lib/tex/fonts/pk\"
+
+BINDIR = /usr/local/bin # directory for executable
+
+MANDIR = /usr/man/manl # directory for local man pages
+
+MANEXT = l # extension for local man pages
+
+DEBUG = #-g
+
+# the definition of _TYPES_ below seems to have become necessary with
+# sunos4.1
+
+# For sun3.
+#CFLAGS = -O -D_TYPES_ -DFONT_AREA=$(FONT_AREA) $(DEBUG)
+
+# For sun3, f68881
+CFLAGS = -O -f68881 -D_TYPES_ -DFONT_AREA=$(FONT_AREA) $(DEBUG)
+
+# For Sun4.
+#CFLAGS = -O -D_TYPES_ -DFONT_AREA=$(FONT_AREA) $(DEBUG)
+
+# Sun libraries.
+L = -lsuntool -lsunwindow -lpixrect -lm
+
+dvipage: dvipage.o sample.o fonts.o findfile.o message.o utils.o args.o
+ ${CC} $(DEBUG) -o dvipage \
+ dvipage.o sample.o fonts.o findfile.o message.o utils.o args.o $L
+
+dvipage.o: dvipage.c dvi.h dvipage.h
+
+sample.o: sample.c dvipage.h
+
+fonts.o: fonts.c dvipage.h dvi.h
+
+findfile.o: findfile.c dvipage.h
+
+message.o: message.c dvipage.h
+
+utils.o: utils.c dvipage.h
+
+args.o: args.c dvipage.h
+
+install: dvipage dvipage.1
+ install dvipage $(BINDIR)
+ install dvipage.1 $(MANDIR)/dvipage.$(MANEXT)
+
+clean:
+ rm -f dvipage *.o core *~ *%
diff --git a/dviware/dvipage/makefonts b/dviware/dvipage/makefonts
new file mode 100644
index 0000000000..e5ec10c643
--- /dev/null
+++ b/dviware/dvipage/makefonts
@@ -0,0 +1,24 @@
+#! /bin/csh
+setenv NEW_DIR "$PWD"
+pushd /usr/lib/publisher
+foreach font_set ( `ls -d *pixels` )
+ pushd $font_set
+ foreach resolution_set ( screen xerox300 canon300 )
+ if ( -d $resolution_set ) then
+ pushd $resolution_set
+ foreach resolution ( `ls -d dpi*` )
+ setenv DPI "`( echo $resolution | cut -c4- )`pk"
+ pushd $resolution
+ foreach font ( `ls *.pk` )
+ setenv FONT_NAME "`basename $font pk`"
+ setenv NEW_NAME "$NEW_DIR/$FONT_NAME$DPI"
+ if ( -e $NEW_NAME == 0 ) ln $font $NEW_NAME
+ end
+ popd
+ end
+ popd
+ endif
+ end
+ popd
+end
+popd
diff --git a/dviware/dvipage/message.c b/dviware/dvipage/message.c
new file mode 100644
index 0000000000..343bfbf145
--- /dev/null
+++ b/dviware/dvipage/message.c
@@ -0,0 +1,659 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: message.c,v $
+ * Revision 1.2 88/12/07 18:48:27 hunt
+ * Fixed typo left from previous mods.
+ *
+ * Revision 1.1 88/11/28 18:41:13 hunt
+ * Initial revision
+ *
+ * Stripped from dvipage.c 1.4.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <varargs.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include <suntool/canvas.h>
+#include <suntool/panel.h>
+#include "dvipage.h"
+
+/*
+ * Forward functions.
+ * =================
+ */
+
+forward void mess_done();
+
+/*
+ * These are here rather than in dvipage.h because
+ * they cause problems unless a whole raft of other includes
+ * go in front.
+ */
+extern Frame disp_frame;
+extern Canvas disp_canvas;
+
+Frame mess_frame; /* Frame for message window. */
+Panel mess_panel; /* Panel for message window. */
+
+static int errors_displayed = 0;
+
+/*
+ * message:
+ * Pops up a message window (if one is not already displayed)
+ * Formats a message (using fmt and args) and displays it into the window.
+ * Repeated calls to this function result in multiple lines of messages.
+ */
+
+void
+message(fmt, va_alist)
+char *fmt;
+va_dcl
+{
+ va_list args;
+ static char string[100];
+
+ if(silent)
+ return;
+
+ va_start(args);
+ vsprintf(string, fmt, args);
+ va_end(args);
+
+ /*
+ * If there are no errors displayed,
+ * then build a window..
+ */
+ if(errors_displayed == 0)
+ {
+ mess_frame = window_create(disp_frame, FRAME,
+ FRAME_NO_CONFIRM, TRUE,
+ 0);
+ mess_panel = window_create(mess_frame, PANEL,
+ 0);
+ panel_create_item(mess_panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE,
+ panel_button_image(mess_panel, "OK", 0, 0),
+ PANEL_ITEM_X, ATTR_COL(1),
+ PANEL_ITEM_Y, ATTR_ROW(0),
+ PANEL_NOTIFY_PROC, mess_done,
+ 0);
+ }
+ else
+ window_set(mess_frame,
+ WIN_SHOW, FALSE,
+ 0);
+
+ panel_create_item(mess_panel, PANEL_MESSAGE,
+ PANEL_LABEL_STRING, string,
+ PANEL_ITEM_X, ATTR_COL(1),
+ PANEL_ITEM_Y, ATTR_ROW(++errors_displayed)+5,
+ 0);
+
+ window_fit(mess_panel);
+ window_fit(mess_frame);
+
+ window_set(mess_frame,
+ WIN_SHOW, TRUE,
+ 0);
+}
+
+/*
+ * mess_done:
+ * This function is called when the OK button is pressed on the message
+ * window; the window is closed, and displayed messages are cleared.
+ */
+
+void
+mess_done()
+{
+ window_destroy(mess_frame);
+
+ errors_displayed = 0;
+}
+
+/*
+ * Pop up prompts:
+ * ==============
+ */
+
+static bool prompt_return_value = TRUE;
+
+static Pixrect *ok_button = NULL;
+static Pixrect *abort_button = NULL;
+
+static Panel_setting prompt_ok_proc();
+static Panel_setting prompt_abort_proc();
+static Panel_setting prompt_notify_proc();
+
+/*
+ * strings_prompt: eg.
+ * strings_prompt(1152/2, 900/2,
+ * "Directory: ", &dir[0],
+ * "Filename: ", &fname[0],
+ * 0);
+ */
+
+#define MAX_STRING_ITEMS 10
+
+bool
+strings_prompt(x, y, va_alist)
+int x, y;
+va_dcl
+{
+ Frame frame;
+ Panel panel;
+ Panel_item string_item[MAX_STRING_ITEMS], ok_item, abort_item;
+ Event *event;
+ int w, h;
+ int i;
+ char *prompt;
+ char *value;
+ va_list ap;
+
+ /*
+ * Create the frame and panel.
+ */
+ frame = window_create(NULL, FRAME,
+ FRAME_SHOW_LABEL, FALSE,
+ FRAME_NO_CONFIRM, TRUE,
+ 0);
+
+ panel = window_create(frame, PANEL,
+ PANEL_ITEM_X_GAP, 1000, /* Enforces vertical layout */
+ 0);
+
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_STRING_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, char *)) == NULL)
+ break;
+
+ /*
+ * Create a text item for the string.
+ */
+ string_item[i] = panel_create_item(panel, PANEL_TEXT,
+ PANEL_LABEL_STRING, prompt,
+ PANEL_VALUE, value,
+ PANEL_VALUE_DISPLAY_LENGTH, 20,
+ PANEL_VALUE_STORED_LENGTH, 132,
+ PANEL_NOTIFY_LEVEL, PANEL_ALL,
+ PANEL_NOTIFY_PROC, prompt_notify_proc,
+ 0);
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Create an OK button.
+ */
+ if(ok_button == NULL)
+ ok_button = panel_button_image(panel, "OK", 0, 0);
+
+ ok_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, ok_button,
+ PANEL_NOTIFY_PROC, prompt_ok_proc,
+ 0);
+
+ /*
+ * Create an abort button.
+ */
+ if(abort_button == NULL)
+ abort_button = panel_button_image(panel, "Abort", 0, 0);
+
+ abort_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, abort_button,
+ PANEL_NOTIFY_PROC, prompt_abort_proc,
+ 0);
+
+ /*
+ * Make them windows fit.
+ */
+ window_fit(panel);
+ window_fit(frame);
+
+ /*
+ * Centre the prompt
+ */
+ w = (int)window_get(frame, WIN_WIDTH);
+ h = (int)window_get(frame, WIN_HEIGHT);
+ x -= w/2;
+ y -= h/2;
+ window_set(frame,
+ WIN_X, x,
+ WIN_Y, y,
+ 0);
+
+ /*
+ * Set the flag to TRUE to indicate not aborted.
+ */
+ prompt_return_value = TRUE;
+
+ /*
+ * Display and wait for done.
+ */
+ (void)window_loop(frame);
+
+ /*
+ * If OK, then retrieve the window values and store them.
+ */
+ if(prompt_return_value)
+ {
+ /*
+ * Loop through the items copying back values.
+ */
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_STRING_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, char *)) == NULL)
+ break;
+
+ /*
+ * Get the value of this item.
+ */
+ strcpy(value, panel_get_value(string_item[i]));
+ }
+ }
+ va_end(ap);
+ }
+
+ /*
+ * Destroy the window.
+ */
+ window_destroy(frame);
+
+ return prompt_return_value;
+}
+
+/*
+ * integers_prompt: eg.
+ * integers_prompt(1152/2, 900/2,
+ * "Width: ", &w,
+ * "Height: ", &h,
+ * 0);
+ */
+
+#define MAX_INTEGER_ITEMS MAX_STRING_ITEMS
+
+bool
+integers_prompt(x, y, va_alist)
+int x, y;
+va_dcl
+{
+ Frame frame;
+ Panel panel;
+ Panel_item integer_item[MAX_INTEGER_ITEMS], ok_item, abort_item;
+ Event *event;
+ int w, h;
+ int i;
+ char *prompt;
+ int *value;
+ va_list ap;
+ char value_string[20];
+
+ /*
+ * Create the frame and panel.
+ */
+ frame = window_create(NULL, FRAME,
+ FRAME_SHOW_LABEL, FALSE,
+ FRAME_NO_CONFIRM, TRUE,
+ 0);
+
+ panel = window_create(frame, PANEL,
+ PANEL_ITEM_X_GAP, 1000, /* Enforces vertical layout */
+ 0);
+
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_INTEGER_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, int *)) == NULL)
+ break;
+
+ /*
+ * Create a text item for the string.
+ */
+ sprintf(value_string, "%d", *value);
+ integer_item[i] = panel_create_item(panel, PANEL_TEXT,
+ PANEL_LABEL_STRING, prompt,
+ PANEL_VALUE, value_string,
+ PANEL_VALUE_DISPLAY_LENGTH, 20,
+ PANEL_VALUE_STORED_LENGTH, 20,
+ PANEL_NOTIFY_STRING, "\033",
+ PANEL_NOTIFY_LEVEL, PANEL_ALL,
+ PANEL_NOTIFY_PROC, prompt_notify_proc,
+ 0);
+
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Create an OK button.
+ */
+ if(ok_button == NULL)
+ ok_button = panel_button_image(panel, "OK", 0, 0);
+
+ ok_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, ok_button,
+ PANEL_NOTIFY_PROC, prompt_ok_proc,
+ 0);
+
+ /*
+ * Create an abort button.
+ */
+ if(abort_button == NULL)
+ abort_button = panel_button_image(panel, "Abort", 0, 0);
+
+ abort_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, abort_button,
+ PANEL_NOTIFY_PROC, prompt_abort_proc,
+ 0);
+
+ /*
+ * Make them windows fit.
+ */
+ window_fit(panel);
+ window_fit(frame);
+
+ /*
+ * Centre the prompt
+ */
+ w = (int)window_get(frame, WIN_WIDTH);
+ h = (int)window_get(frame, WIN_HEIGHT);
+ x -= w/2;
+ y -= h/2;
+ window_set(frame,
+ WIN_X, x,
+ WIN_Y, y,
+ 0);
+
+ /*
+ * Set the flag to TRUE to indicate not aborted.
+ */
+ prompt_return_value = TRUE;
+
+ /*
+ * Display and wait for done.
+ */
+ (void)window_loop(frame);
+
+ /*
+ * If OK, then retrieve the window values and store them.
+ */
+ if(prompt_return_value)
+ {
+ /*
+ * Loop through the items copying back values.
+ */
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_INTEGER_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, int *)) == NULL)
+ break;
+
+ /*
+ * Get the value of this item.
+ */
+ *value = atoi(panel_get_value(integer_item[i]));
+ }
+ }
+ va_end(ap);
+ }
+
+ /*
+ * Destroy the window.
+ */
+ window_destroy(frame);
+
+ return prompt_return_value;
+}
+
+/*
+ * doubles_prompt: eg.
+ * doubles_prompt(1152/2, 900/2,
+ * "Width: ", &w,
+ * "Height: ", &h,
+ * 0);
+ */
+
+#define MAX_DOUBLE_ITEMS MAX_INTEGER_ITEMS
+
+bool
+doubles_prompt(x, y, va_alist)
+int x, y;
+va_dcl
+{
+ Frame frame;
+ Panel panel;
+ Panel_item double_item[MAX_DOUBLE_ITEMS], ok_item, abort_item;
+ Event *event;
+ int w, h;
+ int i;
+ char *prompt;
+ double *value;
+ va_list ap;
+ char value_string[20];
+
+ /*
+ * Create the frame and panel.
+ */
+ frame = window_create(NULL, FRAME,
+ FRAME_SHOW_LABEL, FALSE,
+ FRAME_NO_CONFIRM, TRUE,
+ 0);
+
+ panel = window_create(frame, PANEL,
+ PANEL_ITEM_X_GAP, 1000, /* Enforces vertical layout */
+ 0);
+
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_DOUBLE_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, double *)) == NULL)
+ break;
+
+ /*
+ * Create a text item for the string.
+ */
+ sprintf(value_string, "%g", *value);
+ double_item[i] = panel_create_item(panel, PANEL_TEXT,
+ PANEL_LABEL_STRING, prompt,
+ PANEL_VALUE, value_string,
+ PANEL_VALUE_DISPLAY_LENGTH, 20,
+ PANEL_VALUE_STORED_LENGTH, 40,
+ PANEL_NOTIFY_STRING, "\033",
+ PANEL_NOTIFY_LEVEL, PANEL_ALL,
+ PANEL_NOTIFY_PROC, prompt_notify_proc,
+ 0);
+ }
+ }
+ va_end(ap);
+
+ /*
+ * Create an OK button.
+ */
+ if(ok_button == NULL)
+ ok_button = panel_button_image(panel, "OK", 0, 0);
+
+ ok_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, ok_button,
+ PANEL_NOTIFY_PROC, prompt_ok_proc,
+ 0);
+
+ /*
+ * Create an abort button.
+ */
+ if(abort_button == NULL)
+ abort_button = panel_button_image(panel, "Abort", 0, 0);
+
+ abort_item = panel_create_item(panel, PANEL_BUTTON,
+ PANEL_LABEL_IMAGE, abort_button,
+ PANEL_NOTIFY_PROC, prompt_abort_proc,
+ 0);
+
+ /*
+ * Make them windows fit.
+ */
+ window_fit(panel);
+ window_fit(frame);
+
+ /*
+ * Centre the prompt
+ */
+ w = (int)window_get(frame, WIN_WIDTH);
+ h = (int)window_get(frame, WIN_HEIGHT);
+ x -= w/2;
+ y -= h/2;
+ window_set(frame,
+ WIN_X, x,
+ WIN_Y, y,
+ 0);
+
+ /*
+ * Set the flag to FALSE to indicate not aborted.
+ */
+ prompt_return_value = FALSE;
+
+ /*
+ * Display and wait for done.
+ */
+ (void)window_loop(frame);
+
+ /*
+ * If OK, then retrieve the window values and store them.
+ */
+ if(prompt_return_value)
+ {
+ /*
+ * Loop through the items copying back values.
+ */
+ va_start(ap);
+ {
+ for(i = 0; i < MAX_DOUBLE_ITEMS; i++)
+ {
+ /*
+ * Stop if no more strings.
+ */
+ if((prompt = va_arg(ap, char *)) == NULL ||
+ (value = va_arg(ap, double *)) == NULL)
+ break;
+
+ /*
+ * Get the value of this item.
+ */
+ *value = atof(panel_get_value(double_item[i]));
+ }
+ }
+ va_end(ap);
+ }
+
+ /*
+ * Destroy the window.
+ */
+ window_destroy(frame);
+
+ return prompt_return_value;
+}
+
+/*
+ * prompt_notify_proc:
+ */
+
+static Panel_setting
+prompt_notify_proc(item, event)
+Panel_item item;
+Event *event;
+{
+ if(event_id(event) == ESC)
+ {
+ prompt_return_value = TRUE;
+ window_return(NULL);
+ return PANEL_NONE;
+ }
+ else if(event_id(event) == Control('C'))
+ {
+ prompt_return_value = FALSE;
+ window_return(NULL);
+ return PANEL_NONE;
+ }
+ else
+ return panel_text_notify(item, event);
+}
+
+/*
+ * prompt_ok_proc:
+ * Normal return from string prompt.
+ */
+
+static Panel_setting
+prompt_ok_proc(item, event)
+Panel_item item;
+Event *event;
+{
+ prompt_return_value = TRUE;
+
+ window_return(NULL);
+
+ return PANEL_NONE;
+}
+
+/*
+ * prompt_abort_proc:
+ * Return from prompt with null string.
+ */
+
+static Panel_setting
+prompt_abort_proc(item, event)
+Panel_item item;
+Event *event;
+{
+ prompt_return_value = FALSE;
+
+ window_return(NULL);
+
+ return PANEL_NONE;
+}
diff --git a/dviware/dvipage/readme b/dviware/dvipage/readme
new file mode 100644
index 0000000000..bb6ffb0689
--- /dev/null
+++ b/dviware/dvipage/readme
@@ -0,0 +1,129 @@
+Installation of Dvipage.
+=======================
+
+Dvipage previews DVI files on Sun workstations under SunView.
+Version 3.0 has been tested on Sun 3 /160, /75, /60 under OS 3.5 and 4.0.1,
+and also on a Sun 4/260 under OS 4.0.1. An earlier version worked
+on many other configurations also.
+
+You should have the following files in a directory:
+-rw-r--r-- 1 hunt 2183 Dec 20 10:33 Makefile
+-r--r--r-- 1 hunt 4324 Dec 20 10:31 README
+-r--r--r-- 1 hunt 3606 Dec 15 19:14 args.c
+-r--r--r-- 1 hunt 7587 Dec 15 19:14 dvi.h
+-r--r--r-- 1 hunt 11199 Dec 15 19:14 dvipage.1
+-rw-r--r-- 1 hunt 48924 Dec 15 19:14 dvipage.c
+-rw-r--r-- 1 hunt 8869 Dec 15 19:14 dvipage.h
+-r--r--r-- 1 hunt 8953 Dec 15 19:14 findfile.c
+-r--r--r-- 1 hunt 20760 Dec 15 19:14 fonts.c
+-r--r--r-- 1 hunt 12593 Dec 15 19:14 message.c
+-r--r--r-- 1 hunt 30047 Dec 15 19:14 sample.c
+-r--r--r-- 1 hunt 2883 Dec 15 19:14 utils.c
+
+Installation is simple; however, there are some system dependent
+parameters which must be set in the file dvipage.h, in particular,
+the FONT_AREA definition must reflect the location of the TeX fonts
+on your system; in the file as provided, there are conditionals which
+select a different font file location for different types of machine.
+FONT_AREA is a colon separated list of directories where font files
+will be found; either PXL or GF files can be used:
+
+#ifndef FONT_AREA
+#ifdef sparc
+#define FONT_AREA \
+ "/nfs/tex-server/tex/1988/lib/tex/fonts:/fonts/tex/pxl"
+#else !sparc
+#define FONT_AREA \
+ "/nfs/tex-server/tex/1988/lib/tex/fonts:/usr/spar/font/tex/pxl"
+#endif sparc
+#endif FONT_AREA
+
+You should also alter PRINT_SPOOLER and PRINT_PAGE_SPOOLER also in
+the file dvipage.h, in the obvious way to provide commands which can
+be used to print either the whole document or a single page of the document.
+
+/*
+ * Define a command which will print the whole document.
+ */
+#ifndef PRINT_SPOOLER
+#define PRINT_SPOOLER "lpr -d %s >/dev/null 2>/dev/null"
+#endif PRINT_SPOOLER
+
+/*
+ * Define a command which will print the specified page of the document.
+ */
+#ifndef PRINT_PAGE_SPOOLER
+#define PRINT_PAGE_SPOOLER \
+ "texpagefilter -f %d -t %d %s | lpr -d >/dev/null 2>/dev/null"
+#endif PRINT_PAGE_SPOOLER
+
+It may be that the simple PRINT_ definitions above do not have enough
+flexibility to deal with the printer configurations at your site.
+At Spar, we have some laserwriters and some imagen printers;
+the following hacks in the file `dvipage.c' examine the PRINTER
+environment variable and set the print_spooler and print_page_spooler
+strings accordingly:
+
+ /*
+ * Customise this part for your local printer environment.
+ * ======================================================
+ */
+#ifdef SPAR_HACKS
+
+ /*
+ * Set local printer hacks.
+ */
+ printer = getenv("PRINTER");
+ if(printer && strncmp(printer, "lw", 2) == 0)
+ {
+ sprintf(print_spooler,
+ "dvips -P%s %%s >/dev/null 2>/dev/null",
+ printer);
+ sprintf(print_page_spooler,
+ "dvips -P%s -f %%d -t %%d %%s >/dev/null 2>/dev/null",
+ printer);
+ }
+ else if(printer && strncmp(printer, "im", 2) == 0)
+ {
+ sprintf(print_spooler,
+ "dviimp -P%s %%s >/dev/null 2>/dev/null",
+ printer);
+ sprintf(print_page_spooler,
+ "dviimp -P%s -S %%d -E %%d %%s >/dev/null 2>/dev/null",
+ printer);
+ }
+ else
+ {
+ fprintf(stderr, "PRINTER environment not recognised:\n");
+ fprintf(stderr, " using `%s' to print files\n",
+ print_spooler);
+ fprintf(stderr, " using `%s' to print pages\n",
+ print_page_spooler);
+ }
+
+ if(verbose & DEBUG_PRINTER)
+ {
+ fprintf(stderr, "Using `%s' to print files\n",
+ print_spooler);
+ fprintf(stderr, "Using `%s' to print pages\n",
+ print_page_spooler);
+ }
+
+#endif SPAR_HACKS
+
+Remember to add a -DLOCAL_HACKS into the compile line in the Makefile,
+or in dvipage.h, if you add something similar.
+
+Finally, change the compile flags in `Makefile' if you are not
+running on a Sun 3 with a f68881 floating point unit.
+
+When all is set up, run `make'. It will build a program called dvipage,
+which can be installed in a suitable place. The manual pages dvipage.1
+should be installed in /usr/man/man1 as dvipage.1l, or in you local manual
+pages directory.
+
+Enjoy,
+
+ Neil Hunt.
+ hunt@spar.slb.com
+ ...{amdahl|decwrl|hplabs}!spar!hunt
diff --git a/dviware/dvipage/sample.c b/dviware/dvipage/sample.c
new file mode 100644
index 0000000000..7262e31993
--- /dev/null
+++ b/dviware/dvipage/sample.c
@@ -0,0 +1,1245 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: sample.c,v $
+ * Revision 1.1 88/11/28 18:41:24 hunt
+ * Initial revision
+ *
+ * Split out of dvipage.c version 1.4.
+ */
+
+#include <stdio.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include <suntool/canvas.h>
+#include "dvipage.h"
+
+forward struct pixrect * pr_alloc();
+forward struct pixrect * pr_free();
+forward struct pixrect * pr_check();
+forward struct pixrect * pr_link();
+forward struct pixrect * pr_sample_4();
+forward struct pixrect * pr_sample_34();
+forward struct pixrect * pr_sample_3();
+forward struct pixrect * pr_sample_2();
+
+forward void pw_cover();
+forward void pr_rect();
+forward void pw_rect();
+
+/*
+ * sample_page:
+ * Filter and sample down page according to current sampling rate,
+ * and prepare for display.
+ */
+
+void
+sample_page()
+{
+
+#ifdef TIMING
+ start_time();
+#endif TIMING
+
+ switch(sampling)
+ {
+ default:
+ case 1:
+ sample_pr = pr_link(&page_mpr, &sample_mpr);
+ break;
+
+ case 2:
+ if(! (sample_pr = pr_sample_2(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 3:
+ if(! (sample_pr = pr_sample_3(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 4:
+ if(! (sample_pr = pr_sample_4(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 5:
+ if(! (sample_pr = pr_sample_34(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+ }
+
+#ifdef TIMING
+ stop_time("Sampling one page");
+#endif TIMING
+
+}
+
+/*
+ * Here follow some functions to deal with pixrects under the special case
+ * assumption that they are mem_pixrects, where the mpr_data is part
+ * of a parent structure.
+ */
+
+extern struct pixrectops mem_ops;
+
+/*
+ * pr_alloc:
+ * Allocate memory for a pixrect of size w, h, d.
+ * Returns a pointer to the pixrect structure.
+ */
+
+struct pixrect *
+pr_alloc(mpr, w, h, d)
+struct mem_pixrect *mpr;
+int w, h, d;
+{
+ int size;
+ int linebytes;
+ short *image;
+
+ /*
+ * Compute the size of memory needed, and alloc it.
+ */
+ linebytes = mpr_linebytes(w, d);
+ size = linebytes * h;
+ if(! (image = (short *)malloc(size)))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Set up the pr.
+ */
+ mpr->mpr_pr.pr_ops = &mem_ops;
+ mpr->mpr_pr.pr_width = w;
+ mpr->mpr_pr.pr_height = h;
+ mpr->mpr_pr.pr_depth = d;
+ mpr->mpr_pr.pr_data = (caddr_t)&mpr->mpr_data;
+
+ /*
+ * Set up the mpr_data
+ */
+ mpr->mpr_data.md_linebytes = linebytes;
+ mpr->mpr_data.md_image = image;
+ mpr->mpr_data.md_offset.x = 0;
+ mpr->mpr_data.md_offset.y = 0;
+ mpr->mpr_data.md_primary = TRUE;
+ mpr->mpr_data.md_flags = 0;
+
+ /*
+ * Return the pr.
+ */
+ return &mpr->mpr_pr;
+}
+
+/*
+ * pr_free:
+ * Free the memory associated with a pixrect.
+ * Returns a pointer to no pixrect structure.
+ */
+
+struct pixrect *
+pr_free(mpr)
+struct mem_pixrect *mpr;
+{
+ short *image;
+
+ if((image = mpr->mpr_data.md_image))
+ {
+ if(mpr->mpr_data.md_primary)
+ free(image);
+ mpr->mpr_data.md_image = (short *)NULL;
+ }
+ mpr->mpr_pr.pr_width = 0;
+ mpr->mpr_pr.pr_height = 0;
+
+ return (struct pixrect *)NULL;
+}
+
+/*
+ * pr_check:
+ * Check that a designated pixrect has memory allocated for an image
+ * of size w, h, d. If not, free any existing memory and allocate
+ * more memory. This is equivalent to, but much faster than, a
+ * sequence of
+ * pr_destroy(mpr);
+ * mpr = mem_create(w, h, d);
+ */
+
+struct pixrect *
+pr_check(mpr, w, h, d)
+struct mem_pixrect *mpr;
+int w, h, d;
+{
+ /*
+ * If there is an image, check that it is the correct size.
+ */
+ if(mpr->mpr_data.md_image)
+ {
+ if(mpr->mpr_pr.pr_width == w &&
+ mpr->mpr_pr.pr_height == h &&
+ mpr->mpr_pr.pr_depth == d)
+ return &mpr->mpr_pr;
+
+ (void)pr_free(mpr);
+ }
+
+ return pr_alloc(mpr, w, h, d);
+}
+
+/*
+ * pr_link:
+ * Link the memory of mpr1 to mpr2, making mpr2 a secondary pixrect.
+ */
+
+struct pixrect *
+pr_link(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ /*
+ * Free the existing memory, if any.
+ */
+ (void)pr_free(mpr2);
+
+ /*
+ * Set up the pr.
+ */
+ mpr2->mpr_pr.pr_ops = &mem_ops;
+ mpr2->mpr_pr.pr_width = mpr1->mpr_pr.pr_width;
+ mpr2->mpr_pr.pr_height = mpr1->mpr_pr.pr_height;
+ mpr2->mpr_pr.pr_depth = mpr1->mpr_pr.pr_depth;
+ mpr2->mpr_pr.pr_data = (caddr_t)&mpr2->mpr_data;
+
+ /*
+ * Set up the mpr_data
+ */
+ mpr2->mpr_data.md_linebytes = mpr1->mpr_data.md_linebytes;
+ mpr2->mpr_data.md_image = mpr1->mpr_data.md_image;
+ mpr2->mpr_data.md_offset.x = mpr1->mpr_data.md_offset.x;
+ mpr2->mpr_data.md_offset.y = mpr1->mpr_data.md_offset.y;
+ mpr2->mpr_data.md_primary = FALSE;
+ mpr2->mpr_data.md_flags = 0;
+
+ /*
+ * Return the pr.
+ */
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * Colour Map Stuff
+ * ================
+ */
+
+#define M4F 0
+#define M4T (M4F+16)
+#define M3F (M4T+1)
+#define M3T (M3F+24)
+#define M2F (M3T+1)
+#define M2T (M2F+4)
+
+uchar cmap_red[64] =
+{
+#ifdef NEVER
+ /* Cmap with GAMMA=2,2,2,20,20,20 */
+ /* 4x4 from 0 to 16 */
+ 255, 247, 239, 231, 223, 214, 205, 196, 186,
+ 175, 163, 151, 137, 121, 103, 78, 20,
+
+ /* 3x3 from 17 to 41 */
+ 255, 250, 244, 239, 234, 229, 223, 217, 211,
+ 205, 199, 192, 186, 179, 171, 163, 155,
+ 146, 137, 127, 115, 103, 87, 67, 20,
+
+ /* 2x2 from 42 to 46 */
+ 255, 223, 186, 137, 20,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif NEVER
+ /* Cmap with GAMMA=1.3,1.3,1.3,0,0,0 */
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+uchar cmap_green[64] =
+{
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+uchar cmap_blue[64] =
+{
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+double gamma_red = 2.0;
+double gamma_green = 2.0;
+double gamma_blue = 2.0;
+int min_red = 20;
+int min_green = 20;
+int min_blue = 20;
+
+forward void make_one_cmap();
+
+void
+make_cmap()
+{
+ char *e;
+
+ if((e = getenv("DVIPAGE_GAMMA")) == NULL)
+ return;
+
+ min_red = 20;
+ min_green = 20;
+ min_blue = 20;
+ gamma_red = 0.0;
+ gamma_green = 0.0;
+ gamma_blue = 0.0;
+
+ (void)sscanf(e, " %lf,%lf,%lf,%d,%d,%d ",
+ &gamma_red, &gamma_green, &gamma_blue,
+ &min_red, &min_green, &min_blue);
+
+ if(gamma_red == 0.0)
+ gamma_red = 1.3;
+ if(gamma_green == 0.0)
+ gamma_green = gamma_red;
+ if(gamma_blue == 0.0)
+ gamma_blue = gamma_red;
+
+ make_one_cmap(cmap_red, 1.0/gamma_red, min_red);
+ make_one_cmap(cmap_green, 1.0/gamma_green, min_green);
+ make_one_cmap(cmap_blue, 1.0/gamma_blue, min_blue);
+}
+
+void
+make_one_cmap(cmap, power, mn)
+uchar cmap[];
+double power;
+int mn;
+{
+ int i;
+
+ /*
+ * 4x4 cmap.
+ */
+ for(i = M4F; i <= M4T; i++)
+ cmap[i] = (uchar)(pow((double)(M4T - i) / (M4T - M4F), power)
+ * (255 - mn) + mn);
+
+ /*
+ * 3x3 cmap.
+ */
+ for(i = M3F; i <= M3T; i++)
+ cmap[i] = (uchar)(pow((double)(M3T - i) / (M3T - M3F), power)
+ * (255 - mn) + mn);
+
+ /*
+ * 2x2 cmap.
+ */
+ for(i = M2F; i <= M2T; i++)
+ cmap[i] = (uchar)(pow((double)(M2T - i) / (M2T - M2F), power)
+ * (255 - mn) + mn);
+
+ cmap[63] = mn;
+}
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 4x4 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * The most significant 16 bits of the value obtained represent the
+ * number of bits in the upper half of the index, with each bit counted
+ * with a weight of 15.
+ * The least significant 16 bits of the value obtained represent the
+ * number of bits in the l;ower hald of the index, with each bit counted
+ * with a weight of 15.
+ *
+ * By combining the upper and lower halves in a single word, the values
+ * for the four vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously both the tallies
+ * for the left and the right halves of the word.
+ */
+
+static int tally4[] =
+{
+ 0x00000000, 0x00000001, 0x00000001, 0x00000002,
+ 0x00000001, 0x00000002, 0x00000002, 0x00000003,
+ 0x00000001, 0x00000002, 0x00000002, 0x00000003,
+ 0x00000002, 0x00000003, 0x00000003, 0x00000004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00040000, 0x00040001, 0x00040001, 0x00040002,
+ 0x00040001, 0x00040002, 0x00040002, 0x00040003,
+ 0x00040001, 0x00040002, 0x00040002, 0x00040003,
+ 0x00040002, 0x00040003, 0x00040003, 0x00040004,
+};
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 3x3 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * Bits 23..16 of the value obtained represent the number of bits in
+ * the upper 2.67 bits of the index, with each bit counted with a weight
+ * of 15. etc. etc.
+ *
+ * By combining the three parts in a single word, the values
+ * for the three vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously both the tallies
+ * for the left and the right halves of the word.
+ */
+
+static int tally3[] =
+{
+ 0x00000000, 0x00000003, 0x00000003, 0x00000006,
+ 0x00000102, 0x00000105, 0x00000105, 0x00000108,
+ 0x00000300, 0x00000303, 0x00000303, 0x00000306,
+ 0x00000402, 0x00000405, 0x00000405, 0x00000408,
+ 0x00000300, 0x00000303, 0x00000303, 0x00000306,
+ 0x00000402, 0x00000405, 0x00000405, 0x00000408,
+ 0x00000600, 0x00000603, 0x00000603, 0x00000606,
+ 0x00000702, 0x00000705, 0x00000705, 0x00000708,
+ 0x00020100, 0x00020103, 0x00020103, 0x00020106,
+ 0x00020202, 0x00020205, 0x00020205, 0x00020208,
+ 0x00020400, 0x00020403, 0x00020403, 0x00020406,
+ 0x00020502, 0x00020505, 0x00020505, 0x00020508,
+ 0x00020400, 0x00020403, 0x00020403, 0x00020406,
+ 0x00020502, 0x00020505, 0x00020505, 0x00020508,
+ 0x00020700, 0x00020703, 0x00020703, 0x00020706,
+ 0x00020802, 0x00020805, 0x00020805, 0x00020808,
+ 0x00030000, 0x00030003, 0x00030003, 0x00030006,
+ 0x00030102, 0x00030105, 0x00030105, 0x00030108,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030600, 0x00030603, 0x00030603, 0x00030606,
+ 0x00030702, 0x00030705, 0x00030705, 0x00030708,
+ 0x00050100, 0x00050103, 0x00050103, 0x00050106,
+ 0x00050202, 0x00050205, 0x00050205, 0x00050208,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050700, 0x00050703, 0x00050703, 0x00050706,
+ 0x00050802, 0x00050805, 0x00050805, 0x00050808,
+ 0x00030000, 0x00030003, 0x00030003, 0x00030006,
+ 0x00030102, 0x00030105, 0x00030105, 0x00030108,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030600, 0x00030603, 0x00030603, 0x00030606,
+ 0x00030702, 0x00030705, 0x00030705, 0x00030708,
+ 0x00050100, 0x00050103, 0x00050103, 0x00050106,
+ 0x00050202, 0x00050205, 0x00050205, 0x00050208,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050700, 0x00050703, 0x00050703, 0x00050706,
+ 0x00050802, 0x00050805, 0x00050805, 0x00050808,
+ 0x00060000, 0x00060003, 0x00060003, 0x00060006,
+ 0x00060102, 0x00060105, 0x00060105, 0x00060108,
+ 0x00060300, 0x00060303, 0x00060303, 0x00060306,
+ 0x00060402, 0x00060405, 0x00060405, 0x00060408,
+ 0x00060300, 0x00060303, 0x00060303, 0x00060306,
+ 0x00060402, 0x00060405, 0x00060405, 0x00060408,
+ 0x00060600, 0x00060603, 0x00060603, 0x00060606,
+ 0x00060702, 0x00060705, 0x00060705, 0x00060708,
+ 0x00080100, 0x00080103, 0x00080103, 0x00080106,
+ 0x00080202, 0x00080205, 0x00080205, 0x00080208,
+ 0x00080400, 0x00080403, 0x00080403, 0x00080406,
+ 0x00080502, 0x00080505, 0x00080505, 0x00080508,
+ 0x00080400, 0x00080403, 0x00080403, 0x00080406,
+ 0x00080502, 0x00080505, 0x00080505, 0x00080508,
+ 0x00080700, 0x00080703, 0x00080703, 0x00080706,
+ 0x00080802, 0x00080805, 0x00080805, 0x00080808,
+};
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 2x2 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * The most significant 8 bits of the value obtained represent the
+ * number of bits in the upper half of the index, with each bit counted
+ * with a weight of 15.
+ * ...
+ * The least significant 8 bits of the value obtained represent the
+ * number of bits in the l;ower hald of the index, with each bit counted
+ * with a weight of 15.
+ *
+ * By combining the four pairs of tallies in a single word, the values
+ * for the two vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously all four tallies
+ * for the four pairs of the word.
+ */
+
+static int tally2[] =
+{
+ 0x00000000, 0x00000001, 0x00000001, 0x00000002,
+ 0x00000100, 0x00000101, 0x00000101, 0x00000102,
+ 0x00000100, 0x00000101, 0x00000101, 0x00000102,
+ 0x00000200, 0x00000201, 0x00000201, 0x00000202,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010200, 0x00010201, 0x00010201, 0x00010202,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010200, 0x00010201, 0x00010201, 0x00010202,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020100, 0x00020101, 0x00020101, 0x00020102,
+ 0x00020100, 0x00020101, 0x00020101, 0x00020102,
+ 0x00020200, 0x00020201, 0x00020201, 0x00020202,
+ 0x01000000, 0x01000001, 0x01000001, 0x01000002,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000200, 0x01000201, 0x01000201, 0x01000202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01020000, 0x01020001, 0x01020001, 0x01020002,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020200, 0x01020201, 0x01020201, 0x01020202,
+ 0x01000000, 0x01000001, 0x01000001, 0x01000002,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000200, 0x01000201, 0x01000201, 0x01000202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01020000, 0x01020001, 0x01020001, 0x01020002,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020200, 0x01020201, 0x01020201, 0x01020202,
+ 0x02000000, 0x02000001, 0x02000001, 0x02000002,
+ 0x02000100, 0x02000101, 0x02000101, 0x02000102,
+ 0x02000100, 0x02000101, 0x02000101, 0x02000102,
+ 0x02000200, 0x02000201, 0x02000201, 0x02000202,
+ 0x02010000, 0x02010001, 0x02010001, 0x02010002,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010200, 0x02010201, 0x02010201, 0x02010202,
+ 0x02010000, 0x02010001, 0x02010001, 0x02010002,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010200, 0x02010201, 0x02010201, 0x02010202,
+ 0x02020000, 0x02020001, 0x02020001, 0x02020002,
+ 0x02020100, 0x02020101, 0x02020101, 0x02020102,
+ 0x02020100, 0x02020101, 0x02020101, 0x02020102,
+ 0x02020200, 0x02020201, 0x02020201, 0x02020202,
+};
+
+/*
+ * P_row:
+ * Access macro for obtaining a pointer to the bytes of a pixrect
+ * starting at row `row'.
+ */
+
+#define P_row(mpr, row) \
+ (uchar *)((int)((mpr)->mpr_data.md_image) + \
+ (int)((short)(row) * (short)((mpr)->mpr_data.md_linebytes)));
+
+/*
+ * pr_sample_4:
+ * Filter and sample mpr1 on a 4x4 basis into mpr2.
+ */
+
+struct pixrect *
+pr_sample_4(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *p3; /* a2 */
+ register uchar *pr;
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width / 4;
+ rows = mpr1->mpr_pr.pr_height / 4;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_4: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*4);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+ p3 = p2 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0 && *p3 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally4[*p0] +
+ tally4[*p1] +
+ tally4[*p2] +
+ tally4[*p3];
+
+ /*
+ * High order 4 bits
+ */
+ *pr++ = (tallies >> 16) + M4F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 4 bits
+ */
+ *pr++ = tallies + M4F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ p3++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_34:
+ * Filter and sample mpr1 on a 2.67x4 basis into mpr2.
+ * Tally count uses M3 table, and gets up to 32 pixels (weighted at 1/3)
+ * divides by two to index into the 0..16 M4 table.
+ */
+
+struct pixrect *
+pr_sample_34(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *p3; /* a2 */
+ register uchar *pr;
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width * 3 / 8;
+ rows = mpr1->mpr_pr.pr_height / 4;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_34: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*4);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+ p3 = p2 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally3[*p0] +
+ tally3[*p1] +
+ tally3[*p2] +
+ tally3[*p3];
+
+ /*
+ * High order 3 bits
+ */
+ *pr++ = (tallies >> (16+1)) + M4F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> (8+1)) + M4F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 3 bits
+ */
+ *pr++ = (tallies >> 1) + M4F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ p3++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_3:
+ * Filter and sample mpr1 on a 3x3 basis into mpr2.
+ * Note that the horizontal sampling is actually 3/8 rather than 1/3.
+ */
+
+struct pixrect *
+pr_sample_3(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *pr; /* a2 */
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width * 3 / 8;
+ rows = mpr1->mpr_pr.pr_height / 3;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_3: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*3);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally3[*p0] +
+ tally3[*p1] +
+ tally3[*p2];
+
+ /*
+ * High order 3 bits
+ */
+ *pr++ = (tallies >> 16) + M3F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 8) + M3F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 3 bits
+ */
+ *pr++ = tallies + M3F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_2:
+ * Filter and sample mpr1 on a 2x2 basis into mpr2.
+ */
+
+struct pixrect *
+pr_sample_2(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *pr; /* a3 */
+ register uchar *er; /* a2 */
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width / 2;
+ rows = mpr1->mpr_pr.pr_height / 2;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_2: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*2);
+ p1 = p0 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally2[*p0] +
+ tally2[*p1];
+
+ /*
+ * Highest two bits
+ */
+ *pr++ = (tallies >> 24) + M2F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 16) + M2F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 8) + M2F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Lowest two bits
+ */
+ *pr++ = tallies + M2F;
+ }
+ p0++;
+ p1++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pw_cover:
+ * Function which writes a pixrect onto a pixwin;
+ * where there are no src pixels, it writes background colour.
+ */
+
+void
+pw_cover(dpw, dx, dy, dw, dh, op, spr, sx, sy)
+Pixwin *dpw;
+int dx, dy, dw, dh;
+int op;
+Pixrect *spr;
+int sx, sy;
+{
+ int aw, ah;
+
+ /*
+ * Handle the left margin.
+ * If the left margin is less than the width to be painted,
+ * paint a margin, else paint the whole region and return.
+ */
+ if(sx < 0)
+ {
+ if(-sx < dw)
+ {
+ pw_writebackground(dpw, dx, dy, -sx, dh, op);
+ dx -= sx;
+ sx = 0;
+ dw += sx;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the top margin.
+ * If the top margin is less thatn the width to be painted,
+ * paint a margin, else paint the whole region and return.
+ */
+ if(sy < 0)
+ {
+ if(-sy < dh)
+ {
+ pw_writebackground(dpw, dx, dy, dw, -sy, op);
+ dy -= sy;
+ sy = 0;
+ dh += sy;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the right margin.
+ * aw = available width of source image.
+ * If available width > 0 paint a margin of dw-aw width,
+ * otherwise paint the whole region.
+ */
+ aw = spr->pr_width-sx;
+ if(dw > aw)
+ {
+ if(aw > 0)
+ {
+ pw_writebackground(dpw, dx+aw, dy, dw-aw, dh, op);
+ dw = aw;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the bottom margin.
+ * ah = available height of source image.
+ * If available height > 0 paint a margin of dh-ah height,
+ * otherwise paint the whole region.
+ */
+ ah = spr->pr_height-sy;
+ if(dh > ah)
+ {
+ if(ah > 0)
+ {
+ pw_writebackground(dpw, dx, dy+ah, dw, dh-ah, op);
+ dh = ah;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Paint the image.
+ */
+ pw_write(dpw, dx, dy, dw, dh, op, spr, sx, sy);
+}
+
+/*
+ * pr_rect:
+ * Draws a box with op and colour as specified.
+ */
+
+void
+pr_rect(pr, x, y, w, h, t, op, value)
+struct pixrect *pr;
+int x, y, w, h;
+int t;
+int op, value;
+{
+ int i;
+
+ for(i = 0; i < t; i++)
+ {
+ pr_vector(pr, x, y, x+w-1, y, op, value);
+ pr_vector(pr, x+w-1, y+1, x+w-1, y+h-2, op, value);
+ pr_vector(pr, x, y+h-1, x+w-1, y+h-1, op, value);
+ pr_vector(pr, x, y+1, x, y+h-2, op, value);
+
+ x += 1;
+ y += 1;
+ w -= 2;
+ h -= 2;
+
+ if(w <= 0 || h <= 0)
+ break;
+ }
+}
+
+/*
+ * pw_rect:
+ * Draws a box with op and colour as specified.
+ */
+
+void
+pw_rect(pw, x, y, w, h, t, op, value)
+Pixwin *pw;
+int x, y, w, h;
+int t;
+int op, value;
+{
+ int i;
+ Rect r;
+
+ r.r_left = x;
+ r.r_top = y;
+ r.r_width = w;
+ r.r_height = h;
+ pw_lock(pw, &r);
+
+ for(i = 0; i < t; i++)
+ {
+ pw_vector(pw, x, y, x+w-1, y, op, value);
+ pw_vector(pw, x+w-1, y+1, x+w-1, y+h-2, op, value);
+ pw_vector(pw, x, y+h-1, x+w-1, y+h-1, op, value);
+ pw_vector(pw, x, y+1, x, y+h-2, op, value);
+
+ x += 1;
+ y += 1;
+ w -= 2;
+ h -= 2;
+
+ if(w <= 0 || h <= 0)
+ break;
+ }
+
+ pw_unlock(pw);
+}
diff --git a/dviware/dvipage/utils.c b/dviware/dvipage/utils.c
new file mode 100644
index 0000000000..757813ece7
--- /dev/null
+++ b/dviware/dvipage/utils.c
@@ -0,0 +1,134 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: utils.c,v $
+ * Revision 1.1 88/11/28 18:41:33 hunt
+ * Initial revision
+ *
+ * Stripped from dvipage.c 1.4.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include "dvipage.h"
+
+/*
+ * Utility Functions.
+ * =================
+ */
+
+/*
+ * get_unsigned:
+ *
+ */
+
+unsigned int
+get_unsigned(fp, n)
+register FILE *fp;
+register int n;
+{
+ register int x;
+
+ x = 0;
+ while (n--)
+ {
+ x <<= 8;
+ x |= getc(fp);
+ }
+
+ return(x);
+}
+
+/*
+ * get_signed:
+ *
+ */
+
+int
+get_signed(fp, n)
+register FILE *fp;
+register int n;
+{
+ int n1;
+ register int x;
+
+ x = getc(fp); /* get first (high-order) byte */
+ n1 = n--;
+ while (n--)
+ {
+ x <<= 8;
+ x |= getc(fp);
+ }
+
+ /* NOTE: This code assumes that the right-shift is an arithmetic, rather
+ than logical, shift which will propagate the sign bit right. According
+ to Kernighan and Ritchie, this is compiler dependent! */
+
+ x<<=32-8*n1;
+ x>>=32-8*n1; /* sign extend */
+
+ return(x);
+}
+
+/*
+ * actual_factor:
+ * compute the actual size factor given the approximation.
+ */
+
+double
+actual_factor(unmodsize)
+int unmodsize; /* actually factor * 1000 */
+{
+ float realsize; /* the actual magnification factor */
+
+ realsize = (float)unmodsize / 1000.0;
+ /* a real hack to correct for rounding in some cases--rkf */
+ if(unmodsize==1095) realsize = 1.095445; /*stephalf*/
+ else if(unmodsize==1315) realsize=1.314534; /*stepihalf*/
+ else if(unmodsize==2074) realsize=2.0736; /*stepiv*/
+ else if(unmodsize==2488) realsize=2.48832; /*stepv*/
+ else if(unmodsize==2986) realsize=2.985984; /*stepiv*/
+ /* the remaining magnification steps are represented with sufficient
+ accuracy already */
+ return(realsize);
+}
+
+
+/*
+ * do_convert
+ */
+
+int
+do_convert(num, den, convResolution)
+int num;
+int den;
+int convResolution;
+{
+ register float conv;
+ conv = ((float)num/(float)den) *
+#ifdef USEGLOBALMAG
+/* actual_factor(mag) * why was this in as Actual Factor? jls */
+ ((float) mag/1000.0) *
+#endif
+ ((float)convResolution/254000.0);
+ return((int) (1.0 / conv + 0.5));
+}