1 /* xbitmap.c:
2 *
3 * at one time this was XRdBitF.c. it bears very little resemblence to it
4 * now. that was ugly code. this is cleaner, faster, and more reliable
5 * in most cases.
6 *
7 * jim frost 10.06.89
8 *
9 * Copyright, 1987, Massachusetts Institute of Technology
10 *
11 * Copyright 1989 Jim Frost. See included file "copyright.h" for complete
12 * copyright information.
13 */
14
15 #include "mit.cpyrght"
16 #include "copyright.h"
17 #include "image.h"
18 #include <ctype.h>
19
20 /* SUPPRESS 560 */
21
22 #if defined(SYSV) || defined(VMS) || 1
23 #include <string.h>
24 #define rindex strrchr
25 #else
26 char *rindex();
27 #endif
28
29 #define MAX_SIZE 255
30
31 static short HexTable[256]; /* conversion value */
32 static unsigned int Initialized= 0; /* easier to fill in at run time */
33
34 #define b0000 0 /* things make more sense if you see them by bit */
35 #define b0001 1
36 #define b0010 2
37 #define b0011 3
38 #define b0100 4
39 #define b0101 5
40 #define b0110 6
41 #define b0111 7
42 #define b1000 8
43 #define b1001 9
44 #define b1010 10
45 #define b1011 11
46 #define b1100 12
47 #define b1101 13
48 #define b1110 14
49 #define b1111 15
50
51 #define HEXSTART -1
52 #define HEXDELIM -2
53 #define HEXBAD -3
54
55 /* build a hex digit value table with the bits inverted
56 */
57
initHexTable()58 static void initHexTable()
59 { int a;
60
61 for (a= 0; a < 256; a++)
62 HexTable[a]= HEXBAD;
63
64 HexTable['0']= b0000;
65 HexTable['1']= b1000;
66 HexTable['2']= b0100;
67 HexTable['3']= b1100;
68 HexTable['4']= b0010;
69 HexTable['5']= b1010;
70 HexTable['6']= b0110;
71 HexTable['7']= b1110;
72 HexTable['8']= b0001;
73 HexTable['9']= b1001;
74 HexTable['A']= b0101; HexTable['a']= HexTable['A'];
75 HexTable['B']= b1101; HexTable['b']= HexTable['B'];
76 HexTable['C']= b0011; HexTable['c']= HexTable['C'];
77 HexTable['D']= b1011; HexTable['d']= HexTable['D'];
78 HexTable['E']= b0111; HexTable['e']= HexTable['E'];
79 HexTable['F']= b1111; HexTable['f']= HexTable['F'];
80 HexTable['x']= HEXSTART;
81 HexTable['\r']= HEXDELIM;
82 HexTable['\n']= HEXDELIM;
83 HexTable['\t']= HEXDELIM;
84 HexTable[' ']= HEXDELIM;
85 HexTable[',']= HEXDELIM;
86 HexTable['}']= HEXDELIM;
87
88 Initialized = 1;
89 }
90
91 /* read a hex value and return its value
92 */
93
nextInt(zf)94 static int nextInt(zf)
95 ZFILE *zf;
96 { int c;
97 int value= 0;
98 int shift= 0;
99
100 for (;;) {
101 c= zgetc(zf);
102 if (c == EOF)
103 return(-1);
104 else {
105 c= HexTable[c & 0xff];
106 switch(c) {
107 case HEXSTART:
108 shift= 0; /* reset shift counter */
109 break;
110 case HEXDELIM:
111 if (shift)
112 return(value);
113 break;
114 case HEXBAD:
115 return(-1);
116 default:
117 value += (c << shift);
118 shift += 4;
119 }
120 }
121 }
122 }
123
badFile(name)124 static void badFile(name)
125 char *name;
126 {
127 fprintf(stderr, "%s: bad X bitmap file\n", name);
128 cleanup(-1);
129 }
130
xbitmapLoad(fullname,name,verbose)131 Image *xbitmapLoad(fullname, name, verbose)
132 char *fullname, *name;
133 unsigned int verbose;
134 { ZFILE *zf;
135 Image *image;
136 char line[MAX_SIZE];
137 char name_and_type[MAX_SIZE];
138 char *type;
139 int value;
140 int v10p=0;
141 unsigned int linelen, dlinelen;
142 unsigned int x, y;
143 unsigned int w = 0, h = 0;
144 byte *dataptr;
145
146 if (!Initialized)
147 initHexTable();
148
149 if (! (zf= zopen(fullname)))
150 return(NULL);
151
152 /* get width/height values */
153
154 while (zgets((byte *)line, MAX_SIZE, zf)) {
155 if (strlen(line) == MAX_SIZE-1) {
156 zclose(zf);
157 return(NULL);
158 }
159
160 /* width/height/hot_x/hot_y scanning
161 */
162
163 if (sscanf(line,"#define %s %d", name_and_type, &value) == 2) {
164 if (!(type = rindex(name_and_type, '_')))
165 type = name_and_type;
166 else
167 type++;
168
169 if (!strcmp("width", type))
170 w= (unsigned int)value;
171 if (!strcmp("height", type))
172 h= (unsigned int)value;
173 }
174
175 /* if start of data, determine if it's X10 or X11 data and break
176 */
177
178 if (sscanf(line, "static short %s = {", name_and_type) == 1) {
179 v10p = 1;
180 break;
181 }
182 if ((sscanf(line,"static unsigned char %s = {", name_and_type) == 1) ||
183 (sscanf(line, "static char %s = {", name_and_type) == 1)) {
184 v10p = 0;
185 break;
186 }
187 }
188
189 if (!w || !h) {
190 zclose(zf);
191 return(NULL);
192 }
193 image= newBitImage(w, h);
194
195 /* get title of bitmap if any
196 */
197
198 if ((type = rindex(name_and_type, '_')) && !strcmp("bits[]", type + 1)) {
199 *type= '\0';
200 image->title= dupString(name_and_type);
201 }
202
203 /* read bitmap data
204 */
205
206 linelen= (w / 8) + (w % 8 ? 1 : 0); /* internal line length */
207 if (v10p) {
208 dlinelen= (w / 8) + (w % 16 ? 2 : 0);
209 dataptr= image->data;
210 for (y= 0; y < h; y++) {
211 for (x= 0; x < dlinelen; x++) {
212 if ((value= nextInt(zf)) < 0) {
213 freeImage(image);
214 zclose(zf);
215 return(NULL);
216 }
217 *(dataptr++)= value >> 8;
218 if (++x < linelen)
219 *(dataptr++)= value & 0xff;
220 }
221 }
222 }
223 else {
224 dataptr= image->data;
225 for (y= 0; y < h; y++)
226 for (x= 0; x < linelen; x++) {
227 if ((value= nextInt(zf)) < 0)
228 badFile(name);
229 *(dataptr++)= value;
230 }
231 }
232
233 if (verbose) {
234 fprintf(stderr, "%s is a %dx%d X", name, image->width, image->height);
235 if (v10p)
236 fprintf(stderr, "10");
237 else
238 fprintf(stderr, "11");
239 if (image->title)
240 fprintf(stderr, " bitmap file titled '%s'", image->title);
241 fprintf(stderr, "\n");
242 }
243 zclose(zf);
244 return(image);
245 }
246
247 /* this is the easiest way to do this. it's not likely we'll have mondo
248 * x bitmaps anyway given their size
249 */
250
xbitmapIdent(fullname,name)251 int xbitmapIdent(fullname, name)
252 char *fullname, *name;
253 { Image *image;
254
255 if ((image = xbitmapLoad(fullname, name, (unsigned int)1))) {
256 freeImage(image);
257 return(1);
258 }
259 return(0);
260 }
261