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