Merge branch 'arkkra' into shiny
[mup] / mup / mupdisp / dos.c
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