1 /* Zgv v3.0 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux.
2  * Copyright (C) 1993-1998 Russell Marks. See README for license details.
3  *
4  * readxbm.c - read an X bitmap.
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include "zgv.h"
11 #include "readxbm.h"
12 
13 
14 /* for aborted_file_xbm_cleanup() */
15 static unsigned char *work_bmap,*work_pal;
16 static FILE *work_in;
17 
18 
read_xbm_file(char * filename,hffunc howfarfunc,unsigned char ** bmap,unsigned char ** pal,int * output_type,PICINFO * pp)19 int read_xbm_file(char *filename,hffunc howfarfunc,unsigned char **bmap,
20                   unsigned char **pal,int *output_type,PICINFO *pp)
21 {
22 static unsigned char buf[1024];
23 FILE *in;
24 int w8,w,h,x,y,data;
25 unsigned char *image,*ptr;
26 int tmppos;
27 int i,mask;
28 
29 *bmap=NULL;
30 *pal=NULL;
31 
32 if((in=fopen(filename,"rb"))==NULL)
33   return(_PICERR_NOFILE);
34 
35 /* the format as defined in "Xlib - C Language X Interface"
36  * (in subsection 16.9, "Manipulating Bitmaps") is
37  * relatively strict, and this code follows it pretty
38  * much to the letter.
39  */
40 
41 /* first two lines must be:
42  * #define foo_width <width>
43  * #define foo_height <height>
44  *
45  * Inevitably, some people don't seem able to read the spec, so I've
46  * seen one or two files which don't work (they have comments in - but
47  * the spec doesn't provide for comments). :-(
48  */
49 
50 if(fgets(buf,sizeof(buf),in)==NULL || strncmp(buf,"#define ",8)!=0)
51   CLOSE_AND_RET(_PICERR_CORRUPT);
52 
53 /* read number after "_width" */
54 if((ptr=strstr(buf,"_width"))==NULL)
55   CLOSE_AND_RET(_PICERR_CORRUPT);
56 w=atoi(ptr+6);
57 
58 /* repeat for height */
59 if(fgets(buf,sizeof(buf),in)==NULL || strncmp(buf,"#define ",8)!=0)
60   CLOSE_AND_RET(_PICERR_CORRUPT);
61 
62 if((ptr=strstr(buf,"_height"))==NULL)
63   CLOSE_AND_RET(_PICERR_CORRUPT);
64 h=atoi(ptr+7);
65 
66 if(w==0 || h==0)
67   CLOSE_AND_RET(_PICERR_CORRUPT);
68 
69 /* ignore possible hotspot lines
70  * (the easiest way is to ignore until we get a line which doesn't
71  * start with "#define")
72  */
73 tmppos=ftell(in);
74 while(fgets(buf,sizeof(buf),in)!=NULL)
75   {
76   if(strncmp(buf,"#define ",8)!=0) break;
77   tmppos=ftell(in);
78   }
79 
80 /* check for "_bits[" and `{' */
81 if(strstr(buf,"_bits[")==NULL || (ptr=strrchr(buf,'{'))==NULL)
82   CLOSE_AND_RET(_PICERR_CORRUPT);
83 
84 
85 /* seek to just after the brace
86  * (bit nasty but it seems like the easiest way to deal with
87  * the possibility of hex on the line with the opening brace on)
88  */
89 fseek(in,tmppos+(ptr+1-buf),SEEK_SET);
90 
91 
92 if((*pal=calloc(768,1))==NULL)
93   CLOSE_AND_RET(_PICERR_NOMEM);
94 
95 (*pal)[0]=(*pal)[256]=(*pal)[512]=0;
96 (*pal)[1]=(*pal)[257]=(*pal)[513]=255;
97 
98 w8=(w+7)/8;
99 
100 if(WH_BAD(w,h) || (*bmap=image=malloc(w*h))==NULL)
101   CLOSE_AND_RET(_PICERR_NOMEM);
102 
103 /* save stuff in case of abort */
104 work_in=in; work_bmap=(*bmap); work_pal=*pal;
105 
106 
107 for(y=0;y<h;y++)
108   {
109   for(x=0;x<w8;x++)
110     {
111     if(fscanf(in,"%x",&data)!=1)
112       {
113       y=h;
114       break;
115       }
116 
117     fgetc(in);		/* remove comma (or LF or whatever) */
118 
119     for(i=0,mask=1;i<8;i++,mask<<=1)
120       if(x*8+i<w)
121         image[y*w+x*8+i]=((data&mask)?0:1);
122     }
123 
124   if(howfarfunc!=NULL) howfarfunc(y,h);
125   }
126 
127 fclose(in);
128 
129 pp->width=w;
130 pp->height=h;
131 pp->numcols=2;
132 
133 *output_type=1;
134 
135 return(_PIC_OK);
136 }
137 
138 
aborted_file_xbm_cleanup()139 void aborted_file_xbm_cleanup()
140 {
141 free(work_bmap);
142 free(work_pal);
143 fclose(work_in);
144 }
145