1 #   include	"bitmapConfig.h"
2 
3 #   include	"bmintern.h"
4 #   include	<stdio.h>
5 #   include	<ctype.h>
6 #   include	<string.h>
7 #   include	<stdlib.h>
8 #   include	<sioFileio.h>
9 
10 #   include	<appDebugon.h>
11 
12 static unsigned char BMXBMflip[256];
13 
bmXbmSetFlip(void)14 static void bmXbmSetFlip( void )
15     {
16     int	i;
17 
18     for ( i= 0; i < 256; i++ )
19 	{
20 	BMXBMflip[i]=	( ( i & 0x80 ) >> 7 )	|
21 			( ( i & 0x40 ) >> 5 )   |
22 			( ( i & 0x20 ) >> 3 )   |
23 			( ( i & 0x10 ) >> 1 )   |
24 			( ( i & 0x08 ) << 1 )   |
25 			( ( i & 0x04 ) << 3 )   |
26 			( ( i & 0x02 ) << 5 )   |
27 			( ( i & 0x01 ) << 7 )   ;
28 	}
29     }
30 
31 /************************************************************************/
32 /*  Read an X bitmap file.						*/
33 /*  Routine stolen from the X11R6 file 'lib/X11/RdBitF.c'		*/
34 /************************************************************************/
35 
36 /*  Fake X headers */
37 #define Bool unsigned char
38 #define False 0
39 #define True 1
40 #define BitmapOpenFailed -1
41 #define BitmapFileInvalid -1
42 #define BitmapNoMemory -1
43 #define BitmapSuccess 0
44 #define Xfree(p) free(p)
45 #define Xmalloc(n) malloc(n)
46 
47 #define MAX_SIZE 255
48 
49 /* shared data for the image read/parse logic */
50 static short hexTable[256];		/* conversion value */
51 static Bool initialized = False;	/* easier to fill in at run time */
52 
53 
54 /*
55  *	Table index for the hex values. Initialized once, first time.
56  *	Used for translation value or delimiter significance lookup.
57  */
initHexTable(void)58 static void initHexTable( void )
59 {
60     /*
61      * We build the table at run time for several reasons:
62      *
63      *     1.  portable to non-ASCII machines.
64      *     2.  still reentrant since we set the init flag after setting table.
65      *     3.  easier to extend.
66      *     4.  less prone to bugs.
67      */
68     hexTable['0'] = 0;	hexTable['1'] = 1;
69     hexTable['2'] = 2;	hexTable['3'] = 3;
70     hexTable['4'] = 4;	hexTable['5'] = 5;
71     hexTable['6'] = 6;	hexTable['7'] = 7;
72     hexTable['8'] = 8;	hexTable['9'] = 9;
73     hexTable['A'] = 10;	hexTable['B'] = 11;
74     hexTable['C'] = 12;	hexTable['D'] = 13;
75     hexTable['E'] = 14;	hexTable['F'] = 15;
76     hexTable['a'] = 10;	hexTable['b'] = 11;
77     hexTable['c'] = 12;	hexTable['d'] = 13;
78     hexTable['e'] = 14;	hexTable['f'] = 15;
79 
80     /* delimiters of significance are flagged w/ negative value */
81     hexTable[' '] = -1;	hexTable[','] = -1;
82     hexTable['}'] = -1;	hexTable['\n'] = -1;
83     hexTable['\t'] = -1;
84 
85     initialized = True;
86 }
87 
88 /*
89  *	read next hex value in the input stream, return -1 if EOF
90  */
NextInt(FILE * fstream)91 static int NextInt ( FILE *fstream )
92 {
93     int	ch;
94     int	value = 0;
95     int gotone = 0;
96     int done = 0;
97 
98     /* loop, accumulate hex value until find delimiter  */
99     /* skip any initial delimiters found in read stream */
100 
101     while (!done) {
102 	ch = getc(fstream);
103 	if (ch == EOF) {
104 	    value	= -1;
105 	    done++;
106 	} else {
107 	    /* trim high bits, check type and accumulate */
108 	    ch &= 0xff;
109 	    if (isascii(ch) && isxdigit(ch)) {
110 		value = (value << 4) + hexTable[ch];
111 		gotone++;
112 	    } else if ((hexTable[ch]) < 0 && gotone)
113 	      done++;
114 	}
115     }
116     return value;
117 }
118 
XReadBitmapFileData(const char * filename,unsigned int * width,unsigned int * height,unsigned char ** data,int * x_hot,int * y_hot)119 static int XReadBitmapFileData (
120     const char *filename,
121     unsigned int *width,                /* RETURNED */
122     unsigned int *height,               /* RETURNED */
123     unsigned char **data,               /* RETURNED */
124     int *x_hot,                         /* RETURNED */
125     int *y_hot)                         /* RETURNED */
126 {
127     FILE *fstream;			/* handle on file  */
128     unsigned char *bits = NULL;		/* working variable */
129     char line[MAX_SIZE];		/* input line from file */
130     int size;				/* number of bytes of data */
131     char name_and_type[MAX_SIZE];	/* an input line */
132     char *type;				/* for parsing */
133     int value;				/* from an input line */
134     int version10p;			/* boolean, old format */
135     int padding;			/* to handle alignment */
136     int bytes_per_line;			/* per scanline of data */
137     unsigned int ww = 0;		/* width */
138     unsigned int hh = 0;		/* height */
139     int hx = -1;			/* x hotspot */
140     int hy = -1;			/* y hotspot */
141 
142     /* first time initialization */
143     if (initialized == False) initHexTable();
144 
145     if (!(fstream = fopen(filename, "r")))
146 	{ SDEB(filename); return BitmapOpenFailed; }
147 
148     /* error cleanup and return macro	*/
149 #define	RETURN(code) \
150 { if (bits) Xfree ((char *)bits); fclose (fstream); LDEB(1); return code; }
151 
152     while (fgets(line, MAX_SIZE, fstream)) {
153 	if (strlen(line) == MAX_SIZE-1)
154 	    RETURN (BitmapFileInvalid);
155 	if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
156 	    if (!(type = strrchr(name_and_type, '_')))
157 	      type = name_and_type;
158 	    else
159 	      type++;
160 
161 	    if (!strcmp("width", type))
162 	      ww = (unsigned int) value;
163 	    if (!strcmp("height", type))
164 	      hh = (unsigned int) value;
165 	    if (!strcmp("hot", type)) {
166 		if (type-- == name_and_type || type-- == name_and_type)
167 		  continue;
168 		if (!strcmp("x_hot", type))
169 		  hx = value;
170 		if (!strcmp("y_hot", type))
171 		  hy = value;
172 	    }
173 	    continue;
174 	}
175 
176 	if (sscanf(line, "static short %s = {", name_and_type) == 1)
177 /*}*/
178 	  version10p = 1;
179 	else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
180 /*}*/
181 	  version10p = 0;
182 	else if (sscanf(line, "static char %s = {", name_and_type) == 1)
183 /*}*/
184 	  version10p = 0;
185 	else
186 	  continue;
187 
188 	if (!(type = strrchr(name_and_type, '_')))
189 	  type = name_and_type;
190 	else
191 	  type++;
192 
193 	if (strcmp("bits[]", type))
194 	  continue;
195 
196 	if (!ww || !hh)
197 	  { LLDEB(ww,hh); RETURN (BitmapFileInvalid); }
198 
199 	if ((ww % 16) && ((ww % 16) < 9) && version10p)
200 	  padding = 1;
201 	else
202 	  padding = 0;
203 
204 	bytes_per_line = (ww+7)/8 + padding;
205 
206 	size = bytes_per_line * hh;
207 	bits = (unsigned char *) Xmalloc ((unsigned int) size);
208 	if (!bits)
209 	  { LDEB(bits); RETURN (BitmapNoMemory); }
210 
211 	if (version10p) {
212 	    unsigned char *ptr;
213 	    int bytes;
214 
215 	    for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
216 		if ((value = NextInt(fstream)) < 0)
217 		  { LDEB(value); RETURN (BitmapFileInvalid); }
218 		*(ptr++) = value;
219 		if (!padding || ((bytes+2) % bytes_per_line))
220 		  *(ptr++) = value >> 8;
221 	    }
222 	} else {
223 	    unsigned char *ptr;
224 	    int bytes;
225 
226 	    for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
227 		if ((value = NextInt(fstream)) < 0)
228 		  { LDEB(value); RETURN (BitmapFileInvalid); }
229 		*ptr=value;
230 	    }
231 	}
232     }					/* end while */
233 
234     fclose(fstream);
235     if (!bits)
236 	{ XDEB(bits); return (BitmapFileInvalid); }
237 
238     *data = bits;
239     *width = ww;
240     *height = hh;
241     if (x_hot) *x_hot = hx;
242     if (y_hot) *y_hot = hy;
243 
244     return (BitmapSuccess);
245 }
246 
247 /************************************************************************/
248 /*  Write an X bitmap file.						*/
249 /*  Part of this routine is stolen from: the X11R6 file			*/
250 /*  'lib/X11/WrBitF.c							*/
251 /************************************************************************/
252 
253 #define BYTES_PER_OUTPUT_LINE 12
254 
bmWriteXbmFile(const MemoryBuffer * filename,const unsigned char * buffer,const BitmapDescription * bd,int privateFormat)255 int bmWriteXbmFile(	const MemoryBuffer *		filename,
256 			const unsigned char *		buffer,
257 			const BitmapDescription *	bd,
258 			int				privateFormat )
259     {
260     SimpleOutputStream *	sos;
261     int				x_hot= -1;
262     int				y_hot= -1;
263     const char *		name= "IMAGE";
264     const unsigned char *	data= buffer;
265     int				width= bd->bdPixelsWide;
266     int				height= bd->bdPixelsHigh;
267     int				size= bd->bdBufferLength;
268 
269     int				byte;
270     int				c;
271     const unsigned char *	ptr;
272 
273     sos= sioOutFileioOpen( filename );
274     if  ( ! sos )
275 	{ XDEB(sos); return -1;	}
276 
277     bmXbmSetFlip();
278 
279 /* #>>>>>>>>>>>>>>>>>>> begin FROM X*/
280 
281   /* Write out standard header */
282   sioOutPrintf(sos, "#define %s_width %d\n", name, width);
283   sioOutPrintf(sos, "#define %s_height %d\n", name, height);
284   if (x_hot != -1) {
285     sioOutPrintf(sos, "#define %s_x_hot %d\n", name, x_hot);
286     sioOutPrintf(sos, "#define %s_y_hot %d\n", name, y_hot);
287   }
288 
289   /* Print out the data itself */
290   sioOutPrintf(sos, "static unsigned char %s_bits[] = {", name);
291   for (byte=0, ptr=data; byte<size; byte++, ptr++) {
292     if (!byte)
293       sioOutPrintf(sos, "\n   ");
294     else if (!(byte % BYTES_PER_OUTPUT_LINE))
295       sioOutPrintf(sos, ",\n   ");
296     else
297       sioOutPrintf(sos, ", ");
298     c = *ptr;
299     if (c<0)
300       c += 256;
301     sioOutPrintf(sos, "0x%02x", BMXBMflip[c]);
302   }
303   sioOutPrintf(sos, "};\n");
304 
305   sioOutClose(sos);
306   return(BitmapSuccess);
307 }
308 /* #<<<<<<<<<<<<<<<<<<< end   FROM X*/
309 
bmCanWriteXbmFile(const BitmapDescription * bd,int privateFormat)310 int bmCanWriteXbmFile(	const BitmapDescription *	bd,
311 			int				privateFormat )
312     {
313     if  ( privateFormat != 11 )
314 	{ return -1;	}
315 
316     if  ( bd->bdBitsPerPixel != 1 )
317 	{ return -1;	}
318 
319     return 0;
320     }
321 
322 /************************************************************************/
323 /*									*/
324 /*  Read an XBM bitmap file.						*/
325 /*									*/
326 /************************************************************************/
327 
bmReadXbmFile(const MemoryBuffer * filename,unsigned char ** pBuffer,BitmapDescription * bd,int * pPrivateFormat)328 int bmReadXbmFile(	const MemoryBuffer *	filename,
329 			unsigned char **	pBuffer,
330 			BitmapDescription *	bd,
331 			int *			pPrivateFormat )
332     {
333     unsigned int	width;
334     unsigned int	height;
335     int			x_hot;
336     int			y_hot;
337     unsigned char *	s;
338 
339     if  ( XReadBitmapFileData (	utilMemoryBufferGetString( filename ),
340 				&width,
341 				&height,
342 				pBuffer,
343 				&x_hot, &y_hot	) )
344 	{  LDEB(1); return -1;	}
345 
346     bd->bdBytesPerRow= ( width+ 7 )/8;
347     bd->bdBufferLength= height* bd->bdBytesPerRow;
348     bd->bdPixelsWide= width;
349     bd->bdPixelsHigh= height;
350     bd->bdBitsPerSample= 1;
351     bd->bdSamplesPerPixel= 1;
352     bd->bdBitsPerPixel= 1;
353     bd->bdXResolution= 1;
354     bd->bdYResolution= 1;
355     bd->bdUnit= BMunPIXEL;
356     bd->bdColorEncoding= BMcoBLACKWHITE;
357     bd->bdHasAlpha= 0;
358     utilInitColorPalette( &(bd->bdPalette) );
359 
360     *pPrivateFormat= 11;
361 
362     bmXbmSetFlip();
363     s= *pBuffer;
364     for ( width = 0; width < bd->bdBufferLength; width++ )
365 	{ *s= BMXBMflip[*s]; s++; }
366 
367     return 0;
368     }
369