chiark / gitweb /
Import upstream version 5.3.
[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