summaryrefslogtreecommitdiff
path: root/dviware/textool
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/textool
Initial commit
Diffstat (limited to 'dviware/textool')
-rw-r--r--dviware/textool/README48
-rw-r--r--dviware/textool/commands.h266
-rw-r--r--dviware/textool/defs.h83
-rw-r--r--dviware/textool/dvistuff.c1006
-rw-r--r--dviware/textool/globals.h64
-rw-r--r--dviware/textool/makefile36
-rw-r--r--dviware/textool/pkstuff.c618
-rw-r--r--dviware/textool/problems35
-rw-r--r--dviware/textool/pxlstuff.c173
-rw-r--r--dviware/textool/sunstuff.c1620
-rw-r--r--dviware/textool/textool.fix92
-rw-r--r--dviware/textool/textool.icon36
-rw-r--r--dviware/textool/textool.l224
-rw-r--r--dviware/textool/textool.pdfbin0 -> 62931 bytes
14 files changed, 4301 insertions, 0 deletions
diff --git a/dviware/textool/README b/dviware/textool/README
new file mode 100644
index 0000000000..10faa2d059
--- /dev/null
+++ b/dviware/textool/README
@@ -0,0 +1,48 @@
+This is a TeX previewer for SunView. It works under V3.2 of Sun unix,
+and under V3.0 with KEYBOARDSCROLL undefined in defs.h. It has not been
+tested with any other versions or on any hardware other than my 3/160M.
+
+The following files should be here:
+ README what you are reading
+ Problems various things that went wrong
+ Makefile the obvious thing
+ defs.h various #defines used everywhere
+ globals.h global variable and structure definitions
+ commands.h DVI format command defs
+ sunstuff.c The SunView parts of it
+ dvistuff.c The DVI file specific bits
+ pkstuff.c Routines for pk format fonts
+ pxlstuff.c Routines for pxl format fonts
+ textool.l a man page
+ textool.icon The icon file
+
+It has a fairly long history, see the note at the start of dvistuff.c
+and the authors bit of the man page. This version opens its own window,
+complete with scrollbars, menus etc. and does not use its parent window
+for anything except debugging output.
+
+It can be compiled to use either pxl or pk format font files.
+
+Note that it was edited with tabs set to 4 rather than 8 spaces.
+
+Installation:
+
+Check the Makefile for paths etc. and for which of pkstuff.o or pxlstuff.o
+you want included.
+
+Check defs.h, mainly for font file paths and MAXOPEN.
+
+Check the note in the Problems file about frame_default_done_proc() and
+edit your <suntool/frame.h> if necessary.
+
+Make and then make install.
+
+Please send comments, bugs etc. to:
+
+ peter@memex.co.uk
+ peter@memex.uucp
+
+Peter Ilieve
+Memex Information Engines Ltd.
+East Kilbride
+Scotland
diff --git a/dviware/textool/commands.h b/dviware/textool/commands.h
new file mode 100644
index 0000000000..22475dabd7
--- /dev/null
+++ b/dviware/textool/commands.h
@@ -0,0 +1,266 @@
+/*
+ *
+ * $Revision: 1.1 $
+ * $Log: commands.h,v $
+ * Revision 1.1 83/11/23 10:56:00 mds
+ * Initial revision
+ *
+ *
+ */
+#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
+#define UNDEF_00 250
+#define UNDEF_01 251
+#define UNDEF_02 252
+#define UNDEF_03 253
+#define UNDEF_04 254
+#define UNDEF_05 255
+
diff --git a/dviware/textool/defs.h b/dviware/textool/defs.h
new file mode 100644
index 0000000000..9724b6ceed
--- /dev/null
+++ b/dviware/textool/defs.h
@@ -0,0 +1,83 @@
+/*
+ * The various defines needed by TeXtool.
+ */
+
+typedef short Boolean;
+
+char *calloc();
+#define NEW(count, type) ((type *) calloc(count, sizeof(type)))
+
+#define DEBUG /* for massive printing of input */
+ /* trace information; select with -d */
+ /* or -x for pxl font stuff */
+
+#define BINARYOPEN fopen /* byte-oriented host version */
+
+#define USEGLOBALMAG /* when defined, the dvi global
+ * magnification is applied
+ * and user specified magnifications
+ * are also allowed
+ */
+/*
+ * This is problematical. It would allow better resolution to be obtained
+ * by expanding the page but the code only allocates a fixed size canvas
+ * for drawing on, big enough for a normal page. If magnification is used
+ * the right and bottom of the page will not fall on the canvas and will
+ * never be visible. Scrolling only moves the canvas under the frame and
+ * will not redraw anything.
+ * It is rare to have a complete set of fonts at any other mag anyway.
+ */
+
+#define KEYBOARDSCROLL /* allows h,j,k,l,c scrolling */
+ /*
+ * NOTE: this will expose bugs in the
+ * scrolling code in V3.0. Do not use
+ * with 3.0
+ */
+
+#define FALSE 0
+#define TRUE 1
+#define NOTCACHED -1
+#define SETCMD 1
+#define PUTCMD 0
+#define DVIFORMAT 2
+#define FIRSTPXLCHAR 0
+#define LASTPXLCHAR 255
+#define NPXLCHARS 256
+#define PXLID 1001
+#ifndef PXLFONTAREA
+#define PXLFONTAREA "/u/tex/pxlfiles"
+#endif
+#ifndef PKFONTAREA
+#define PKFONTAREA "/u/tex/pk118"
+#endif
+#define MAXOPEN 9 /* limit of number of PXL files open */
+ /*
+ * Not very many as SunView needs a lot
+ * You need two spare after allowing 3 for
+ * stdin, stout & stderr, 12 for SunView and
+ * 1 for the .dvi file. So MAXOPEN should
+ * be a max. of NOFILE-18.
+ */
+#define RESOLUTION 118 /* is really about 81 (11in raster, 900 dots */
+#define STACKSIZE 100
+#define STRSIZE 256
+
+/* these are defined as macros for speed */
+#define MoveDown(a) v += (a);
+#define MoveOver(b) h += (b);
+#define PixRound(x, conv) ((int)(((x) + ((conv) >> 1)) / (conv)));
+
+/* status bits for main_state */
+#define SB_INITIAL 01 /* for case where called as textool <file> */
+#define SB_NOFILE 02 /* set after error or for no file name */
+#define SB_NEWFILE 04 /* we have a new dvi name to open */
+#define SB_NODVIFILE 010 /* we can't access(2) the dvi file */
+#define SB_NOTEXFILE 020 /* we can't access(2) the tex file */
+#define SB_INTERPRET 040 /* safe to process dvi file */
+#define SB_PLUSNUMBER 0100 /* accumulating a positive number */
+#define SB_MINUSNUMBER 0200 /* accumulating a negative number */
+#define SB_TEXING 0400 /* subwindow currently running tex or latex */
+#define SB_EDITING 01000 /* subwindow currently running vi */
+#define SB_SHELL 02000 /* subwindow currently running shell */
+
diff --git a/dviware/textool/dvistuff.c b/dviware/textool/dvistuff.c
new file mode 100644
index 0000000000..513c08938a
--- /dev/null
+++ b/dviware/textool/dvistuff.c
@@ -0,0 +1,1006 @@
+/*
+ * This is the DVI related part of TeXtool
+ */
+
+/*
+ * This code has quite a long history.
+ * The header comment from the dvi2ps driver from the TeX tape I
+ * received about August 86 is shown below
+ */
+
+/*
+ *
+ * AUTHOR(s)
+ * Mark Senn wrote the early versions of this program 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. Neal Holtz ported
+ * it to the Apollo, and from there to producing PostScript
+ * output. Scott Jones added intelligent font substitution.
+ *
+ */
+
+/*
+ * This version presumably diverged from the dvi2ps line before the
+ * move to Apollo and was then modified by Y. Ledru (yl@lln-cs)
+ * to work with SunView.
+ * A bugfix from dvi2ps to do with marking font files closed when they
+ * are removed from the cache has been "bought back" into this version.
+ * The font data structures have also been changed so they are
+ * cross-linked so no searching has to be done except to find the
+ * least used cache entry.
+ * Extra tests for valid data values have been put into LoadAChar()
+ * as a bogus PXL file was causing havoc by overfilling a character
+ * pixrect.
+ * Much other tidying up and removal of code which was no longer used
+ * has also been done
+ * Peter Ilieve - peter@memex.co.uk
+ */
+
+#include "defs.h"
+#include "commands.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <pixrect/pixrect_hs.h>
+char *index();
+char *calloc();
+char *rindex();
+char *sprintf();
+char *strcpy();
+
+/* procedures in sunstuff */
+extern void BatchStart();
+extern void BatchEnd();
+extern void Fatal();
+extern void SetBop();
+extern void SetChar();
+extern void SetRule();
+extern void Warning();
+
+/* procedures in pxlstuff or pkstuff */
+extern void FindFontFile();
+extern void LoadAChar();
+extern void ReadCharDefs();
+
+/* procedures here */
+float ActualFactor();
+FILE* BINARYOPEN();
+void CloseDviFile();
+int DoConv();
+void DoPage();
+Boolean DviFileChanged();
+void FindPostAmblePtr();
+void FreeFontStorage();
+void GetBytes();
+int NoSignExtend();
+void OpenDviFile();
+FILE *OpenFontFile();
+int ReadFontDef();
+void ReadPagePointers();
+void ReadPreAmble();
+void ReadPostAmble();
+void SetFntNum();
+int SignExtend();
+void SkipFontDef();
+#ifdef DEBUG
+void ShowPxlCache();
+void ShowPxlFd();
+#endif
+
+/* a few global variables and data structures */
+#include "globals.h"
+
+struct pixel_list
+{
+ FILE *pixel_file_id; /* file identifier */
+ struct font_entry *feptr; /* font_entry for this cache slot */
+ int use_count; /* count of "opens" */
+};
+
+struct font_entry *fontptr; /* font_entry pointer */
+struct font_entry *hfontptr=NULL;/* font_entry pointer to head of chain */
+struct font_entry *pfontptr = NULL; /* previous font_entry pointer */
+int nopen = 0; /* number of open font files */
+struct pixel_list pixel_files[MAXOPEN+1];
+ /* list of open font file identifiers */
+ /* slot 0 not used */
+
+/*
+ * DVI file related data structures
+ */
+
+/* pagepointers moved to globals to let sunstuff get at count_0 */
+
+ /* two structs to hold pre and postamble */
+ /* a lot of this is not used */
+struct Preamble
+{
+ unsigned int num;
+ unsigned int den;
+ unsigned int mag;
+} preamble;
+
+struct Postamble
+{
+ long last_page_ptr;
+ unsigned int num;
+ unsigned int den;
+ unsigned int mag;
+ unsigned int maxheight;
+ unsigned int maxwidth;
+ unsigned short maxstack;
+ unsigned short totalpages;
+} postamble;
+
+FILE *dvifp; /* DVI file pointer */
+static time_t dvimodtime;
+
+struct stack_entry { /* stack entry */
+ int h, v, w, x, y, z; /* what's on stack */
+};
+struct stack_entry stack[STACKSIZE]; /* stack */
+int sp; /* stack pointer */
+
+ /* h and v are global */
+int w; /* current horizontal spacing */
+int x; /* current horizontal spacing */
+int y; /* current vertical spacing */
+int z; /* current vertical spacing */
+
+/* display related stuff */
+
+int hconv, vconv; /* converts DVI units to pixels */
+
+/* now to the real code */
+
+/*-->ActualFactor*/
+/**********************************************************************/
+/************************** ActualFactor ****************************/
+/**********************************************************************/
+
+float /* compute the actual size factor given the approximation */
+ActualFactor(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);
+}
+
+
+/*-->CloseDviFile*/
+/**********************************************************************/
+/************************** CloseDviFile ******************************/
+/**********************************************************************/
+
+void
+CloseDviFile()
+{
+ if (dvifp != NULL)
+ fclose(dvifp);
+ if (pagepointers != NULL) {
+ free (pagepointers);
+ pagepointers = NULL;
+ }
+}
+
+
+/*-->DoConv*/
+/**********************************************************************/
+/****************************** DoConv ******************************/
+/**********************************************************************/
+
+int
+DoConv(num, den, mag, convResolution)
+{
+ register float conv;
+ conv = ((float)num/(float)den) *
+#ifdef USEGLOBALMAG
+ ActualFactor(mag) *
+#endif
+ ((float)convResolution/254000.0);
+ return((int) (1.0 / conv + 0.5));
+}
+
+
+/*-->DoPage*/
+/**********************************************************************/
+/****************************** DoPage ******************************/
+/**********************************************************************/
+
+void
+DoPage(pagenumber)
+int pagenumber;
+{
+ unsigned char command;
+ int val, val2;
+ int k;
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"DoPage(%d)\n", pagenumber);
+#endif
+ if (!(main_state & SB_INTERPRET))
+ return;
+ h = v = w = x = y = z = 0; /* zero position */
+ sp = 0; /* empty stack */
+ fontptr = NULL; /* no font */
+ fseek(dvifp, pagepointers[pagenumber].page_ptr, 0); /* go to correct page */
+ SetBop(); /* clear canvas */
+ if (Batching)
+ BatchStart();
+ while (main_state & SB_INTERPRET) /* interpret DVI file */
+
+ /* we use getc here for speed */
+ /* also force a complete jump table */
+ switch (command=getc(dvifp)) {
+
+ case SETC_000: case SETC_001: case SETC_002: case SETC_003:
+ case SETC_004: case SETC_005: case SETC_006: case SETC_007:
+ case SETC_008: case SETC_009: case SETC_010: case SETC_011:
+ case SETC_012: case SETC_013: case SETC_014: case SETC_015:
+ case SETC_016: case SETC_017: case SETC_018: case SETC_019:
+ case SETC_020: case SETC_021: case SETC_022: case SETC_023:
+ case SETC_024: case SETC_025: case SETC_026: case SETC_027:
+ case SETC_028: case SETC_029: case SETC_030: case SETC_031:
+ case SETC_032: case SETC_033: case SETC_034: case SETC_035:
+ case SETC_036: case SETC_037: case SETC_038: case SETC_039:
+ case SETC_040: case SETC_041: case SETC_042: case SETC_043:
+ case SETC_044: case SETC_045: case SETC_046: case SETC_047:
+ case SETC_048: case SETC_049: case SETC_050: case SETC_051:
+ case SETC_052: case SETC_053: case SETC_054: case SETC_055:
+ case SETC_056: case SETC_057: case SETC_058: case SETC_059:
+ case SETC_060: case SETC_061: case SETC_062: case SETC_063:
+ case SETC_064: case SETC_065: case SETC_066: case SETC_067:
+ case SETC_068: case SETC_069: case SETC_070: case SETC_071:
+ case SETC_072: case SETC_073: case SETC_074: case SETC_075:
+ case SETC_076: case SETC_077: case SETC_078: case SETC_079:
+ case SETC_080: case SETC_081: case SETC_082: case SETC_083:
+ case SETC_084: case SETC_085: case SETC_086: case SETC_087:
+ case SETC_088: case SETC_089: case SETC_090: case SETC_091:
+ case SETC_092: case SETC_093: case SETC_094: case SETC_095:
+ case SETC_096: case SETC_097: case SETC_098: case SETC_099:
+ case SETC_100: case SETC_101: case SETC_102: case SETC_103:
+ case SETC_104: case SETC_105: case SETC_106: case SETC_107:
+ case SETC_108: case SETC_109: case SETC_110: case SETC_111:
+ case SETC_112: case SETC_113: case SETC_114: case SETC_115:
+ case SETC_116: case SETC_117: case SETC_118: case SETC_119:
+ case SETC_120: case SETC_121: case SETC_122: case SETC_123:
+ case SETC_124: case SETC_125: case SETC_126: case SETC_127:
+ SetChar(&(fontptr->ch[command - SETC_000]), SETCMD);
+ break;
+
+ case SET1:case SET2:case SET3:case SET4:
+ val = NoSignExtend(dvifp, command-SET1+1);
+ SetChar(&(fontptr->ch[val]), SETCMD);
+ break;
+
+ case SET_RULE:
+ val = NoSignExtend(dvifp, 4);
+ val2 = NoSignExtend(dvifp, 4);
+ SetRule(val, val2, SETCMD);
+ break;
+
+ case PUT1:case PUT2:case PUT3:case PUT4:
+ val = NoSignExtend(dvifp,command-PUT1+1);
+ SetChar(&(fontptr->ch[val]), PUTCMD);
+ break;
+
+ case PUT_RULE:
+ val = NoSignExtend(dvifp, 4);
+ val2 = NoSignExtend(dvifp, 4);
+ SetRule(val, val2, PUTCMD);
+ break;
+
+ case NOP:
+ break;
+
+ case BOP:
+ Fatal("BOP encountered in page");
+ break;
+
+ case EOP:
+ if (Batching)
+ BatchEnd();
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"DoPage return after EOP found\n");
+#endif
+ return;
+
+ case PUSH:
+ if (sp >= STACKSIZE)
+ Fatal("stack overflow");
+ else {
+ 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)
+ Fatal("stack underflow");
+ else {
+ 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 = SignExtend(dvifp,command-RIGHT1+1);
+ MoveOver(val);
+ break;
+
+ case W0:
+ MoveOver(w);
+ break;
+
+ case W1:case W2:case W3:case W4:
+ w = SignExtend(dvifp,command-W1+1);
+ MoveOver(w);
+ break;
+
+ case X0:
+ MoveOver(x);
+ break;
+
+ case X1:case X2:case X3:case X4:
+ x = SignExtend(dvifp,command-X1+1);
+ MoveOver(x);
+ break;
+
+ case DOWN1:case DOWN2:case DOWN3:case DOWN4:
+ val = SignExtend(dvifp,command-DOWN1+1);
+ MoveDown(val);
+ break;
+
+ case Y0:
+ MoveDown(y);
+ break;
+
+ case Y1:case Y2:case Y3:case Y4:
+ y = SignExtend(dvifp,command-Y1+1);
+ MoveDown(y);
+ break;
+
+ case Z0:
+ MoveDown(z);
+ break;
+
+ case Z1:case Z2:case Z3:case Z4:
+ z = SignExtend(dvifp,command-Z1+1);
+ MoveDown(z);
+ break;
+
+ case FONT_00: case FONT_01: case FONT_02: case FONT_03:
+ case FONT_04: case FONT_05: case FONT_06: case FONT_07:
+ case FONT_08: case FONT_09: case FONT_10: case FONT_11:
+ case FONT_12: case FONT_13: case FONT_14: case FONT_15:
+ case FONT_16: case FONT_17: case FONT_18: case FONT_19:
+ case FONT_20: case FONT_21: case FONT_22: case FONT_23:
+ case FONT_24: case FONT_25: case FONT_26: case FONT_27:
+ case FONT_28: case FONT_29: case FONT_30: case FONT_31:
+ case FONT_32: case FONT_33: case FONT_34: case FONT_35:
+ case FONT_36: case FONT_37: case FONT_38: case FONT_39:
+ case FONT_40: case FONT_41: case FONT_42: case FONT_43:
+ case FONT_44: case FONT_45: case FONT_46: case FONT_47:
+ case FONT_48: case FONT_49: case FONT_50: case FONT_51:
+ case FONT_52: case FONT_53: case FONT_54: case FONT_55:
+ case FONT_56: case FONT_57: case FONT_58: case FONT_59:
+ case FONT_60: case FONT_61: case FONT_62: case FONT_63:
+ SetFntNum(command - FONT_00);
+ break;
+
+ case FNT1:case FNT2:case FNT3:case FNT4:
+ SetFntNum(NoSignExtend(dvifp, command-FNT1+1));
+ break;
+
+ case XXX1:case XXX2:case XXX3:case XXX4:
+ k = NoSignExtend(dvifp,command-XXX1+1);
+ while (k--)
+ getc(dvifp);
+ break;
+
+ case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
+ k = NoSignExtend(dvifp, command-FNT_DEF1+1);
+ SkipFontDef (k); /* always read from postamble */
+ break;
+
+ case PRE:
+ Fatal("PRE occurs within file");
+ break;
+
+ case POST:
+ Fatal("POST found before EOP");
+ break;
+
+ case POST_POST:
+ Fatal("POST_POST with no preceding POST");
+ break;
+
+ case UNDEF_00: case UNDEF_01: case UNDEF_02: case UNDEF_03:
+ case UNDEF_04: case UNDEF_05:
+ default:
+ Fatal("%d is an undefined command", command);
+ break;
+
+ }
+ if (Batching)
+ BatchEnd(); /* to catch cases when stop in mid page */
+}
+
+
+/*-->DviFileChanged*/
+/**********************************************************************/
+/************************ DviFileChanged ****************************/
+/**********************************************************************/
+
+Boolean
+DviFileChanged()
+{
+ struct stat statbuf;
+
+ if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* can't do fstat */
+ return (FALSE);
+ fstat(fileno(dvifp), &statbuf);
+ if (statbuf.st_mtime > dvimodtime) {
+ dvimodtime = statbuf.st_mtime;
+ return (TRUE);
+ }
+ else
+ return (FALSE);
+}
+
+
+/*-->FindPostAmblePtr*/
+/**********************************************************************/
+/************************ FindPostAmblePtr **************************/
+/**********************************************************************/
+
+void
+FindPostAmblePtr(postambleptr)
+long *postambleptr;
+
+/* this routine will move to the end of the file and find the start
+ of the postamble */
+
+{
+ int i;
+
+ fseek (dvifp, (long) 0, 2); /* goto end of file */
+ *postambleptr = ftell (dvifp) - 4;
+ fseek (dvifp, *postambleptr, 0);
+
+ while (TRUE) {
+ fseek (dvifp, --(*postambleptr), 0);
+ if (((i = NoSignExtend(dvifp, 1)) != 223) && (i != DVIFORMAT)) {
+ Fatal ("Bad end of DVI file");
+ return;
+ }
+ if (i == DVIFORMAT)
+ break;
+ }
+ fseek (dvifp, (*postambleptr) - 4, 0);
+ (*postambleptr) = NoSignExtend(dvifp, 4);
+ fseek (dvifp, *postambleptr, 0);
+}
+
+
+/*-->FreeFontStorage*/
+/**********************************************************************/
+/**************************** FreeFontStorage ***********************/
+/**********************************************************************/
+
+void
+FreeFontStorage()
+{
+ register struct font_entry *tfontptr;
+ register struct char_entry *tcharptr;
+ register int i;
+
+ while (hfontptr != NULL) {
+ tfontptr = hfontptr->next;
+ /* close open font file */
+ if (hfontptr->cache_slot != NOTCACHED)
+ fclose(pixel_files[hfontptr->cache_slot].pixel_file_id);
+ /* free all memory pixrects for chars */
+ if (hfontptr->has_been_opened == TRUE) {
+ for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
+ tcharptr = &(hfontptr->ch[i]);
+ if (tcharptr->where.isloaded == TRUE)
+ pr_destroy(tcharptr->where.address.pixrectptr);
+ }
+ }
+ /* free font_entry struct */
+ free(hfontptr);
+ hfontptr = tfontptr;
+ }
+ pfontptr = NULL;
+ nopen = 0; /* zero font cache count */
+}
+
+
+/*-->GetBytes*/
+/**********************************************************************/
+/***************************** GetBytes *****************************/
+/**********************************************************************/
+
+void
+GetBytes(fp, cp, n) /* get n bytes from file fp */
+register FILE *fp; /* file pointer */
+register char *cp; /* character pointer */
+register int n; /* number of bytes */
+
+{
+ while (n--)
+ *cp++ = getc(fp);
+}
+
+
+/*-->NoSignExtend*/
+/**********************************************************************/
+/*************************** NoSignExtend ***************************/
+/**********************************************************************/
+
+int
+NoSignExtend(fp, n) /* return n byte quantity from file fd */
+register FILE *fp; /* file pointer */
+register int n; /* number of bytes */
+
+{
+ register int x; /* number being constructed */
+
+ x = 0;
+ while (n--) {
+ x <<= 8;
+ x |= getc(fp);
+ }
+ return(x);
+}
+
+
+/*-->OpenDviFile*/
+/**********************************************************************/
+/************************** OpenDviFile ******************************/
+/**********************************************************************/
+
+void
+OpenDviFile(dviname)
+char *dviname;
+{
+ if (main_state & (SB_NOFILE | SB_NODVIFILE))
+ return; /* don't even try */
+ if ((dvifp=BINARYOPEN(dviname,"r")) == NULL) {
+ Fatal("Can't open \"%s\"", dviname);
+ return;
+ }
+ ReadPreAmble();
+#ifdef USEGLOBALMAG
+ if (Mflag)
+ preamble.mag = user_mag;
+#endif
+ ReadPostAmble();
+#ifdef USEGLOBALMAG
+ if (Mflag)
+ postamble.mag = user_mag;
+#endif
+ ReadPagePointers();
+ if (postamble.maxstack >= STACKSIZE) {
+ Fatal ("Stack size is too small for \"%s\"", dviname);
+ return;
+ }
+ if ((preamble.num != postamble.num) ||
+ (preamble.den != postamble.den) ||
+ (preamble.mag != postamble.mag)) {
+ Fatal("Preamble-Postamble mismatch in \"%s\"", dviname);
+ return;
+ }
+ totalpages = postamble.totalpages;
+ hconv = DoConv(preamble.num, preamble.den, preamble.mag, RESOLUTION);
+ vconv = DoConv(preamble.num, preamble.den, preamble.mag, RESOLUTION);
+ dvimodtime = 0; /* to force DviFileChanged() to set it */
+ (void)DviFileChanged();
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"DVI file open OK, total pages = %d\n",
+ totalpages);
+#endif
+}
+
+
+/*-->OpenFontFile*/
+/**********************************************************************/
+/************************** OpenFontFile *****************************/
+/**********************************************************************/
+
+FILE *
+OpenFontFile()
+/***********************************************************************
+ The original version of this dvi driver reopened the font file each
+ time the font changed, resulting in an enormous number of relatively
+ expensive file openings. This version keeps a cache of up to
+ MAXOPEN open files, so that when a font change is made, the file
+ pointer returned can usually be updated from the cache. When the
+ file is not found in the cache, it must be opened. In this case,
+ the next empty slot in the cache is assigned, or if the cache is
+ full, the least used font file is closed and its slot reassigned for
+ the new file. Identification of the least used file is based on the
+ counts of the number of times each file has been "opened" by this
+ routine. On return, the file pointer is always repositioned to the
+ beginning of the file.
+
+***********************************************************************/
+{
+ register int i,least_used,current;
+ FILE *fontfp;
+
+#ifdef DEBUG
+ if (ExtraDebug) fprintf(stderr,"Open Font file:\n");
+#endif
+ if (pfontptr == fontptr)
+ {
+ pixel_files[fontptr->cache_slot].use_count++; /* update reference count */
+#ifdef DEBUG
+ if (ExtraDebug) fprintf(stderr,"quick return (k = %d)\n",
+ fontptr->k);
+#endif
+ return (pixel_files[fontptr->cache_slot].pixel_file_id);
+ }
+
+ if ((current = fontptr->cache_slot) != NOTCACHED)
+ /* it is already in cache */
+ {
+ fontfp = pixel_files[current].pixel_file_id;
+ fseek(fontfp,0,0); /* reposition to start of file */
+#ifdef DEBUG
+ if (ExtraDebug) fprintf(stderr,
+ "reposition font file position %d (k = %d)\n",
+ current, fontptr->k);
+#endif
+ }
+ else /* file not in cache */
+ {
+ if (nopen < MAXOPEN) /* just add it to list */
+ current = ++nopen;
+ else /* list full -- find least used file, */
+ { /* close it, and reuse slot for new file */
+ least_used = 1;
+ for (i = 2; i <= MAXOPEN; ++i)
+ if (pixel_files[least_used].use_count >
+ pixel_files[i].use_count)
+ least_used = i;
+ (pixel_files[least_used].feptr)->cache_slot = NOTCACHED;
+ /* flag font_entry as no longer cached */
+ fclose(pixel_files[least_used].pixel_file_id);
+ /* close it */
+#ifdef DEBUG
+ if (ExtraDebug) fprintf(stderr,
+ "font file %s, slot %d closed (k = %d)\n",
+ (pixel_files[least_used].feptr)->name,
+ least_used,
+ (pixel_files[least_used].feptr)->k);
+#endif
+ current = least_used;
+ }
+ if (!fontptr->has_been_opened)
+ FindFontFile(fontptr, preamble.mag);
+ if (ExtraDebug)
+ printf("Trying to open file %s\n", fontptr->name);
+ if ((fontfp=BINARYOPEN(fontptr->name,"r")) == NULL) {
+ if (ExtraDebug)
+ printf("Failed to open file %s\n", fontptr->name);
+ Fatal("font file %s could not be opened; %d font files are open",
+ fontptr->name,nopen);
+ return (NULL);
+ }
+#ifdef DEBUG
+ if (ExtraDebug)
+ fprintf(stderr,"font file %s opened, position %d, (k = %d)\n",
+ fontptr->name, current, fontptr->k);
+#endif
+ pixel_files[current].pixel_file_id = fontfp;
+ pixel_files[current].use_count = 0;
+ pixel_files[current].feptr = fontptr; /* make cross links */
+ fontptr->cache_slot = current;
+ if (!fontptr->has_been_opened) {
+ ReadCharDefs(fontptr, fontfp);
+ fontptr->has_been_opened = TRUE;
+ }
+ }
+ pfontptr = fontptr; /* make previous = current font */
+ pixel_files[current].use_count++; /* update reference count */
+ return (fontfp);
+}
+
+
+/*-->ReadFontDef*/
+/**********************************************************************/
+/**************************** ReadFontDef ***************************/
+/**********************************************************************/
+
+int
+ReadFontDef(k)
+int k;
+{
+ register struct font_entry *tfontptr; /* temporary font_entry pointer */
+
+ if ((tfontptr = NEW(1, struct font_entry)) == NULL) {
+ Fatal("can't malloc space for font_entry");
+ return;
+ }
+ tfontptr->next = hfontptr;
+ fontptr = hfontptr = tfontptr;
+
+ tfontptr->k = k;
+ tfontptr->c = NoSignExtend(dvifp, 4); /* checksum */
+ tfontptr->s = NoSignExtend(dvifp, 4); /* space size */
+ tfontptr->d = NoSignExtend(dvifp, 4); /* design size */
+ tfontptr->a = NoSignExtend(dvifp, 1); /* area length for font name */
+ tfontptr->l = NoSignExtend(dvifp, 1); /* device length */
+ GetBytes(dvifp, tfontptr->n, tfontptr->a+tfontptr->l);
+ tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
+ tfontptr->cache_slot = NOTCACHED;
+ tfontptr->has_been_opened = FALSE;
+ if (PreLoad || BigPreLoad)
+ (void)OpenFontFile();
+}
+
+
+/*-->ReadPagePointers*/
+/**********************************************************************/
+/************************** ReadPagePointers ************************/
+/**********************************************************************/
+
+void
+ReadPagePointers()
+{
+ long temp_ptr;
+ int index;
+ int k;
+
+ if (main_state & (SB_NOFILE | SB_NODVIFILE))
+ return;
+#ifdef DEBUG
+ if (Debug) fprintf (stderr, "now reading page pointers\n");
+#endif
+ pagepointers = NEW(postamble.totalpages ,struct page_entry);
+ if (pagepointers == NULL) {
+ Fatal("can't malloc space for page pointers");
+ return;
+ }
+ index = postamble.totalpages;
+ temp_ptr = postamble.last_page_ptr;
+ while (--index >= 0) {
+ fseek(dvifp, temp_ptr, 0);
+ if(NoSignExtend(dvifp, 1) != BOP) {
+ Fatal("Couldn't find BOP");
+ return;
+ }
+ pagepointers[index].count_0 = NoSignExtend(dvifp, 4);
+ k = 36;
+ while (k--)
+ getc(dvifp);
+ pagepointers[index].page_ptr = temp_ptr+45;
+ temp_ptr = (long)NoSignExtend(dvifp, 4);
+ }
+}
+
+
+/*-->ReadPreAmble*/
+/**********************************************************************/
+/************************** ReadPreAmble ****************************/
+/**********************************************************************/
+
+void
+ReadPreAmble()
+{
+ int k;
+
+ if (main_state & (SB_NOFILE | SB_NODVIFILE))
+ return;
+ if (NoSignExtend(dvifp, 2) != ((PRE << 8) | DVIFORMAT)) {
+ Fatal("This doesn't look like a DVI file, it doesn't start with PRE, %d",
+ DVIFORMAT);
+ return;
+ }
+ preamble.num = NoSignExtend(dvifp, 4);
+ preamble.den = NoSignExtend(dvifp, 4);
+ preamble.mag = NoSignExtend(dvifp, 4);
+ k = NoSignExtend(dvifp, 1);
+ while (k--)
+ getc(dvifp);
+}
+
+
+/*-->ReadPostAmble*/
+/**********************************************************************/
+/************************** ReadPostAmble ***************************/
+/**********************************************************************/
+
+void
+ReadPostAmble()
+{
+ long postambleptr;
+ int command;
+ Boolean foundPOST_POST;
+
+ if (main_state & (SB_NOFILE | SB_NODVIFILE))
+ return;
+ FindPostAmblePtr (&postambleptr);
+ if (NoSignExtend(dvifp, 1) != POST) {
+ Fatal ("POST missing at head of postamble");
+ return;
+ }
+#ifdef DEBUG
+ if (Debug) fprintf (stderr, "got POST command\n");
+#endif
+ postamble.last_page_ptr = NoSignExtend(dvifp, 4);
+ postamble.num = NoSignExtend(dvifp, 4);
+ postamble.den = NoSignExtend(dvifp, 4);
+ postamble.mag = NoSignExtend(dvifp, 4);
+ postamble.maxheight = NoSignExtend(dvifp, 4);
+ postamble.maxheight = NoSignExtend(dvifp, 4);
+ postamble.maxstack = NoSignExtend(dvifp, 2);
+ postamble.totalpages = NoSignExtend(dvifp, 2);
+
+#ifdef DEBUG
+ if (Debug) fprintf (stderr, "now reading font defs\n");
+#endif
+ foundPOST_POST = FALSE;
+ while (!foundPOST_POST) {
+ switch (command = NoSignExtend(dvifp, 1)) {
+ case FNT_DEF1:
+ case FNT_DEF2:
+ case FNT_DEF3:
+ case FNT_DEF4:
+ ReadFontDef(NoSignExtend(dvifp, command-FNT_DEF1+1));
+ break;
+ case NOP:
+ break;
+ case POST_POST:
+ foundPOST_POST = TRUE;
+#ifdef DEBUG
+ if (Debug) fprintf (stderr, "got POST_POST command\n");
+#endif
+ break;
+ default:
+ Fatal ("Bad command in postamble font defs");
+ return;
+ }
+ }
+}
+
+
+/*-->SetFntNum*/
+/**********************************************************************/
+/**************************** SetFntNum *****************************/
+/**********************************************************************/
+
+void
+SetFntNum(k)
+int k;
+
+/*
+ * This sets the global fontptr from the DVI font number k.
+ * This font is then used for all subsequent characters until the next
+ * SetFntNum
+ */
+
+{
+ fontptr = hfontptr;
+ while ((fontptr!=NULL) && (fontptr->k!=k))
+ fontptr = fontptr->next;
+ if (fontptr == NULL)
+ Fatal("font %d undefined", k);
+}
+
+
+/*-->SignExtend*/
+/**********************************************************************/
+/**************************** SignExtend ****************************/
+/**********************************************************************/
+
+int
+SignExtend(fp, n) /* return n byte quantity from file fd */
+register FILE *fp; /* file pointer */
+register int n; /* number of bytes */
+
+{
+ int n1; /* number of bytes */
+ register int x; /* number being constructed */
+
+ x = getc(fp); /* get first (high-order) byte */
+ if ((x & 0x80) != 0) /* it is negative */
+ x |= 0xFFFFFF00; /* fill upper bits with ones */
+ n1 = n--;
+ while (n--) {
+ x <<= 8;
+ x |= getc(fp);
+ }
+ return(x);
+}
+
+
+/*-->SkipFontDef*/
+/**********************************************************************/
+/**************************** SkipFontDef ***************************/
+/**********************************************************************/
+
+void
+SkipFontDef()
+{
+ short n;
+
+ n = 12; /* for c, s and d params */
+ while (n--)
+ getc(dvifp);
+ n = getc(dvifp); /* a param */
+ n += getc(dvifp); /* l param, form a+l */
+ while (n--)
+ getc(dvifp); /* throw away name */
+}
+
+
+#ifdef DEBUG
+/*-->ShowPxlFd*/
+/**********************************************************************/
+/**************************** ShowPxlCache **************************/
+/**********************************************************************/
+
+void
+ShowPxlCache()
+{
+ short i;
+
+ fprintf(stderr, "Font file cache contents:\n");
+ for(i=1; i<=nopen; i++) {
+ fprintf(stderr,"Slot %d: Name %s.%dpxl: Use count %d\n",
+ i,
+ (pixel_files[i].feptr)->n,
+ (pixel_files[i].feptr)->font_mag,
+ pixel_files[i].use_count);
+ }
+}
+
+
+/*-->ShowPxlFd*/
+/**********************************************************************/
+/**************************** ShowPxlFd *****************************/
+/**********************************************************************/
+
+void
+ShowPxlFd()
+{
+ short i;
+
+ if (dvifp)
+ fprintf(stderr,"\ndvi file %d\n\n", fileno(dvifp));
+ fprintf(stderr,"number of pxl files open = %d\n", nopen);
+ for (i=1; i<=nopen; i++)
+ if ((pixel_files[i].feptr)->cache_slot != NOTCACHED)
+ fprintf(stderr,"pixel_files[%d]: fd %d, name %s\n",
+ i,
+ fileno(pixel_files[i].pixel_file_id),
+ (pixel_files[i].feptr)->n);
+}
+#endif
+
diff --git a/dviware/textool/globals.h b/dviware/textool/globals.h
new file mode 100644
index 0000000000..9486dc4a72
--- /dev/null
+++ b/dviware/textool/globals.h
@@ -0,0 +1,64 @@
+/*
+ * a few really global variables
+ */
+
+#ifdef _DEFINE
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+/* various flags and state variables */
+
+EXTERN Boolean Debug;
+EXTERN Boolean ExtraDebug;
+EXTERN Boolean PreLoad; /* preload the font descriptions? */
+EXTERN Boolean BigPreLoad; /* preload the font descriptions? */
+EXTERN Boolean Batching; /* batch raster-ops for speed (approx x3) */
+EXTERN Boolean Mflag; /* to say that -m was specified */
+EXTERN int user_mag; /* the value specified with -m */
+EXTERN short main_state; /* to say what we are currently doing */
+
+EXTERN int h; /* horizontal and vertical positions */
+EXTERN int v;
+EXTERN int hconv; /* conversion factors from DVI to pixels */
+EXTERN int vconv;
+
+EXTERN char *PXLpath;
+EXTERN char *PKpath;
+
+EXTERN unsigned short totalpages;
+
+struct char_entry { /* character entry */
+ unsigned short width, height; /* width and height in pixels */
+ short xOffset, yOffset; /* x offset and y offset in pixels */
+ struct {
+ Boolean isloaded;
+ union {
+ long fileOffset;
+ struct pixrect *pixrectptr;
+ } address;
+ } where;
+ int tfmw; /* TFM width */
+};
+
+struct font_entry { /* font entry */
+ int k, c, s, d, a, l;
+ char n[STRSIZE]; /* FNT_DEF command parameters */
+ int font_mag; /* computed from FNT_DEF s and d parameters */
+ /* and only used for generating PXL filename */
+ char name[STRSIZE]; /* full name of PXL file */
+ int cache_slot; /* slot in pixel_files, NOTCACHED if not */
+ Boolean has_been_opened; /* to say if ReadCharDefs() has been done */
+ struct char_entry ch[NPXLCHARS]; /* character information */
+ struct font_entry *next; /* next font in chain */
+};
+
+struct page_entry /* for holding BOP info */
+{
+ long page_ptr; /* offset in DVI file of command after BOP */
+ int count_0; /* TeX count 0 (page number) for this page */
+};
+
+EXTERN struct page_entry *pagepointers;
+
diff --git a/dviware/textool/makefile b/dviware/textool/makefile
new file mode 100644
index 0000000000..1e76916dee
--- /dev/null
+++ b/dviware/textool/makefile
@@ -0,0 +1,36 @@
+CFLAGS = -f68881 -fsingle -O
+LIBS = -lsuntool -lsunwindow -lpixrect
+BINDIR = /u/tex/bin
+MANDIR = /usr/man/manl
+ICONDIR = /usr/include/images
+FONTOBJ = pkstuff.o
+# change the above to pxlstuff.o for pxl format fonts
+RHOST = drake
+FILES = README Problems Makefile defs.h globals.h commands.h\
+ sunstuff.c dvistuff.c pkstuff.c pxlstuff.c textool.l textool.icon
+
+textool: sunstuff.o dvistuff.o ${FONTOBJ}
+ cc -o textool ${CFLAGS} sunstuff.o dvistuff.o ${FONTOBJ} ${LIBS}
+
+install: textool
+ install -s textool ${BINDIR}
+
+rinstall: ${BINDIR}/textool
+ rcp ${BINDIR}/textool ${RHOST}:${BINDIR}
+
+installall: textool textool.l textool.icon
+ install -s textool ${BINDIR}
+ cp textool.l ${MANDIR}
+ cp textool.icon ${ICONDIR}
+
+clean:
+ rm -rf *.o textool kit
+
+kit: ${FILES}
+ tar cvf - ${FILES} | compress | btoa > kit
+
+sunstuff.o: defs.h globals.h
+dvistuff.o: defs.h globals.h commands.h
+pxlstuff.o: defs.h globals.h
+pkstuff.o: defs.h globals.h
+
diff --git a/dviware/textool/pkstuff.c b/dviware/textool/pkstuff.c
new file mode 100644
index 0000000000..32de8ed7e2
--- /dev/null
+++ b/dviware/textool/pkstuff.c
@@ -0,0 +1,618 @@
+/*
+ * This is the font part of textool, dealing with PK format files.
+ * The low level routines to deal with the PK format
+ * were transliterated from pktopx
+ * See the pktopx documentation for details.
+ * For V2.3, 29 Mar 88
+- * Fixed stupid errors in skip_specials() that caused specials to be
+missed
+
+ */
+
+#include "defs.h"
+#include <stdio.h>
+#include <sys/file.h> /* for access() stuff */
+#include <pixrect/pixrect_hs.h> /* for LoadAChar() */
+
+char *index();
+int strlen();
+char *strcpy();
+char *sprintf();
+
+/* procedures in sunstuff */
+extern void Fatal();
+extern void Warning();
+
+/* procedures in dvistuff */
+extern float ActualFactor();
+extern FILE *OpenFontFile();
+
+/* procedures here */
+void ReadCharDefs();
+void LoadAChar();
+
+/* a few global variables and data structures */
+#include "globals.h"
+
+#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_ID 89
+
+#define ROWSIZE 64 /* maximum width of raster in 16 bit words */
+
+static FILE *pkfp;
+static long pk_loc; /* points to next byte to be read in file */
+static long pk_char_start;
+static int repeat_count;
+static int dyn_f;
+static int word_width;
+static int char_height;
+static int char_width;
+static Boolean got_pk_post;
+static Boolean turn_on;
+static int bit_weight;
+static int flag_byte;
+static int packet_length;
+static int char_code;
+static int tfm_width;
+static int hor_esc;
+static int vert_esc;
+static int h_off;
+static int v_off;
+static int nybindex;
+static short row[ROWSIZE];
+static short *rowptr;
+static short *imageptr;
+
+static int power[16] =
+ {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
+ 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000};
+static int gpower[17] =
+ {0, 1, 3, 7, 15, 0x1f, 0x3f, 0x7f,
+ 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
+
+#define get_pk_byte() (pk_loc++, getc(pkfp))
+
+
+int
+get_pk_word()
+{
+ int myword;
+
+ myword = get_pk_byte() << 8;
+ return (myword + get_pk_byte());
+}
+
+
+int
+get_pk_double()
+{
+ register int mydouble;
+
+ mydouble = get_pk_byte() << 8;
+ mydouble += get_pk_byte();
+ mydouble = (mydouble << 8) + get_pk_byte();
+ return ((mydouble << 8) + get_pk_byte());
+}
+
+
+ /*
+ * This returns the next nybble from the pk file
+ * The variable nybindex controls which nybble is
+ * returned. This is initialised to 0 in normal_raster()
+ * as a previous normal_raster() may have read an odd
+ * number of nybbles.
+ */
+int
+get_pk_nybble()
+{
+ static int mynybble;
+
+ if (nybindex) {
+ nybindex = 0;
+ return (mynybble & 0xf);
+ }
+ else {
+ mynybble = get_pk_byte();
+ nybindex = 1;
+ return (mynybble >> 4);
+ }
+}
+
+
+ /*
+ * This returns a non-zero value if the next pk file
+ * bit is a one. It is only used in an if (..) so
+ * the actual value is not important.
+ * The variable bit_weight is used to count the bits
+ * between calls to get_pk_byte(). It is initialised
+ * to 0 in bitmap_raster() so a byte is fetched the
+ * first time.
+ * The function is given for illustration. The macro
+ * following is used for speed.
+ */
+/*
+ *int
+ *get_pk_bit()
+ *{
+ * static int byte_for_bits;
+ *
+ * if (bit_weight <= 1) {
+ * bit_weight = 256;
+ * byte_for_bits = get_pk_byte();
+ * }
+ * bit_weight = bit_weight >> 1;
+ * return (byte_for_bits & bit_weight);
+ *}
+ */
+static int byte_for_bits;
+#define get_pk_bit() (((bit_weight<=1) ?\
+ (bit_weight = 128, byte_for_bits=get_pk_byte()) : (bit_weight>>=1)),\
+ byte_for_bits&bit_weight)
+
+
+void
+send_row()
+{
+ register short *dp;
+ register int i;
+ register int repcount;
+
+ dp = imageptr;
+ repcount = repeat_count + 1;
+ while (repcount--) {
+ rowptr = row;
+ i = word_width;
+ while(i--)
+ *dp++ = *rowptr++;
+ }
+ imageptr=dp; /* save for next call */
+}
+
+
+void
+skip_specials()
+{
+ register int i;
+
+ do {
+ i = 0;
+ flag_byte = get_pk_byte();
+ if (flag_byte >= PK_XXX1)
+ switch (flag_byte) {
+ case PK_XXX4:
+ i = get_pk_byte();
+ case PK_XXX3:
+ i = (i<<8) + get_pk_byte();
+ case PK_XXX2:
+ i = (i<<8) + get_pk_byte();
+ case PK_XXX1:
+ i = (i<<8) + get_pk_byte();
+ while (i--)
+ (void)get_pk_byte();
+ break;
+ case PK_YYY:
+ (void)get_pk_double();
+ break;
+ case PK_POST:
+#ifdef DEBUG
+ if (ExtraDebug)
+ fprintf(stderr, "Got pk_post in skip_specials()\n");
+#endif
+ got_pk_post = TRUE;
+ return;
+ case PK_NOP:
+ break;
+ default:
+ Fatal("Bad pk command byte (%d) in skip_specials()",
+ flag_byte);
+ return;
+ }
+ } while (flag_byte >= PK_XXX1);
+}
+
+
+ /*
+ * This routine returns the next run count from the pk
+ * character description. It will set the global repeat_count
+ * to any repeat count value encountered.
+ */
+int
+pk_packed_num()
+{
+ register int i, j;
+
+ i = get_pk_nybble();
+ if (i == 0) {
+ do {
+ j = get_pk_nybble();
+ i++;
+ } while (j == 0);
+ while (i--)
+ j = (j<<4) + get_pk_nybble();
+ return (j - 15 + ((13 - dyn_f)<<4) + dyn_f);
+ }
+ else if (i <= dyn_f)
+ return (i);
+ else if (i < 14)
+ return (((i - dyn_f - 1)<<4) + get_pk_nybble() + dyn_f + 1);
+ else {
+ if (i == 14)
+ repeat_count = pk_packed_num();
+ else /* i must be 15 */
+ repeat_count = 1;
+ return (pk_packed_num());
+ }
+}
+
+ /*
+ * This deals with run count encoded rasters.
+ * It uses pk_packed_num() which in turn uses get_pk_nybble().
+ */
+void
+normal_raster(dp)
+short *dp;
+{
+ register int word = 0;
+ register int count;
+ register int h_bit = char_width;
+ register int word_weight = 16;
+ register int rows_left = char_height;
+
+ repeat_count = 0;
+ nybindex = 0;
+ imageptr = dp;
+ rowptr = row;
+
+ while (rows_left > 0) {
+ count = pk_packed_num();
+ while (count > 0) {
+ if ((count < word_weight) && (count < h_bit)) {
+ if (turn_on)
+ word += gpower[word_weight] - gpower[word_weight - count];
+ h_bit -= count;
+ word_weight -= count;
+ count = 0;
+ }
+ else if ((count >= h_bit) && (h_bit <= word_weight)) {
+ if (turn_on)
+ word += gpower[word_weight] - gpower[word_weight - h_bit];
+ *rowptr++ = word;
+ send_row();
+ rowptr = row;
+ rows_left -= repeat_count + 1;
+ repeat_count = 0;
+ word = 0;
+ word_weight = 16;
+ count -= h_bit;
+ h_bit = char_width;
+ }
+ else {
+ if (turn_on)
+ word += gpower[word_weight];
+ *rowptr++ = word;
+ word = 0;
+ count -= word_weight;
+ h_bit -= word_weight;
+ word_weight = 16;
+ }
+ }
+ turn_on ^= 1;
+ }
+ if ((rows_left != 0) || (h_bit != char_width)) {
+ Fatal("Bad pk file - more bits than required\n");
+ return;
+ }
+}
+
+
+ /*
+ * This deals with bit mapped raster (dyn_f = 14).
+ * It uses get_pk_bit().
+ */
+void
+bitmap_raster(dp)
+short *dp;
+{
+ register int i;
+ register int j;
+ register int word;
+ register int word_weight;
+
+ bit_weight = 0;
+
+ for (i = 0; i < char_height; i++) {
+ word = 0;
+ word_weight = 15;
+ for (j = 0; j < char_width; j++) {
+ if (get_pk_bit())
+ word += power[word_weight];
+ if (word_weight-- == 0) {
+ *dp++ = word;
+ word = 0;
+ word_weight = 15;
+ }
+ }
+ if (word_weight < 15)
+ *dp++ = word;
+ }
+}
+
+
+ /*
+ * This reads the pk file preamble and rejects the file
+ * if it does not start correctly.
+ */
+void
+get_pk_preamble()
+{
+ register int comment_length;
+
+ got_pk_post = FALSE;
+ fseek(pkfp, 0L, 0);
+ pk_loc = 0;
+ if (get_pk_byte() != PK_PRE) {
+ Fatal("Bad pk file - doesn't start with pk_pre\n");
+ return;
+ }
+ if (get_pk_byte() != PK_ID) {
+ Fatal("Bad pk file - wrong pk_id byte\n");
+ return;
+ }
+ comment_length = get_pk_byte();
+ while (comment_length--)
+ get_pk_byte();
+ (void)get_pk_double();
+ (void)get_pk_double();
+ (void)get_pk_double();
+ (void)get_pk_double();
+}
+
+
+ /*
+ * This reads the preamble for one character up to the tfm width.
+ * The tfm width is read as when it is stored in the char_entry
+ * struct it needs to be multiplied by the font "s" parameter.
+ * ReadCharDefs() is passed a pointer to the font_entry struct
+ * so it can do this whereas LoadAChar() can't.
+ * The rest of the char will either be skipped or read with
+ * get_pk_char_dimen().
+ * flag_byte will have been set by a previous skip_specials().
+ */
+void
+get_pk_char_code()
+{
+ dyn_f = flag_byte >> 4;
+ turn_on = (flag_byte & 0x8) >> 3;
+ flag_byte &= 0x7;
+ pk_char_start = pk_loc - 1; /* - 1 as flag byte has been read */
+
+ if (flag_byte < 4) { /* short preamble */
+ packet_length = (flag_byte << 8) + get_pk_byte();
+ char_code = get_pk_byte();
+ tfm_width = get_pk_byte() << 16;
+ tfm_width += get_pk_word();
+ packet_length -= 3; /* correct for reading tfm_width */
+ }
+ else if (flag_byte < 7) { /* extended short preamble */
+ packet_length = ((flag_byte - 4) << 16) + get_pk_word();
+ char_code = get_pk_byte();
+ tfm_width = get_pk_byte() << 16;
+ tfm_width += get_pk_word();
+ packet_length -= 3;
+ }
+ else { /* long preamble */
+ packet_length = get_pk_double();
+ char_code = get_pk_double();
+ tfm_width = get_pk_double();
+ packet_length -= 4;
+ }
+}
+
+ /*
+ * This reads the char preamble starting after the tfm width,
+ * carrying on where get_pk_char_code() left off.
+ */
+void
+get_pk_char_dimen()
+{
+ if (flag_byte < 4) { /* short preamble */
+ hor_esc = get_pk_byte();
+ char_width = get_pk_byte();
+ word_width = (char_width + 15)>>4;
+ char_height = get_pk_byte();
+ h_off = (char)get_pk_byte();
+ v_off = (char)get_pk_byte();
+ }
+ else if (flag_byte < 7) { /* extended short preamble */
+ hor_esc = get_pk_word();
+ char_width = get_pk_word();
+ word_width = (char_width + 15)>>4;
+ char_height = get_pk_word();
+ h_off = (short)get_pk_word();
+ v_off = (short)get_pk_word();
+ }
+ else { /* long preamble */
+ hor_esc = get_pk_double();
+ vert_esc = get_pk_double();
+ char_width = get_pk_double();
+ word_width = (char_width + 15)>>4;
+ char_height = get_pk_double();
+ h_off = get_pk_double();
+ v_off = get_pk_double();
+ }
+}
+
+
+ /*
+ * This reads the preamble for one character.
+ */
+void
+get_pk_char_preamble()
+{
+ flag_byte = get_pk_byte();
+ get_pk_char_code();
+ get_pk_char_dimen();
+}
+
+
+/*
+ * Now here are the routines called by the rest of textool
+ */
+
+/*-->FindFontFile*/
+
+void
+FindFontFile(tfontptr, mag)
+struct font_entry *tfontptr;
+unsigned int mag;
+{
+ char *direct, *tcp, *tcp1;
+ int found;
+ char curarea[STRSIZE];
+
+ tfontptr->font_mag = (int)(
+ ActualFactor((int)(((float)tfontptr->s/(float)tfontptr->d)*1000.0+0.5))
+#ifdef USEGLOBALMAG
+ * ActualFactor(mag)
+#endif
+ * (float)RESOLUTION + 0.5);
+#ifdef DEBUG
+ if (ExtraDebug) {
+ fprintf(stderr, "FindFontFile():\n");
+ fprintf(stderr, " mag = %d\n", mag);
+ fprintf(stderr, " s = %d\n", tfontptr->s);
+ fprintf(stderr, " d = %d\n", tfontptr->d);
+ fprintf(stderr, " font_mag = %d\n", tfontptr->font_mag);
+ }
+#endif
+ if (tfontptr->a != 0) {
+ sprintf(tfontptr->name, "%s.%dpk", tfontptr->n, tfontptr->font_mag);
+ } else {
+ direct = PKpath;
+ found = FALSE;
+ do {
+ tcp = index(direct, ':');
+ if (tcp == NULL) tcp = strlen(direct) + direct;
+ strncpy(curarea, direct, tcp-direct);
+ tcp1 = curarea + (tcp - direct);
+ *tcp1++ = '/';
+ *tcp1++ = '\0';
+
+ sprintf(tfontptr->name, "%s%s.%dpk",
+ curarea, tfontptr->n, tfontptr->font_mag);
+ found = (access(tfontptr->name, R_OK) == 0);
+ if (*tcp) direct = tcp + 1; else direct = tcp;
+ } while ( !found && *direct != '\0');
+ }
+#ifdef DEBUG
+ if (ExtraDebug)
+ fprintf(stderr, "FindFontFile() returns with name %s\n",
+ tfontptr->name);
+#endif
+}
+
+
+/*-->LoadAChar*/
+
+void
+LoadAChar(ptr)
+register struct char_entry *ptr;
+{
+ register Pixrect *pr;
+ register short *dp;
+
+ pkfp = OpenFontFile();
+ if (ptr->where.address.fileOffset == 0) {
+ ptr->where.address.pixrectptr = NULL;
+ return;
+ }
+ fseek(pkfp, ptr->where.address.fileOffset, 0);
+ get_pk_char_preamble();
+ ptr->width = char_width;
+ ptr->height = char_height;
+ ptr->xOffset= h_off;
+ ptr->yOffset = v_off;
+ if ((pr = mem_create(ptr->width, ptr->height, 1)) == NULL) {
+ Fatal("Couldn't allocate pixrect");
+ return;
+ }
+ dp = ((struct mpr_data *)pr->pr_data)->md_image;
+ if (dyn_f == 14)
+ bitmap_raster(dp);
+ else
+ normal_raster(dp);
+ ptr->where.address.pixrectptr = pr;
+ ptr->where.isloaded = TRUE;
+}
+
+
+/*-->ReadCharDefs*/
+
+void
+ReadCharDefs(tfontptr, fp)
+struct font_entry *tfontptr;
+FILE *fp;
+{
+ register struct char_entry *tcharptr; /* temporary char_entry pointer */
+ register Pixrect *pr;
+ register int junk_count;
+ short *dp;
+
+#ifdef DEBUG
+ if (ExtraDebug)
+ fprintf(stderr, "ReadCharDefs() for font %s\n", tfontptr->name);
+#endif
+ pkfp = fp;
+ get_pk_preamble();
+ skip_specials();
+ while (!got_pk_post) {
+ get_pk_char_code();
+ tcharptr = &(tfontptr->ch[char_code]);
+ tcharptr->tfmw = tfm_width * (float)tfontptr->s / (float)(1<<20);
+ if (BigPreLoad) {
+ /*
+ * Load the rest of the character info.
+ */
+ get_pk_char_dimen();
+ tcharptr->width = char_width;
+ tcharptr->height = char_height;
+ tcharptr->xOffset= h_off;
+ tcharptr->yOffset = v_off;
+ if ((pr = mem_create(char_width, char_height, 1)) == NULL) {
+ Fatal("Couldn't allocate pixrect");
+ return;
+ }
+ dp = ((struct mpr_data *)pr->pr_data)->md_image;
+ if (dyn_f == 14)
+ bitmap_raster(dp);
+ else
+ normal_raster(dp);
+ tcharptr->where.address.pixrectptr = pr;
+ tcharptr->where.isloaded = TRUE;
+ }
+ else {
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset = pk_char_start;
+ /*
+ * Otherwise skip the rest of the char.
+ * The bytes are read rather than using fseek as the pk files
+ * are small and the whole thing is likely to fit in one stdio
+ * buffer so this will not involve any function calls.
+ */
+ junk_count = packet_length;
+ while (junk_count--)
+ getc(pkfp);
+ pk_loc += packet_length;
+ }
+ skip_specials();
+ }
+}
+
+
diff --git a/dviware/textool/problems b/dviware/textool/problems
new file mode 100644
index 0000000000..c5b5cda091
--- /dev/null
+++ b/dviware/textool/problems
@@ -0,0 +1,35 @@
+scrollbar_scroll_to() does not work when called from CanvasEventProc()
+ The scroll event generated by this proc does not have the scrollbar
+ handle as an extra arg like it should.
+ Hacked to work by fixing up the arg in the interposer which has to
+ be there anyway to do the page forward/backward commands.
+
+ Fixed in V3.2
+
+menu_show() doesn't return ordinal position as default value
+ Fixed by putting in explicit MENU_VALUE.
+
+mpr_d() macro seems to give problem
+ Fixed by not using it.
+
+/SunView/Ttysubwindow/Retained still used by SunView but not be defaults editor
+ Defaults file edited by hand.
+
+ Probably changed in v3.2.
+
+File descriptors asociated with TTY subwindows not being closed correctly
+when window destroyed.
+ Hacked by noting their fd number relative to the fd for the frame with
+ the "show fd" menu choice and closing them, hoping that the fds are
+ always allocated in the same order.
+
+ Program later changed so this frame is not destroyed, just undisplayed.
+
+Problem with TTY subwindows in two subframes. If you destroy one but not the
+other the undestroyed frame is displayed with nothing in it.
+ Not fixed yet. Program changed not to have two subframes. This means
+ that the "shell" frame is not permanent but is shared with the "tex",
+ "latex" and "edit" ones.
+
+frame_default_done_proc() is misdefined in /usr/include/suntool/frame.h
+ It should use FRAME_DEFAULT_DONE_PROC. Fixed by editing include file.
diff --git a/dviware/textool/pxlstuff.c b/dviware/textool/pxlstuff.c
new file mode 100644
index 0000000000..c74d431699
--- /dev/null
+++ b/dviware/textool/pxlstuff.c
@@ -0,0 +1,173 @@
+/*
+ * This is the font specific bit of textool.
+ * This version supports PXL format files, which are easy to use but big.
+ */
+
+#include "defs.h"
+#include <stdio.h>
+#include <sys/file.h> /* for access() stuff */
+#include <pixrect/pixrect_hs.h> /* for LoadAChar() */
+char *index();
+char *rindex();
+char *sprintf();
+char *strcpy();
+
+/* procedures in sunstuff */
+extern void Fatal();
+extern void Warning();
+
+/* procedures in dvistuff */
+extern float ActualFactor();
+extern int NoSignExtend();
+extern FILE *OpenFontFile();
+
+/* procedures here */
+void FindFontFile();
+void LoadAChar();
+void ReadCharDefs();
+
+/* a few global variables and data structures */
+#include "globals.h"
+
+/* now to the real code */
+
+/*-->FindFontFile*/
+/**********************************************************************/
+/************************ FindFontFile ******************************/
+/**********************************************************************/
+
+void
+FindFontFile(tfontptr, mag)
+struct font_entry *tfontptr;
+unsigned int mag;
+{
+ char *direct, *tcp, *tcp1;
+ int found;
+ char curarea[STRSIZE];
+
+ tfontptr->font_mag = (int)((ActualFactor((int)(((float)tfontptr->s/
+ (float)tfontptr->d)*1000.0 + 0.5)) *
+#ifdef USEGLOBALMAG
+ ActualFactor(mag) *
+#endif
+ (float)RESOLUTION * 5.0) + 0.5);
+ if (tfontptr->a != 0) {
+ sprintf(tfontptr->name, "%s.%dpxl", tfontptr->n, tfontptr->font_mag);
+ }
+ else {
+ direct = PXLpath;
+ found = FALSE;
+ do {
+ tcp = index(direct, ':');
+ if (tcp == NULL)
+ tcp = strlen(direct) + direct;
+ strncpy(curarea, direct, tcp-direct);
+ tcp1 = curarea + (tcp - direct);
+ *tcp1++ = '/';
+ *tcp1++ = '\0';
+
+ sprintf(tfontptr->name, "%s%s.%dpxl",
+ curarea, tfontptr->n, tfontptr->font_mag);
+ found = (access(tfontptr->name, R_OK) == 0);
+ if (*tcp)
+ direct = tcp + 1;
+ else
+ direct = tcp;
+ } while ( !found && *direct != '\0');
+ }
+}
+
+
+/*-->LoadAChar*/
+/**********************************************************************/
+/***************************** LoadAChar ****************************/
+/**********************************************************************/
+
+void
+LoadAChar(ptr)
+register struct char_entry *ptr;
+{
+ register Pixrect *pr;
+ register int nshorts, i, col, nints;
+ register short *dp, *sp;
+ int buffer[8];
+ FILE *pxlfp;
+
+ pxlfp = OpenFontFile();
+ if (ptr->where.address.fileOffset == 0) {
+ ptr->where.address.pixrectptr = NULL;
+ return;
+ }
+ fseek(pxlfp, ptr->where.address.fileOffset, 0);
+ if ((pr = mem_create(ptr->width, ptr->height, 1)) == NULL) {
+ Fatal("Couldn't allocate pixrect");
+ return;
+ }
+ nshorts = (ptr->width + 15) >> 4;
+ /*
+ * the following test is done because
+ * some bogus font files once caused
+ * the pixrect to be overfilled, damaging
+ * other font data structures
+ */
+ if (nshorts != (((struct mpr_data *)pr->pr_data)->md_linebytes >> 1)) {
+ Fatal("Pixrect too narrow for font");
+ return;
+ }
+ nints = (nshorts + 1) >> 1;
+ dp = ((struct mpr_data *)pr->pr_data)->md_image;
+ for (col = 0; col < ptr->height; col++) {
+ fread(buffer, 4, nints, pxlfp);
+ sp = (short *)&buffer[0];
+ for (i = nshorts; i > 0; i--)
+ *dp++ = *sp++;
+ }
+ ptr->where.address.pixrectptr = pr;
+ ptr->where.isloaded = TRUE;
+}
+
+
+/*-->ReadCharDefs*/
+/**********************************************************************/
+/***************************** ReadCharDefs *************************/
+/**********************************************************************/
+
+void
+ReadCharDefs(tfontptr, pxlfp)
+struct font_entry *tfontptr;
+FILE *pxlfp;
+{
+ int t, i;
+ register struct char_entry *tcharptr; /* temporary char_entry pointer */
+
+ if ((t = NoSignExtend(pxlfp, 4)) != PXLID) {
+ Fatal("PXL ID = %d, can only process PXL ID = %d files",
+ t, PXLID);
+ return;
+ }
+ fseek(pxlfp, -20, 2);
+ t = NoSignExtend(pxlfp, 4);
+ if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
+ Warning("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
+ tfontptr->name, tfontptr->c, t);
+ (void)NoSignExtend(pxlfp, 4); /* throw away magnification */
+ (void)NoSignExtend(pxlfp, 4); /* throw away design size */
+
+ fseek(pxlfp, NoSignExtend(pxlfp, 4) * 4, 0);
+
+ for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
+ tcharptr = &(tfontptr->ch[i]);
+ tcharptr->width = NoSignExtend(pxlfp, 2);
+ tcharptr->height = NoSignExtend(pxlfp, 2);
+ tcharptr->xOffset= SignExtend(pxlfp, 2);
+ tcharptr->yOffset = SignExtend(pxlfp, 2);
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset = NoSignExtend(pxlfp, 4) << 2;
+ tcharptr->tfmw = ((float)NoSignExtend(pxlfp, 4)*(float)tfontptr->s) /
+ (float)(1<<20);
+ }
+ if (BigPreLoad) /* load all char pixrects */
+ for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++)
+ LoadAChar(&(tfontptr->ch[i]));
+}
+
diff --git a/dviware/textool/sunstuff.c b/dviware/textool/sunstuff.c
new file mode 100644
index 0000000000..54457101ba
--- /dev/null
+++ b/dviware/textool/sunstuff.c
@@ -0,0 +1,1620 @@
+/*
+ * This file contains the Sun specific bits of TeXtool, a TeX previewer
+ * derived from the texview posted on the network about spring 86, which
+ * in turn was derived from an earlier version and so on right back to
+ * a version for the BBN Bitgraph.
+ *
+ * This stuff deals with all SunView related things and calls things
+ * in the dvistuff file to do the DVI file and font file stuff, which
+ * in turn calls things in here like SetChar and SetRule to drive the
+ * screen.
+ */
+
+/*
+ * Version 2.1 of 30 Oct 87 -- first real outside release
+ *
+ * -> V2.2, 27 Nov 87 -- fixed bug where .dvi file was opened twice,
+ * once from FrameDoneProc() and once by the WIN_REPAINT
+ * case in CanvasEventProc(). This ran us out of fds.
+ * -> V2.3, 29 Mar 88 -- fixed sloppy code in skip_specials() in
+pkstuff.c
+ * that caused specials
+to be missed and treated as chars.
+
+ */
+
+/* include the various global #defines */
+#include "defs.h"
+
+/* now some definitions for the menu items */
+/*
+ * NOTE: The menu items must be in the positions in the menu given by
+ * these values. This is not done automatically!
+ */
+#define M_NULL 0
+#define M_RESTART 1
+#define M_NEWPAGE 2
+#define M_NEWFILE 3
+#define M_CD 4
+#define M_TEX 5
+#define M_LATEX 6
+#define M_EDIT 7
+#define M_SHELL 8
+#define SM_TOGGLE_P 0x11
+#define SM_TOGGLE_BIGP 0x12
+#define SM_TOGGLE_B 0x13
+#define SM_TOGGLE_M 0x14
+#define DM_TOGGLE_D 0x21
+#define DM_TOGGLE_X 0x22
+#define DM_SHOW_FD 0x23
+#define DM_SHOW_PXL_CACHE 0x24
+
+/* now some Sun include files */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <pixrect/pixrect_hs.h>
+#include <suntool/sunview.h>
+#include <suntool/icon_load.h>
+#include <suntool/canvas.h>
+#include <suntool/scrollbar.h>
+#include <suntool/panel.h>
+#include <suntool/tty.h>
+
+/* general external procedures */
+char *getenv();
+char *index();
+char *rindex();
+char *sprintf();
+char *strcpy();
+char *strcat();
+int strlen();
+char *getwd();
+
+/* procedures from dvistuff */
+extern void CloseDviFile();
+extern void DoPage();
+extern Boolean DviFileChanged();
+extern void FreeFontStorage();
+extern void OpenDviFile();
+#ifdef DEBUG
+extern void ShowPxlFd();
+extern void ShowPxlCache();
+#endif
+
+/* procedures from pxlstuff or pkstuff */
+extern void LoadAChar();
+
+/* procedures in this file */
+void BatchEnd();
+void BatchStart();
+void CanvasEventProc();
+Notify_value CanvasInterposer();
+void CheckFiles();
+void ErrorEventProc();
+char *ExpandTilde();
+void Fatal();
+void FrameDoneProc();
+void InitWindows();
+void MenuCd();
+void MenuEdit();
+Menu MenuGenerate();
+void MenuLatex();
+void MenuNewFile();
+void MenuNewPage();
+void MenuRestart();
+void MenuShell();
+void MenuShortPage();
+void MenuTex();
+void MenuToggleFlag();
+void ProcessPage();
+void RestartDviFile();
+void SetBop();
+void SetChar();
+void SetFrameLabel();
+void SetPageMenu();
+void SetRule();
+Menu ShiftMenuGenerate();
+void SplitFilename();
+void TextInputProc();
+void Warning();
+#ifdef DEBUG
+Menu DebugMenuGenerate();
+void ShowFd();
+#endif
+
+/* now include real global variables needed by both files */
+#define _DEFINE
+#include "globals.h"
+
+/* now the "globals" only needed here */
+
+static char progname[STRSIZE]; /* program name */
+static char ttyinbuf[STRSIZE]; /* for input to ttysubwindow */
+static char dirbuf[STRSIZE]; /* current working dir. */
+static char framelabelbuf[STRSIZE]; /* for frame label */
+static char curarea[STRSIZE]; /* current file area */
+static char curext[STRSIZE]; /* current file extension */
+static char curname[STRSIZE]; /* current file name */
+static char textinputbuffer[STRSIZE]; /* for copying text panel item value */
+static char dviname[STRSIZE]; /* current complete DVI filename */
+static short textinput_state;
+
+/* display related stuff */
+
+static int hh; /* current horizontal position in pixels */
+static int vv; /* current vertical position in pixels */
+static int current_page; /* pagepointers index for current page */
+
+static int xcanvasoffset = RESOLUTION; /* 1 inch offset to match TeX's */
+static int ycanvasoffset = RESOLUTION; /* 1 inch margin on paper */
+
+static Boolean keyscroll; /* bodge to say h,j,k or l typed */
+
+/* SunView defs */
+Frame frame;
+Icon icon;
+Canvas canvas;
+Pixwin *pw;
+Scrollbar vsb, hsb;
+Cursor canvas_cursor;
+Menu menu, tenpagemenu, shiftmenu;
+Menu_item shortpageitem, longpageitem;
+Frame ttyframe;
+Tty ttysubwindow;
+Frame errorframe;
+Panel errorpanel;
+Panel_item errorheader, errormessage;
+Panel_item textinput;
+#ifdef DEBUG
+Menu debugmenu;
+#endif
+
+/* now the real code */
+
+main(argc, argv)
+int argc;
+char *argv[];
+
+{
+
+ extern int optind;
+ extern char *optarg;
+ int c;
+
+ strcpy(progname, argv[0]);
+
+ /* initialse some globals */
+ Debug = FALSE;
+ ExtraDebug = FALSE;
+ PreLoad = FALSE;
+ BigPreLoad = FALSE;
+ Batching = TRUE;
+ main_state = SB_INITIAL;
+ Mflag = FALSE;
+ pagepointers = NULL; /* we haven't malloc'd them yet */
+
+ InitWindows(&argc, argv); /* setup windows and consume -W args */
+
+ current_page = 0; /* start at the beginning */
+
+ /* get enviroment variables for different PXL directories */
+
+ if ((PXLpath=getenv("PXLPATH")) == NULL)
+ PXLpath = PXLFONTAREA;
+ if ((PKpath=getenv("PKPATH")) == NULL)
+ PKpath = PKFONTAREA;
+
+ while ((c = getopt(argc, argv, "dxpPbm:")) != EOF)
+ switch(c) {
+ case 'd': /* d selects Debug output */
+ Debug = TRUE;
+ break;
+
+ case 'x': /* extra debug info for pxl files */
+ ExtraDebug = TRUE;
+ break;
+
+ case 'p': /* p enables font pre-loading */
+ PreLoad = TRUE;
+ break;
+
+ case 'P': /* P enables char pixrect pre-loading */
+ BigPreLoad = TRUE;
+ break;
+
+ case 'b': /* turn batching off for slowness */
+ Batching = FALSE;
+ break;
+
+ case 'm': /* specify mag to override that in DVI file */
+ Mflag = TRUE;
+ user_mag = atoi(optarg);
+ break;
+
+ case '?':
+ default:
+ fprintf(stderr,
+ "usage: textool [-pPb] [-m <mag>] [+n] file\n");
+ exit(1);
+ }
+
+ if ((optind < argc) && (argv[optind][0] == '+'))
+ /* we have starting page number */
+ sscanf(&argv[optind][1], "%d", &current_page);
+
+ if (optind >= argc) {
+ main_state = SB_NOFILE; /* cancel SB_INITIAL status */
+ SplitFilename("<no_file>"); /* _ as icon labels don't like space */
+ }
+ else
+ SplitFilename(argv[optind]);
+ SetFrameLabel();
+
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"going into window_main_loop()\n");
+#endif
+ window_main_loop(frame);
+}
+
+
+/*-->InitWindows*/
+
+void
+InitWindows(argcptr, argv) /* initialize SunView stuff */
+int *argcptr;
+char **argv;
+
+{
+Pixrect *pr1;
+char error[IL_ERRORMSG_SIZE];
+int i;
+
+ pr1 = icon_load_mpr("/u/tex/textool/textool.icon", error);
+ if (pr1 == NULL) /* couldn't load icon */
+ fprintf(stderr, "%s\n", error);
+ /* not Fatal() as windows are not yet active */
+ icon = icon_create(ICON_IMAGE, pr1,
+ 0);
+
+ frame = window_create(0,FRAME,
+ WIN_WIDTH, 900,
+ WIN_HEIGHT, 900,
+ WIN_X, 100,
+ WIN_Y, 0,
+ WIN_SHOW, FALSE,
+ FRAME_LABEL, "TeXtool",
+ FRAME_ICON, icon,
+ FRAME_ARGC_PTR_ARGV, argcptr, argv,
+ 0);
+
+ vsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20,
+ SCROLL_ADVANCED_MODE, TRUE,
+ 0);
+ hsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20,
+ SCROLL_ADVANCED_MODE, TRUE,
+ 0);
+
+ canvas = window_create(frame,CANVAS,
+ CANVAS_AUTO_SHRINK, FALSE,
+ CANVAS_AUTO_EXPAND, FALSE,
+ CANVAS_WIDTH, (17 * RESOLUTION)/2, /* 8.5in */
+ CANVAS_HEIGHT, 12 * RESOLUTION, /* 12in */
+ WIN_VERTICAL_SCROLLBAR, vsb,
+ WIN_HORIZONTAL_SCROLLBAR, hsb,
+ WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,
+ WIN_EVENT_PROC, CanvasEventProc,
+ 0);
+ pw = canvas_pixwin(canvas);
+
+ /* interpose before canvas for pageing */
+ (void)notify_interpose_event_func(canvas, CanvasInterposer, NOTIFY_SAFE);
+
+ scrollbar_scroll_to(hsb, (long)RESOLUTION/2);
+ scrollbar_scroll_to(vsb, (long)RESOLUTION);
+
+ /* now make the menu for canvas */
+ tenpagemenu = menu_create(MENU_ACTION_PROC, MenuShortPage, 0);
+ menu_set(tenpagemenu,
+ MENU_STRING_ITEM, "1", 1,
+ MENU_STRING_ITEM, "2", 2,
+ MENU_STRING_ITEM, "3", 3,
+ MENU_STRING_ITEM, "4", 4,
+ MENU_STRING_ITEM, "5", 5,
+ MENU_STRING_ITEM, "6", 6,
+ MENU_STRING_ITEM, "7", 7,
+ MENU_STRING_ITEM, "8", 8,
+ MENU_STRING_ITEM, "9", 9,
+ MENU_STRING_ITEM, "10", 10,
+ 0);
+
+ shortpageitem = menu_create_item(MENU_PULLRIGHT_ITEM, "go to page",
+ tenpagemenu, 0);
+ longpageitem = menu_create_item(MENU_ACTION_ITEM, "go to page",
+ MenuNewPage, 0);
+
+ menu = menu_create(MENU_GEN_PROC, MenuGenerate,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "restart DVI file", MenuRestart,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "new file", MenuNewFile,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "change directory", MenuCd,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "run tex", MenuTex,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "run latex", MenuLatex,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "edit .tex file", MenuEdit,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "shell", MenuShell,
+ 0,0);
+ menu_set(menu, MENU_INSERT, 1, shortpageitem, 0);
+
+ /* now a second menu for shift-right button */
+ shiftmenu = menu_create(MENU_GEN_PROC, ShiftMenuGenerate,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, SM_TOGGLE_P,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, SM_TOGGLE_BIGP,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, SM_TOGGLE_B,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, SM_TOGGLE_M,
+ 0,0);
+
+#ifdef DEBUG
+ /* now a debug menu for the meta key */
+ debugmenu = menu_create(MENU_GEN_PROC, DebugMenuGenerate,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, DM_TOGGLE_D,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_PROC, MenuToggleFlag,
+ MENU_VALUE, DM_TOGGLE_X,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "show fd", ShowFd,
+ MENU_VALUE, DM_SHOW_FD,
+ 0,
+ MENU_ITEM,
+ MENU_ACTION_ITEM, "show PXL cache", ShowPxlCache,
+ MENU_VALUE, DM_SHOW_PXL_CACHE,
+ 0,0);
+#endif DEBUG
+
+ /* now create a frame and panel for errors */
+
+ errorframe = window_create(frame, FRAME,
+ FRAME_NO_CONFIRM, TRUE,
+ WIN_SHOW, FALSE,
+ WIN_COLUMNS, 80,
+ WIN_ROWS, 2,
+ WIN_X, 100,
+ WIN_Y, 100,
+ 0);
+ errorpanel = window_create(errorframe, PANEL,
+ PANEL_BACKGROUND_PROC, ErrorEventProc,
+ PANEL_EVENT_PROC, ErrorEventProc,
+ 0);
+ errorheader = panel_create_item(errorpanel, PANEL_MESSAGE,
+ PANEL_LABEL_STRING, "TeXtool Warning:",
+ 0);
+ errormessage = panel_create_item(errorpanel, PANEL_MESSAGE,
+ PANEL_LABEL_STRING, "dummy message",
+ 0);
+ textinput = panel_create_item(errorpanel, PANEL_TEXT,
+ PANEL_LABEL_STRING, "Magnification:",
+ PANEL_ITEM_Y, ATTR_ROW(1),
+ PANEL_ITEM_X, ATTR_COL(0),
+ PANEL_SHOW_ITEM, FALSE,
+ PANEL_VALUE_DISPLAY_LENGTH, 40,
+ PANEL_NOTIFY_PROC, TextInputProc,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ /* create shell window for TeX, etc */
+ ttyframe = window_create(frame, FRAME,
+ FRAME_LABEL, "TeXtool Shell",
+ FRAME_SHOW_LABEL, TRUE,
+ FRAME_NO_CONFIRM, TRUE,
+ FRAME_DONE_PROC, FrameDoneProc,
+ WIN_X, 25,
+ WIN_Y, 25,
+ WIN_SHOW, FALSE,
+ 0);
+ ttysubwindow = window_create(ttyframe, TTY,
+ 0);
+}
+
+
+/*-->SetFrameLabel*/
+
+void
+SetFrameLabel()
+{
+ if (pagepointers == NULL)
+ sprintf(framelabelbuf,
+ "TeXtool: Directory: %s File: %s%s%s",
+ getwd(dirbuf), curarea, curname, curext);
+ else
+ sprintf(framelabelbuf,
+ "TeXtool: Directory: %s File: %s%s%s \"Page\": %d \\count0: %d",
+ getwd(dirbuf), curarea, curname, curext,
+ current_page+1, pagepointers[current_page].count_0);
+
+
+ window_set(frame, FRAME_LABEL, framelabelbuf, 0);
+}
+
+
+ /*
+ * Now two procs to deal with canvas input.
+ * CanvasInterposer is called first and filters out
+ * the vertical scroll page requests, turning them into
+ * calls of ProcessPage.
+ * CanvasEventProc handles all other input cases.
+ */
+/*-->CanvasInterposer*/
+
+Notify_value
+CanvasInterposer(object, event, arg, type)
+Canvas object;
+Event *event;
+Notify_arg arg;
+Notify_event_type type;
+{
+ Scroll_motion motion;
+ Notify_value retval;
+
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"Interposer called (%d) - ", event_id(event));
+ if (Debug) fprintf(stderr,
+ "\nobject = %X, *event = %X, arg = %X, type = %X\n",
+ object, event, arg, type);
+#endif
+ if (event_id(event) == SCROLL_REQUEST) {
+ if ((Scrollbar)arg == vsb) {
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"arg is vsb, ");
+#endif
+ motion = (Scroll_motion)scrollbar_get(vsb, SCROLL_REQUEST_MOTION);
+ if (!keyscroll && ((motion == SCROLL_PAGE_FORWARD)
+ || (motion == SCROLL_PAGE_BACKWARD))) {
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"motion is %X (PAGE), ", (int)motion);
+#endif
+ /* now tell bar to undo scroll */
+ scrollbar_set(vsb, SCROLL_VIEW_START,
+ scrollbar_get(vsb, SCROLL_LAST_VIEW_START), 0);
+ if (motion == SCROLL_PAGE_BACKWARD) {
+ if (current_page-- > 0)
+ ProcessPage(current_page);
+ else
+ current_page++;
+ }
+ else {
+ if (++current_page < totalpages)
+ ProcessPage(current_page);
+ else
+ current_page--;
+ }
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"Interposer return (DONE)\n");
+#endif
+ return (NOTIFY_DONE);
+ }
+ }
+ }
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"calling next func\n");
+#endif
+ retval = (notify_next_event_func(object, event, arg, type));
+ if (Debug) fprintf(stderr, "Interposer return (%X)\n", retval);
+ return (retval);
+}
+
+
+/*-->CanvasEventProc*/
+
+void
+CanvasEventProc(notused, event)
+Canvas notused;
+Event *event;
+{
+ static int intval;
+
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"event proc called (id = %d) - ",
+ event_id(event));
+#endif
+
+ keyscroll = FALSE;
+ switch (event_id(event)) {
+ case '\n':
+ case '\r':
+ if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER)) {
+ if ((main_state & SB_MINUSNUMBER)
+ && (current_page -= intval) < 0)
+ current_page = 0;
+ if ((main_state & SB_PLUSNUMBER)
+ && (current_page += intval) >= totalpages)
+ current_page = totalpages-1;
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ ProcessPage(current_page);
+ break;
+ } /* else fall into next page case */
+ case ' ': /* normal case - start next page */
+ case 'n':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ if (++current_page < totalpages)
+ ProcessPage(current_page);
+ else
+ current_page--;
+ break;
+
+ case 'b':
+ case 'P':
+ case 'p': /* redisplay from previous page */
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ if (current_page-- > 0)
+ ProcessPage(current_page);
+ else
+ current_page++;
+ break;
+
+#ifdef KEYBOARDSCROLL
+ case 'j':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ keyscroll = TRUE;
+ scrollbar_scroll_to(vsb, (long)600);
+ break;
+
+ case 'h':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ keyscroll = TRUE;
+ scrollbar_scroll_to(hsb, (long)0);
+ break;
+
+ case 'l':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ keyscroll = TRUE;
+ scrollbar_scroll_to(hsb, (long)300);
+ break;
+
+ case 'k':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ keyscroll = TRUE;
+ scrollbar_scroll_to(vsb, (long)0);
+ break;
+
+ case 'c':
+ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER);
+ main_state |= SB_INTERPRET;
+ keyscroll = TRUE;
+ scrollbar_scroll_to(vsb, (long)RESOLUTION);
+ scrollbar_scroll_to(hsb, (long)(RESOLUTION/2));
+ break;
+#endif
+
+#ifdef DEBUG
+ case SCROLL_REQUEST: /* scroll request, after Sb gets it */
+ { int a, b, c, d;
+ if (Debug) {
+ a = (int)scrollbar_get(vsb, SCROLL_VIEW_START);
+ b = (int)scrollbar_get(vsb, SCROLL_LAST_VIEW_START);
+ c = (int)scrollbar_get(hsb, SCROLL_VIEW_START);
+ d = (int)scrollbar_get(hsb, SCROLL_LAST_VIEW_START);
+ fprintf(stderr,"\nVsb scroll from %d to %d\n", b, a);
+ fprintf(stderr,"Hsb scroll from %d to %d\n", d, c);
+ }
+ }
+ break;
+
+#endif
+ case '-':
+ /* read in val */
+ main_state |= SB_MINUSNUMBER;
+ intval = 0;
+ break;
+
+ case '+':
+ /* read in val */
+ main_state |= SB_PLUSNUMBER;
+ intval = 0;
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER))
+ intval = intval*10 + (event_id(event) - '0');
+ break;
+
+ case '\b':
+ case 127: /* delete key */
+ if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER))
+ intval /= 10;
+ break;
+
+ case MS_RIGHT:
+ if (event_is_up(event)) break;
+#ifdef DEBUG
+ if (event_meta_is_down(event)) {
+ (void)menu_show(debugmenu, canvas,
+ canvas_window_event(canvas, event), 0);
+ break;
+ }
+#endif
+ if (event_shift_is_down(event))
+ (void)menu_show(shiftmenu, canvas,
+ canvas_window_event(canvas, event), 0);
+ else
+ (void)menu_show(menu, canvas,
+ canvas_window_event(canvas, event), 0);
+ break;
+
+ case MS_LEFT:
+ canvas_cursor = window_get(canvas, WIN_CURSOR);
+ if (event_is_up(event)) {
+ cursor_set(canvas_cursor,
+ CURSOR_SHOW_CURSOR, TRUE,
+ CURSOR_SHOW_CROSSHAIRS, FALSE,
+ 0);
+ }
+ else {
+ /*
+ * All these except the pixrect op
+ * are defaults but it does not seem
+ * to work unles they are specified
+ */
+ cursor_set(canvas_cursor,
+ CURSOR_SHOW_CURSOR, FALSE,
+ CURSOR_CROSSHAIR_COLOR, 1,
+ CURSOR_CROSSHAIR_THICKNESS, 1,
+ CURSOR_CROSSHAIR_GAP, 0,
+ CURSOR_CROSSHAIR_LENGTH, CURSOR_TO_EDGE,
+ CURSOR_CROSSHAIR_OP, PIX_SRC|PIX_DST,
+ CURSOR_SHOW_CROSSHAIRS, TRUE,
+ 0);
+ }
+ window_set(canvas, WIN_CURSOR, canvas_cursor, 0);
+ break;
+
+ case WIN_REPAINT:
+ if (main_state & SB_INITIAL) { /* first time of display */
+ main_state &= ~SB_INITIAL;
+ CheckFiles(); /* sets main_state */
+ OpenDviFile(dviname);
+ if (main_state & (SB_NOFILE | SB_NODVIFILE))
+ break;
+ SetPageMenu();
+ main_state &= ~SB_NEWFILE;
+ main_state |= SB_INTERPRET;
+ ProcessPage(current_page);
+ }
+ break;
+
+ default:
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"event proc default case - ");
+#endif
+ }
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"event proc return\n");
+#endif
+}
+
+
+ /*
+ * Now the procedures that actually do the work of
+ * drawing on the screen. These get called from
+ * dvistuff to prevent it having to know about
+ * SunView.
+ * SetBop just clears the screen and sets the initial
+ * offset. SetChar and SetRule draw text and lines.
+ */
+/*-->SetBop*/
+
+void
+SetBop()
+{
+ pw_writebackground(pw, 0, 0,
+ pw->pw_prretained->pr_size.x, pw->pw_prretained->pr_size.y,
+ PIX_CLR);
+ /*
+ * Start with h and v at offset point rather than 0,0.
+ * This means that offset does not need to be added in
+ * on every call to SetChar and SetRule.
+ */
+ h = xcanvasoffset * hconv;
+ v = ycanvasoffset * vconv;
+}
+
+
+/*-->SetChar*/
+
+void
+SetChar(charptr, Set)
+struct char_entry *charptr;
+Boolean Set;
+{
+ hh = PixRound(h, hconv);
+ vv = PixRound(v, vconv);
+ if (!charptr->where.isloaded) LoadAChar(charptr);
+ if (charptr->where.isloaded == TRUE)
+ pw_rop(pw, hh-charptr->xOffset,
+ vv-charptr->yOffset,
+ charptr->width, charptr->height, PIX_SRC | PIX_DST,
+ charptr->where.address.pixrectptr, 0, 0);
+ if (Set)
+ h += charptr->tfmw;
+}
+
+
+/*-->SetRule*/
+
+void
+SetRule(a, b, Set)
+int a, b;
+Boolean Set;
+
+{ /* this routine draws \hrule and \vrule */
+ int ehh, evv;
+
+ hh = PixRound(h, hconv);
+ vv = PixRound(v-a, vconv);
+ ehh = PixRound(h + b, hconv);
+ evv = PixRound(v, vconv);
+ if (hh == ehh) ehh++;
+ if (vv == evv) vv--;
+ if ((a > 0) && (b > 0))
+ pw_rop(pw, hh, vv,
+ ehh-hh, evv-vv, PIX_SET, NULL, 0, 0);
+ if (Set)
+ h += b;
+}
+
+
+ /*
+ * These next two are only procedures here to avoid
+ * having dvistuff.c know about Pixwins.
+ * As they are only called once per page the loss of
+ * speed is not a problem.
+ */
+/*-->BatchStart*/
+
+void
+BatchStart()
+{
+ pw_batch_on(pw);
+}
+
+
+/*-->BatchEnd*/
+
+void
+BatchEnd()
+{
+ pw_batch_off(pw);
+}
+
+
+ /*
+ * Now two procedures that call on things in
+ * dvistuff to get pages displayed.
+ */
+/*-->ProcessPage*/
+
+void
+ProcessPage(page)
+int page;
+{
+ if (DviFileChanged())
+ RestartDviFile();
+ SetFrameLabel();
+ DoPage(page);
+}
+
+
+/*-->RestartDviFile*/
+
+void
+RestartDviFile()
+{
+ CloseDviFile();
+ FreeFontStorage();
+ main_state &= (~SB_INTERPRET & ~SB_NOFILE);
+/* main_state |= SB_NEWFILE; /* to allow a try at open */
+ CheckFiles(); /* sets main_state */
+ OpenDviFile(dviname);
+ if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */
+ return;
+ SetPageMenu();
+ main_state &= ~SB_NEWFILE; /* SB_NEWFILE must be set to get to here */
+ main_state |= SB_INTERPRET;
+}
+
+
+ /*
+ * Now to the menu generating procedures, one for
+ * each menu. There is also a procedure to set
+ * the "go to page" menu item depending on the
+ * number of pages.
+ * MenuGenerate() deals with most of the interlocking
+ * to avoid illegal menu choices.
+ */
+/*-->MenuGenerate*/
+
+Menu
+MenuGenerate(object, operation)
+Menu object;
+Menu_generate operation;
+{
+ if (operation == MENU_CREATE) {
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_RESTART),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE ) ?
+ TRUE : FALSE),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_NEWPAGE),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE) ?
+ TRUE : FALSE),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_TEX),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE |
+ SB_NOTEXFILE) ? TRUE : FALSE),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_LATEX),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE |
+ SB_NOTEXFILE) ? TRUE : FALSE),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_EDIT),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE) ?
+ TRUE : FALSE),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, M_SHELL),
+ MENU_INACTIVE,
+ (main_state & (SB_TEXING | SB_EDITING | SB_SHELL) ?
+ TRUE : FALSE),
+ 0);
+ }
+ return (object);
+
+}
+
+
+/*-->ShiftMenuGenerate*/
+
+Menu
+ShiftMenuGenerate(object, operation)
+Menu object;
+Menu_generate operation;
+{
+ if (operation == MENU_CREATE) {
+ menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_P & 0xF),
+ MENU_STRING, (PreLoad ? "reset -p flag" : "set -p flag"),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_B & 0xF),
+ MENU_STRING, (Batching ? "set -b flag" : "reset -b flag"),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_BIGP & 0xF),
+ MENU_STRING, (BigPreLoad ? "reset -P flag" : "set -P flag"),
+ 0);
+#ifdef USEGLOBALMAG
+ menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_M & 0xF),
+ MENU_STRING, (Mflag ? "reset -m flag" : "set -m flag"),
+ 0);
+#endif
+ }
+ return (object);
+}
+
+
+#ifdef DEBUG
+/*-->DebugMenuGenerate*/
+
+Menu
+DebugMenuGenerate(object, operation)
+Menu object;
+Menu_generate operation;
+{
+ if (operation == MENU_CREATE) {
+ menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_D & 0xF),
+ MENU_STRING, (Debug ? "reset -d flag" : "set -d flag"),
+ 0);
+ menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_X & 0xF),
+ MENU_STRING, (ExtraDebug ? "reset -x flag" : "set -x flag"),
+ 0);
+ }
+ return (object);
+}
+#endif DEBUG
+
+
+/*-->SetPageMenu*/
+
+void
+SetPageMenu()
+{
+ short i;
+
+ if (totalpages > 10)
+ menu_set(menu,
+ MENU_REPLACE, 2, longpageitem,
+ 0);
+ else {
+ menu_set(menu,
+ MENU_REPLACE, 2, shortpageitem,
+ 0);
+ for (i = 0; i < 10; i++)
+ menu_set(menu_get(tenpagemenu, MENU_NTH_ITEM, i+1, 0),
+ MENU_INACTIVE, (i < totalpages ? FALSE : TRUE),
+ 0);
+ }
+}
+
+
+ /*
+ * Now the action procs called after a menu selection
+ * is made.
+ */
+/*-->MenuRestart*/
+
+void
+MenuRestart(object, item)
+Menu object;
+Menu_item item;
+{
+ window_release_event_lock(canvas); /* "I may be some time" */
+ current_page = 0;
+ RestartDviFile();
+ DoPage(current_page);
+}
+
+
+/*-->MenuNewPage*/
+
+void
+MenuNewPage(object, item)
+Menu object;
+Menu_item item;
+{
+ panel_set(textinput,
+ PANEL_LABEL_STRING, "Page number:",
+ PANEL_VALUE, "",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errorheader,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, "",
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+ textinput_state = M_NEWPAGE;
+}
+
+
+/*-->MenuShortPage*/
+
+void
+MenuShortPage(object, item)
+Menu object;
+Menu_item item;
+{
+ current_page = (int)menu_get(item, MENU_VALUE, 0);
+ current_page--; /* as current_page =0 for page 1 */
+ if (current_page >= totalpages)
+ current_page = totalpages - 1;
+ ProcessPage(current_page);
+}
+
+
+/*-->MenuNewFile*/
+
+void
+MenuNewFile(object, item)
+Menu object;
+Menu_item item;
+{
+ panel_set(textinput,
+ PANEL_LABEL_STRING, "Filename:",
+ PANEL_VALUE, "",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errorheader,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, "",
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+ textinput_state = M_NEWFILE;
+}
+
+
+/*-->MenuCd*/
+
+void
+MenuCd(object, item)
+Menu object;
+Menu_item item;
+{
+ panel_set(textinput,
+ PANEL_LABEL_STRING, "Directory:",
+ PANEL_VALUE, "",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errorheader,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, "",
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+ textinput_state = M_CD;
+}
+
+
+/*-->MenuTex*/
+
+void
+MenuTex(object, item)
+Menu object;
+Menu_item item;
+{
+ strcpy(ttyinbuf, "cd ");
+ strcat(ttyinbuf, getwd(dirbuf));
+ strcat(ttyinbuf, "\ntex ");
+ strcat(ttyinbuf, curname);
+ strcat(ttyinbuf, ".tex\n");
+ (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
+ main_state |= SB_TEXING;
+ window_set(ttyframe, WIN_SHOW, TRUE, 0);
+}
+
+
+/*-->MenuLatex*/
+
+void
+MenuLatex(object, item)
+Menu object;
+Menu_item item;
+{
+ strcpy(ttyinbuf, "cd ");
+ strcat(ttyinbuf, getwd(dirbuf));
+ strcat(ttyinbuf, "\nlatex ");
+ strcat(ttyinbuf, curname);
+ strcat(ttyinbuf, ".tex\n");
+ (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
+ main_state |= SB_TEXING;
+ window_set(ttyframe, WIN_SHOW, TRUE, 0);
+}
+
+
+/*-->MenuEdit*/
+
+void
+MenuEdit(object, item)
+Menu object;
+Menu_item item;
+{
+ char *tcp;
+
+ if ((tcp = getenv("EDITOR")) == NULL)
+ tcp = "vi";
+ strcpy(ttyinbuf, tcp);
+ strcat(ttyinbuf, " ");
+ strcat(ttyinbuf, getwd(dirbuf));
+ strcat(ttyinbuf, "/");
+ strcat(ttyinbuf, curname);
+ strcat(ttyinbuf, ".tex\n");
+ (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf));
+ main_state |= SB_EDITING;
+ window_set(ttyframe, WIN_SHOW, TRUE, 0);
+}
+
+
+/*-->MenuShell*/
+
+void
+MenuShell(object, item)
+Menu object;
+Menu_item item;
+{
+ main_state |= SB_SHELL;
+ window_set(ttyframe, WIN_SHOW, TRUE, 0);
+}
+
+
+/*-->MenuToggleFlag*/
+
+void
+MenuToggleFlag(object, item)
+Menu object;
+Menu_item item;
+{
+ int itemvalue;
+
+ itemvalue = (int)menu_get(item, MENU_VALUE, 0);
+
+ switch (itemvalue) {
+#ifdef DEBUG
+ case DM_TOGGLE_D:
+ Debug ^= 1;
+ break;
+ case DM_TOGGLE_X:
+ ExtraDebug ^= 1;
+ break;
+#endif
+ case SM_TOGGLE_P:
+ PreLoad ^= 1;
+ break;
+ case SM_TOGGLE_B:
+ Batching ^= 1;
+ break;
+ case SM_TOGGLE_BIGP:
+ BigPreLoad ^= 1;
+ break;
+#ifdef USEGLOBALMAG
+ case SM_TOGGLE_M:
+ Mflag ^= 1;
+ if (Mflag) {
+ panel_set(textinput,
+ PANEL_LABEL_STRING, "Magnification:",
+ PANEL_VALUE, "",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errorheader,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, "",
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+ textinput_state = SM_TOGGLE_M;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+
+ /*
+ * The event proc for the panel which contains the
+ * error message item and the text input item.
+ * If the panel event is an ascii one it passes it
+ * on to the text input item. It removes the panel
+ * on a left mouse button.
+ */
+/*-->ErrorEventProc*/
+
+void
+ErrorEventProc(object, event)
+Panel object;
+Event *event;
+{
+ if (event_id(event) <= ASCII_LAST)
+ panel_accept_key(textinput, event);
+ else if (event_id(event) == MS_LEFT)
+ window_set(errorframe,
+ WIN_SHOW, FALSE,
+ 0);
+}
+
+
+ /*
+ * The notify proc for the panel text input item.
+ * This gets things like page numbers and filenames
+ * from the user.
+ */
+/*-->TextInputProc*/
+
+void
+TextInputProc(item, event)
+Panel_item item;
+Event *event;
+{
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"TextInputProc(): panel_get_value returns %s\n",
+ (char *)panel_get_value(textinput));
+#endif
+ strcpy(textinputbuffer, (char *)panel_get_value(textinput));
+ window_set(errorframe,
+ WIN_SHOW, FALSE,
+ 0);
+ if (*textinputbuffer == NULL)
+ return;
+ switch(textinput_state) {
+ case M_NEWPAGE:
+ sscanf(textinputbuffer, "%d", &current_page);
+ current_page--;
+ if (current_page >= totalpages)
+ current_page = totalpages - 1;
+ ProcessPage(current_page);
+ break;
+
+ case M_NEWFILE:
+ window_release_event_lock(errorframe);
+ /* as this may take some time */
+ SplitFilename(ExpandTilde(textinputbuffer));
+ /* sets dviname */
+ CloseDviFile(); /* from dvifp */
+ FreeFontStorage();
+ SetBop(); /* clear screen */
+ current_page = 0;
+ main_state &= (~SB_INTERPRET & ~SB_NOFILE);
+ CheckFiles(); /* see what's there */
+ OpenDviFile(dviname); /* sets dvifp */
+ SetFrameLabel();
+ if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */
+ break;
+ SetPageMenu();
+ main_state &= ~SB_NEWFILE;
+ main_state |= SB_INTERPRET;
+ DoPage(current_page);
+ break;
+
+ case M_CD:
+ if (chdir(ExpandTilde(textinputbuffer)))
+ Warning("Couldn't change directory");
+ SetFrameLabel();
+ break;
+
+ case SM_TOGGLE_M:
+ user_mag = atoi(textinputbuffer);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+ /*
+ * The done proc for the frame with the tty subwindow.
+ * It removes the frame and adjusts the display if the
+ * DVI file has changed.
+ */
+/*-->FrameDoneProc*/
+
+void
+FrameDoneProc(object)
+Frame object;
+{
+ int i;
+
+ if (Debug) {
+ fprintf(stderr,
+ "FrameDoneProc(), object = %X, frame = %X, ttyframe = %X\n",
+ object, frame, ttyframe);
+ fprintf(stderr,"calling default done proc for object\n");
+ }
+ frame_default_done_proc(object);
+ main_state &= (~SB_TEXING & ~SB_EDITING & ~SB_SHELL);
+ CheckFiles(); /* see if anything changed */
+ if (main_state & SB_NEWFILE) { /* we haven't seen it before */
+ OpenDviFile(dviname);
+ if (main_state & SB_NOFILE)/* can't have NODVIFILE as NEWFILE was set */
+ return;
+ main_state &= ~SB_NEWFILE;
+ main_state |= SB_INTERPRET;
+ DoPage(current_page);
+ }
+ else if (DviFileChanged()) {
+ RestartDviFile();
+ DoPage(current_page);
+ }
+}
+
+
+ /*
+ * Now some utility procedures.
+ */
+/*-->SplitFilename*/
+
+void
+SplitFilename(nameptr)
+char *nameptr;
+{
+ char *tcp, *tcp1;
+ Icon temp_icon; /* for changing label */
+ /* process filename */
+ tcp = rindex(nameptr, '/');
+ if (tcp == NULL) {
+ curarea[0] = '\0';
+ tcp = nameptr;
+ }
+ else {
+ strncpy(curarea, nameptr, tcp-nameptr+1);
+ curarea[tcp-nameptr+1] = '\0'; /* as strncpy will not do this */
+ tcp += 1;
+ }
+ tcp1 = index(tcp, '.');
+ if (tcp1 == NULL) {
+ strcpy(curname, tcp);
+ curext[0] = '\0';
+ }
+ else {
+ strncpy(curname, tcp, tcp1-tcp);
+ strcpy(curext, tcp1);
+ }
+
+ strcpy(dviname, curarea);
+ strcat(dviname, curname);
+ if (curext[0] == '\0')
+ strcat(dviname, ".dvi");
+ else
+ strcat(dviname, curext);
+#ifdef DEBUG
+ if (Debug) {
+ fprintf(stderr,"curarea = %s\n", curarea);
+ fprintf(stderr,"curname = %s\nsetting icon label to curname\n",
+ curname);
+ fprintf(stderr,"curext = %s\n", curext);
+ fprintf(stderr,"dviname = %s\n", dviname);
+ }
+#endif
+ temp_icon = (Icon)window_get(frame, FRAME_ICON, 0);
+ icon_set(temp_icon, ICON_LABEL, curname, 0);
+ window_set(frame, FRAME_ICON, temp_icon, 0);
+}
+
+
+ /*
+ * CheckFiles tries access on the .dvi file,
+ * and if that does not exist, on the .tex file
+ * and sets main_state accordingly.
+ */
+/*-->CheckFiles*/
+
+void
+CheckFiles()
+{
+ char buf[STRSIZE];
+
+ if (access(dviname, F_OK | R_OK) == 0) { /* .dvi file present */
+ if (main_state & SB_NODVIFILE) /* first time .dvi file found */
+ main_state |= SB_NEWFILE;
+ main_state &= (~SB_NODVIFILE & ~SB_NOTEXFILE);
+ }
+ else {
+ strcpy(buf, curarea);
+ strcat(buf, curname);
+ strcat(buf, ".tex");
+ if (access(buf, F_OK | R_OK) == 0) { /* no .dvi file but .tex file ok */
+ main_state |= SB_NODVIFILE;
+ main_state &= (~SB_NEWFILE & ~SB_NOTEXFILE);
+ }
+ else { /* no .tex file either */
+ main_state |= SB_NODVIFILE | SB_NOTEXFILE;
+ main_state &= ~SB_NEWFILE;
+ }
+ }
+
+}
+
+
+/*-->ExpandTilde*/
+
+char *
+ExpandTilde(iptr)
+char *iptr;
+{
+ char buff[STRSIZE];
+ char *tptr;
+ struct passwd *passwdptr;
+
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"ExpandTilde(%s) - ", iptr);
+#endif
+ if (*iptr == '~') { /* something to do */
+ strcpy(buff, iptr);
+ tptr = index(buff, '/');
+ if ((strlen(buff) == 1) || ((tptr-buff) == 1))
+ /* expand to our $HOME */
+ strcpy(iptr, getenv("HOME"));
+ else { /* ~name/... form */
+ if (tptr != NULL) *tptr = 0;
+ if ((passwdptr = getpwnam(&buff[1])) != NULL)
+ strcpy(iptr, passwdptr->pw_dir);
+ if (tptr != NULL) *tptr = '/';
+ }
+ if (tptr != NULL)
+ strcat(iptr, tptr); /* complete rest of path if there is any */
+ }
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,"returns %s\n", iptr);
+#endif
+ return (iptr);
+}
+
+
+ /*
+ * Two error message procedures.
+ * Warning just displays the message, Error displays
+ * and then abandons the DVI file and goes to the
+ * NOFILE state.
+ */
+/*-->Warning*/
+
+void
+Warning(fmt, arg1, arg2, arg3, arg4) /* issue a warning */
+char *fmt; /* format */
+char *arg1, *arg2, *arg3, *arg4; /* arguments */
+{
+ char message[STRSIZE];
+
+ sprintf(message, fmt, arg1, arg2, arg3, arg4);
+
+ panel_set(errorheader,
+ PANEL_LABEL_STRING, "TeXtool Warning:",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, message,
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(textinput,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+}
+
+
+/*-->Fatal*/
+
+void
+Fatal(fmt, arg1, arg2, arg3, arg4)/* issue a fatal error message */
+char *fmt; /* format */
+char *arg1, *arg2, *arg3, *arg4; /* arguments */
+
+{
+ char message[STRSIZE];
+
+ sprintf(message, fmt, arg1, arg2, arg3, arg4);
+ panel_set(errorheader,
+ PANEL_LABEL_STRING, "TeXtool Error:",
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(errormessage,
+ PANEL_LABEL_STRING, message,
+ PANEL_SHOW_ITEM, TRUE,
+ 0);
+ panel_set(textinput,
+ PANEL_SHOW_ITEM, FALSE,
+ 0);
+ window_fit(errorpanel);
+ window_fit(errorframe);
+ window_set(errorframe,
+ WIN_X, 100,
+ WIN_Y, 100,
+ WIN_SHOW, TRUE,
+ 0);
+ CloseDviFile();
+ FreeFontStorage(); /* to get to known stable state */
+ main_state |= SB_NOFILE; /* to stop further processing */
+ main_state &= (~SB_NEWFILE & ~SB_NODVIFILE & ~SB_NOTEXFILE & ~SB_INTERPRET);
+ SplitFilename("<no_file>");
+ SetFrameLabel();
+}
+
+
+#ifdef DEBUG
+ /*
+ * A procedure to show the fds we are using.
+ * There was a leak of fds somewhere where ptys were
+ * not closed when a frame with a tty subwindow in it
+ * was destroyed and this was used to find it.
+ * The tty subframe is now not destroyed but just
+ * undisplayed to cure the problem.
+ * It also shows the huge number of fds needed by
+ * SunView which cuts down on the number available for
+ * PXL file caching.
+ */
+/*-->ShowFd*/
+
+void
+ShowFd(object, item)
+Menu object;
+Menu_item item;
+{
+ short i;
+ struct stat statbuf;
+
+ fprintf(stderr,"frame %d, win%d\n",
+ window_get(frame, WIN_FD), window_get(frame, WIN_DEVICE_NUMBER));
+ fprintf(stderr,"canvas %d, win%d\n",
+ window_get(canvas, WIN_FD), window_get(canvas, WIN_DEVICE_NUMBER));
+ fprintf(stderr,"ttyframe %d, win%d\n",
+ window_get(ttyframe, WIN_FD), window_get(ttyframe, WIN_DEVICE_NUMBER));
+ fprintf(stderr,"ttysubwindow %d, win%d\n",
+ window_get(ttysubwindow, WIN_FD),
+ window_get(ttysubwindow, WIN_DEVICE_NUMBER));
+ fprintf(stderr,"errorframe %d, win%d\n",
+ window_get(errorframe, WIN_FD), window_get(errorframe, WIN_DEVICE_NUMBER));
+ fprintf(stderr,"errorpanel %d, win%d\n",
+ window_get(errorpanel, WIN_FD), window_get(errorpanel, WIN_DEVICE_NUMBER));
+ ShowPxlFd();
+
+ for (i=0; i<30; i++) /* enumerate fds */
+ if (fstat(i,&statbuf) == 0)
+ fprintf(stderr,"fd %d open, type = %o, inode = %d\n",
+ i,
+ statbuf.st_mode & S_IFMT,
+ statbuf.st_ino);
+}
+#endif
+
diff --git a/dviware/textool/textool.fix b/dviware/textool/textool.fix
new file mode 100644
index 0000000000..aae1373855
--- /dev/null
+++ b/dviware/textool/textool.fix
@@ -0,0 +1,92 @@
+*** sunstuff.c Tue Mar 29 08:06:23 1988
+--- sunstuff.c.old Tue Mar 29 08:02:13 1988
+***************
+*** 16,23 ****
+ * -> V2.2, 27 Nov 87 -- fixed bug where .dvi file was opened twice,
+ * once from FrameDoneProc() and once by the WIN_REPAINT
+ * case in CanvasEventProc(). This ran us out of fds.
+- * -> V2.3, 29 Mar 88 -- fixed sloppy code in skip_specials() in pkstuff.c
+- * that caused specials to be missed and treated as chars.
+ */
+
+ /* include the various global #defines */
+--- 16,21 ----
+*** pkstuff.c Tue Mar 29 08:05:07 1988
+--- pkstuff.c.old Tue Mar 29 08:02:03 1988
+***************
+*** 5,15 ****
+ * See the pktopx documentation for details.
+ */
+
+- /*
+- * For V2.3, 29 Mar 88
+- * Fixed stupid errors in skip_specials() that caused specials to be missed
+- */
+-
+ #include "defs.h"
+ #include <stdio.h>
+ #include <sys/file.h> /* for access() stuff */
+--- 5,10 ----
+***************
+*** 190,200 ****
+ case PK_XXX4:
+ i = get_pk_byte();
+ case PK_XXX3:
+! i = (i<<8) + get_pk_byte();
+ case PK_XXX2:
+! i = (i<<8) + get_pk_byte();
+ case PK_XXX1:
+! i = (i<<8) + get_pk_byte();
+ while (i--)
+ (void)get_pk_byte();
+ break;
+--- 185,195 ----
+ case PK_XXX4:
+ i = get_pk_byte();
+ case PK_XXX3:
+! i = i<<8 + get_pk_byte();
+ case PK_XXX2:
+! i = i<<8 + get_pk_byte();
+ case PK_XXX1:
+! i = i<<8 + get_pk_byte();
+ while (i--)
+ (void)get_pk_byte();
+ break;
+***************
+*** 215,221 ****
+ flag_byte);
+ return;
+ }
+! } while (flag_byte >= PK_XXX1);
+ }
+
+
+--- 210,216 ----
+ flag_byte);
+ return;
+ }
+! } while (flag_byte > PK_XXX1);
+ }
+
+
+*** textool.l Tue Mar 29 09:24:36 1988
+--- textool.l.old Tue Mar 29 09:24:09 1988
+***************
+*** 187,193 ****
+ The following things are taken from the environment:
+ .TP
+ .B PKPATH
+! A colon separated list of directories to search for the font PK files
+ in place of the default described below.
+ .TP
+ .B HOME
+--- 187,193 ----
+ The following things are taken from the environment:
+ .TP
+ .B PKPATH
+! A comma separated list of directories to search for the font PK files
+ in place of the default described below.
+ .TP
+ .B HOME
+
+End of diffs.
diff --git a/dviware/textool/textool.icon b/dviware/textool/textool.icon
new file mode 100644
index 0000000000..93dc3c5c54
--- /dev/null
+++ b/dviware/textool/textool.icon
@@ -0,0 +1,36 @@
+/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
+ * Description: A model 120 display and keyboard.
+ * Background: white
+ */
+ 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8FFF,0xFF00,0x00C0,0x0031,0x8FFF,0xFF00,0x00E0,0x0071,
+ 0x8C06,0x0300,0x0070,0x00E1,0x8006,0x0000,0x0038,0x01C1,
+ 0x8006,0x03FF,0xFFDC,0x0381,0x8006,0x03FF,0xFFCE,0x0701,
+ 0x8006,0x0300,0x00C7,0x0E01,0x8006,0x0300,0x0003,0x9C01,
+ 0x8006,0x0300,0x0001,0xF801,0x8006,0x0300,0x0000,0xF001,
+ 0x8006,0x0300,0x0000,0xF001,0x8006,0x0300,0x0001,0xF801,
+ 0x8006,0x0300,0xC003,0x9C01,0x8006,0x03FF,0xC007,0x0E01,
+ 0x8006,0x03FF,0xC00E,0x0701,0x8006,0x0300,0xC01C,0x0381,
+ 0x8006,0x0300,0x0038,0x01C1,0x8006,0x0300,0x0070,0x00E1,
+ 0x800F,0x0300,0x00E0,0x0071,0x800F,0x0300,0x00C0,0x0031,
+ 0x8000,0x0300,0x0000,0x0001,0x8000,0x0300,0x00C0,0x0001,
+ 0x8000,0x03FF,0xFFC0,0x0001,0x8000,0x03FF,0xFFC0,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
+ 0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
diff --git a/dviware/textool/textool.l b/dviware/textool/textool.l
new file mode 100644
index 0000000000..9ae203ddeb
--- /dev/null
+++ b/dviware/textool/textool.l
@@ -0,0 +1,224 @@
+.TH TEXTOOL 1
+.SH NAME
+textool \- TeX previewer for suntools
+.SH SYNOPSIS
+.B textool
+[
+.B \-p
+] [
+.B \-P
+] [
+.B \-b
+] [
+.B \-m
+.I <mag>
+] [ \+n ] [dvifile[.dvi]]
+.SH DESCRIPTION
+.LP
+The
+.I textool
+program displays a TeX DVI file in a SunView window.
+It is an enhanced version of the old "dvisun" command.
+It can be driven either by keyboard commands typed into its window
+or by using the mouse and various menus.
+The label along the top of the window gives the current working directory,
+the current filename and the current page number.
+If invoked with no filename argument it will just display an empty
+window.
+If given a file it will read the preamble, postamble and page backpointers
+so that it can go straight to a given page.
+This means that it will only display files, it will not read stdin.
+After each page of the
+output is displayed the program will wait for a response from the user.
+.SH OPTIONS
+.TP
+.B \-p
+Pre-load all the font descriptions for fonts mentioned in the DVI file.
+Normally only the information from the DVI postamble is loaded and the
+various PK files are opened on demand.
+This option loads all the character information except the actual character
+bitmaps before displaying the first page.
+.TP
+.B \-P
+A stronger version of the above.
+In this case the character bitmaps are pre-loaded as well.
+If this option is used no PK files will need to be accessed after the first
+page is displayed.
+The penalty is extra memory used for characters that may not be printed.
+.TP
+.BI \-m mag
+This option gives a magnification factor (in the TeX form with
+1000 for a magnification of 1) which will over-ride any magnification factor
+specified in the DVI file.
+The program may be compiled with this option disabled as it is uncommon
+to have a set of PK files at several different magnifications.
+.TP
+.B \-b
+This turns off SunView batching.
+This slows page display down by a factor of about three but you get the
+top lines of the screen displayed more quickly.
+.TP
+.BI \+ number
+Skip
+.I number
+pages before displaying anything.
+.LP
+As well as those options described above
+.I textool
+will also consume the standard suntools options of the form \-W*,
+for example the command "textool -Wi &" will start an instance
+of
+.I textool
+in its iconic state in the background.
+This can be used as a tool as and when required.
+.SH "KEYBOARD COMMANDS"
+.LP
+Keyboard commands are provided to go forward and backwards 1 or n pages in
+the file and to provide basic scrolling.
+They are:
+.TP
+.B return
+Go to next page in file.
+.TP
+.B space
+Same as return.
+.TP
+.B b
+Go to previous page in file.
+.TP
+.B p
+Same as b.
+.TP
+.BI \+ nn
+Skip forward
+.I nn
+pages.
+The number is terminated with return.
+.TP
+.BI \- nn
+Go back
+.I nn
+pages.
+The number is again terminated with return.
+.TP
+.B h
+Scroll over to the left edge of the page.
+.TP
+.B j
+Scroll to bottom of page.
+.TP
+.B k
+Scroll to top of page.
+.TP
+.B l
+Scroll over to right edge of page.
+.TP
+.B c
+Scroll to initial position, which is one inch down from the top and
+half an inch in from the left edge.
+.SH "MOUSE COMMANDS"
+.LP
+Both horizontal and vertical scrollbars are provided and these work in the
+standard Sun fashion.
+In particular the middle mouse button in either of the vertical bar's
+page bottons will go to the next page and a shifted middle button will
+go back a page.
+.LP
+Pressing the left mouse button changes the cursor to a set of cross-hairs
+so alignment can be checked.
+The arrow cursor is restored by releasing the button.
+.LP
+A menu is provided, popped up with the right mouse button, to do more
+complex things.
+Selections from this menu which require user text input will pop up a
+text input panel with an appropriate prompt.
+This panel is also used for error messages.
+An error message can be removed by clicking on the panel with the left
+mouse button.
+Operations are interlocked to prevent impossible or inadvisable choices;
+for example if there is no current file you cannot select the
+"restart dvi file" or "go to page" choices.
+.LP
+The various selections are described below:
+.TP
+.B "restart dvi file"
+This is a complete restart with the current file.
+The DVI file is closed, font storage is freed and all PK files closed.
+The file is then reopened and processed from scratch.
+.TP
+.B "go to page"
+This allows direct access to any page in the file.
+For documents of 10 pages or less a pullright menu is provided to select
+the actual page.
+For longer documents you must enter the page number into the pop up
+panel.
+.TP
+.B "new file"
+This closes the current file, as in the restart case, and then prompts for
+a new file to process.
+A leading ~ on the file name is interpreted in the same way as
+.IR csh .
+.TP
+.B "change directory"
+This prompts for a directory to replace the current working directory.
+Leading ~ is allowed as in the "new file" case.
+.TP
+.B "run tex"
+This creates a new window and runs tex on the .tex file with the same
+basename as the current DVI file.
+Only one extra window is allowed so all the other selections which
+would require one are dimmed while the tex window is open.
+As the DVI file is assumed to be changing the restart and page choices are
+also dimmed.
+To remove the window select "done" from its frame menu.
+.TP
+.B "run latex"
+This is the same as the "run tex" case but runs latex instead.
+.TP
+.B "edit .tex file"
+This runs an editor on the .tex file.
+The EDITOR from the environment is used if there is one, otherwise
+/usr/ucb/vi is used.
+.TP
+.B shell
+This creates a window running whatever shell SunView finds for you.
+.SH ENVIRONMENT
+.LP
+The following things are taken from the environment:
+.TP
+.B PKPATH
+A comma separated list of directories to search for the font PK files
+in place of the default described below.
+.TP
+.B HOME
+Used for expanding tilde expressions of the form ~/dir.
+.TP
+.B EDITOR
+The editor to use for the "edit .tex file" menu choice.
+.SH FILES
+.TP 2.5i
+*.dvi
+TeX DeVice Independent output file
+.TP
+/usr/local/lib/tex/fonts/pk/*.*pk
+TeX default font rasters
+.TP
+/etc/passwd
+Used for expanding tilde expressions of the form ~name/dir.
+.SH "SEE ALSO"
+dvitype(1),
+dvisun(1),
+tex(1)
+.SH BUGS
+When using fonts with decent resolution only part of a page appears
+on the screen.
+.SH AUTHORS
+Mark Senn wrote the early versions of this program 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, becoming dvisun.
+Yves Ledru did the initial suntools port, making texview.
+Peter Ilieve re-did the suntools part,
+tidied up and changed the font cacheing in the DVI part
+and changed it to use PK files for fonts.
+
diff --git a/dviware/textool/textool.pdf b/dviware/textool/textool.pdf
new file mode 100644
index 0000000000..ed22767870
--- /dev/null
+++ b/dviware/textool/textool.pdf
Binary files differ