diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvipage |
Initial commit
Diffstat (limited to 'dviware/dvipage')
-rw-r--r-- | dviware/dvipage/args.c | 206 | ||||
-rw-r--r-- | dviware/dvipage/dvi.h | 294 | ||||
-rw-r--r-- | dviware/dvipage/dvipage.1 | 416 | ||||
-rw-r--r-- | dviware/dvipage/dvipage.c | 2421 | ||||
-rw-r--r-- | dviware/dvipage/dvipage.h | 400 | ||||
-rw-r--r-- | dviware/dvipage/findfile.c | 503 | ||||
-rw-r--r-- | dviware/dvipage/fonts.c | 1335 | ||||
-rw-r--r-- | dviware/dvipage/makefile | 97 | ||||
-rw-r--r-- | dviware/dvipage/makefonts | 24 | ||||
-rw-r--r-- | dviware/dvipage/message.c | 659 | ||||
-rw-r--r-- | dviware/dvipage/readme | 129 | ||||
-rw-r--r-- | dviware/dvipage/sample.c | 1245 | ||||
-rw-r--r-- | dviware/dvipage/utils.c | 134 |
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)); +} |