Commit | Line | Data |
---|---|---|
fac14bbe MW |
1 | |
2 | /* Copyright (c) 1995, 1998 by Arkkra Enterprises */ | |
3 | /* All rights reserved */ | |
4 | ||
5 | /* Functions for displaying Mup/Ghostscript output on screen using | |
6 | * Watcom C */ | |
7 | ||
8 | #ifdef __WATCOMC__ | |
9 | #include "mupdisp.h" | |
10 | #include <graph.h> | |
11 | #include <stdlib.h> | |
12 | #include <malloc.h> | |
13 | #include <stdio.h> | |
14 | #include <conio.h> | |
15 | #include <fcntl.h> | |
16 | #include <io.h> | |
17 | ||
18 | /* hard code X and Y sizes for the moment */ | |
19 | #define XSIZE 640 | |
20 | #define YSIZE 480 | |
21 | ||
22 | /* image to be calloc'ed has 6 header bytes, then each row consecutively */ | |
23 | #define BITS2BYTES(bits) (((bits) + 7) / 8) /* round upwards */ | |
24 | #define SIZEIMAGE (6 + ((long)BITS2BYTES(XSIZE)*4) * (long)YSIZE) | |
25 | static char *Image; | |
26 | ||
27 | static void zapblock P((char *area, long size)); | |
28 | \f | |
29 | ||
30 | /* initialize graphics driver, etc */ | |
31 | ||
32 | void | |
33 | dos_setup() | |
34 | ||
35 | { | |
36 | struct videoconfig vidinfo; | |
37 | ||
38 | ||
39 | /* initalize best graphics mode */ | |
40 | if (_setvideomode(_VRES16COLOR) == 0) { | |
41 | fprintf(stderr, "can't set graphics mode\n"); | |
42 | generalcleanup(1); | |
43 | } | |
44 | ||
45 | _getvideoconfig(&vidinfo); | |
46 | ||
47 | if (vidinfo.numxpixels != XSIZE || vidinfo.numypixels != YSIZE) { | |
48 | _setvideomode(_DEFAULTMODE); | |
49 | fprintf(stderr, "video mode %dx%d not supported\n", | |
50 | vidinfo.numxpixels, vidinfo.numypixels); | |
51 | generalcleanup(0); | |
52 | } | |
53 | ||
54 | /* | |
55 | * Allocate the image buffer. Note that both parameters must be less | |
56 | * than 65536, but the total size (product) can be greater. The +1 | |
57 | * is to allow room for the header bytes (and then some). | |
58 | */ | |
59 | Image = (char *)calloc(BITS2BYTES(YSIZE)*4 + 1, XSIZE); | |
60 | if (Image == NULL) { | |
61 | _setvideomode(_DEFAULTMODE); | |
62 | fprintf(stderr, "can't allocate image buffer\n"); | |
63 | generalcleanup(0); | |
64 | } | |
65 | ||
66 | /* set aspect ratio adjust */ | |
67 | Conf_info_p->adjust = 1.375 * (double) vidinfo.numypixels | |
68 | / (double) vidinfo.numxpixels; | |
69 | Conf_info_p->vlines = vidinfo.numypixels; | |
70 | ||
71 | /* set screen to all white */ | |
72 | _setbkcolor(_BRIGHTWHITE); | |
73 | _clearscreen(_GCLEARSCREEN); | |
74 | } | |
75 | \f | |
76 | ||
77 | /* before exiting, clean up graphics, then call the general cleanup routine */ | |
78 | ||
79 | void | |
80 | dos_cleanup(int status) | |
81 | { | |
82 | _setvideomode(_DEFAULTMODE); | |
83 | generalcleanup(status); | |
84 | } | |
85 | \f | |
86 | ||
87 | /* draw a screen worth of the bitmap, starting at specified raster line */ | |
88 | ||
89 | void | |
90 | dos_draw(line, small) | |
91 | ||
92 | int line; /* start at this raster line */ | |
93 | int small; /* YES or NO for small or large page image */ | |
94 | ||
95 | { | |
96 | int r; /* row index */ | |
97 | long offset; /* into bitmap file */ | |
98 | int fd; /* file descriptor */ | |
99 | int himage_bytes; /* horizontal image bytes */ | |
100 | char *row_ptr; /* point at a row of the image */ | |
101 | int n; /* loop variable */ | |
102 | ||
103 | ||
104 | /* make sure we have a valid page to draw */ | |
105 | if (Currpage_p == (struct Pginfo *) 0) { | |
106 | ( *(Conf_info_p->error) ) ("page # out of range"); | |
107 | return; | |
108 | } | |
109 | ||
110 | /* figure out where in the bitmap file this page is */ | |
111 | offset = Currpage_p->seqnum * BYTES_PER_PAGE; | |
112 | fd = gen1file(small); | |
113 | lseek(fd, offset + (long)line * BYTES_PER_LINE, SEEK_SET); | |
114 | ||
115 | /* zero out the image buffer */ | |
116 | zapblock(Image, SIZEIMAGE); | |
117 | ||
118 | /* number of bytes representing one horizontal row in full page image */ | |
119 | himage_bytes = BITS2BYTES(XSIZE) * 4; | |
120 | ||
121 | /* set the header bytes in the image */ | |
122 | Image[0] = XSIZE % 256; | |
123 | Image[1] = XSIZE / 256; | |
124 | Image[2] = YSIZE % 256; | |
125 | Image[3] = YSIZE / 256; | |
126 | Image[4] = 4; | |
127 | Image[5] = 0; | |
128 | ||
129 | /* set screen to all white */ | |
130 | _setbkcolor(_BRIGHTWHITE); | |
131 | _clearscreen(_GCLEARSCREEN); | |
132 | ||
133 | /* for each row */ | |
134 | for (r = 0; r < Conf_info_p->vlines; r++) { | |
135 | /* read it directly into the image */ | |
136 | row_ptr = &Image[ 6 + r * himage_bytes ]; | |
137 | if (read(fd, row_ptr, BYTES_PER_LINE) != BYTES_PER_LINE) { | |
138 | break; | |
139 | } | |
140 | ||
141 | if (small) { | |
142 | /* black out the unused strip on the right */ | |
143 | for (n = BITS_PER_LINE; n < XSIZE; n++) | |
144 | row_ptr[n/8] |= 1 << (7 - n%8); | |
145 | } | |
146 | } | |
147 | /* put at upper left corner, (0, 0) */ | |
148 | _putimage(0, 0, Image, _GPSET); | |
149 | } | |
150 | \f | |
151 | ||
152 | /* for now we just beep on errors */ | |
153 | /*ARGSUSED*/ | |
154 | void | |
155 | dos_error(msg) | |
156 | ||
157 | char *msg; | |
158 | ||
159 | { | |
160 | putc('\7', stderr); | |
161 | } | |
162 | \f | |
163 | ||
164 | /* for user interface, call command processor for each character read */ | |
165 | ||
166 | void | |
167 | dos_user_interf() | |
168 | ||
169 | { | |
170 | int c; | |
171 | int special = 0; /* 1 = got a null, which is first character | |
172 | * of special key sequence */ | |
173 | for ( ; ; ) { | |
174 | c = getch(); | |
175 | if (c == '\0') { | |
176 | special = 1; | |
177 | continue; | |
178 | } | |
179 | if (special == 1) { | |
180 | switch (c) { | |
181 | case 0x49: | |
182 | /* PgUp key */ | |
183 | c = 'p'; | |
184 | break; | |
185 | case 0x51: | |
186 | /* PgDown key */ | |
187 | c = 'n'; | |
188 | break; | |
189 | case 0x48: | |
190 | /* Up arrow key */ | |
191 | c = 'b'; | |
192 | break; | |
193 | case 0x50: | |
194 | /* Down arrow key */ | |
195 | c = 'f'; | |
196 | break; | |
197 | default: | |
198 | special = 0; | |
199 | continue; | |
200 | } | |
201 | } | |
202 | do_cmd(c); | |
203 | special = 0; | |
204 | } | |
205 | } | |
206 | \f | |
207 | ||
208 | /* display a raster centered on window */ | |
209 | ||
210 | void | |
211 | dos_raster(bitmap, width, height) | |
212 | ||
213 | unsigned char *bitmap; /* what to display */ | |
214 | int width, height; /* of bitmap, width is in bytes */ | |
215 | ||
216 | { | |
217 | int r, c; /* row and column indices */ | |
218 | int b; /* index through bits */ | |
219 | int x, y; /* upper left corner of where to put bitmap, | |
220 | * x in bytes */ | |
221 | int himage_bytes; /* bytes needed for one row in image */ | |
222 | int n; /* loop variable */ | |
223 | char *row_ptr; /* point at a row of the image */ | |
224 | ||
225 | ||
226 | himage_bytes = 4 * width; | |
227 | ||
228 | /* figure out how to center on screen */ | |
229 | x = (BYTES_PER_LINE - width) / 2 * 8; | |
230 | y = (Conf_info_p->vlines - height) / 2; | |
231 | ||
232 | /* zero out the image buffer */ | |
233 | zapblock(Image, SIZEIMAGE); | |
234 | ||
235 | /* set the header bytes in the image */ | |
236 | Image[0] = (width * 8) % 256; | |
237 | Image[1] = (width * 8) / 256; | |
238 | Image[2] = height % 256; | |
239 | Image[3] = height / 256; | |
240 | Image[4] = 4; | |
241 | Image[5] = 0; | |
242 | ||
243 | /* for each row */ | |
244 | for (r = 0; r < height; r++) { | |
245 | row_ptr = &Image[ 6 + r * himage_bytes ]; | |
246 | for (c = 0; c < width; c++) { | |
247 | for (b = 0; b < 8; b++) { | |
248 | if (bitmap[r*width+c] & (1 << (7-b))) { | |
249 | /* white (15); set 4 copies of bit */ | |
250 | for (n = 0; n < 4; n++) | |
251 | row_ptr[n*width + c] |= | |
252 | (1 << (7-b)); | |
253 | } else { | |
254 | /* black (8); set only the first */ | |
255 | row_ptr[c] |= (1 << (7-b)); | |
256 | } | |
257 | } | |
258 | } | |
259 | } | |
260 | ||
261 | _putimage(x, y, Image, _GPSET); | |
262 | } | |
263 | \f | |
264 | /* zero out a block of memory that may be bigger than 32K */ | |
265 | ||
266 | #define BLOCKSIZE 0x3fff | |
267 | ||
268 | static void | |
269 | zapblock(area, size) | |
270 | ||
271 | char *area; | |
272 | long size; | |
273 | ||
274 | { | |
275 | long k; | |
276 | ||
277 | /* | |
278 | * memset's third parm is "unsigned int", so we can't do the whole | |
279 | * area at once. | |
280 | */ | |
281 | for (k = 0; k < size; k += BLOCKSIZE) { | |
282 | if (size - k >= BLOCKSIZE) | |
283 | (void)memset(&area[k], 0, BLOCKSIZE); | |
284 | else | |
285 | (void)memset(&area[k], 0, size - k); | |
286 | } | |
287 | } | |
288 | ||
289 | #else | |
290 | ||
291 | /* some compilers don't like empty files, so if __WATCOMC__ isn't defined, | |
292 | * put something here to keep those compilers happy */ | |
293 | static short dummy; | |
294 | ||
295 | #endif |