atobm.c revision 2b32c8f7
1eaef79e5Smrg/*
2eaef79e5Smrg
3eaef79e5SmrgCopyright 1988, 1993, 1998  The Open Group
4eaef79e5Smrg
5eaef79e5SmrgPermission to use, copy, modify, distribute, and sell this software and its
6eaef79e5Smrgdocumentation for any purpose is hereby granted without fee, provided that
7eaef79e5Smrgthe above copyright notice appear in all copies and that both that
8eaef79e5Smrgcopyright notice and this permission notice appear in supporting
9eaef79e5Smrgdocumentation.
10eaef79e5Smrg
11eaef79e5SmrgThe above copyright notice and this permission notice shall be included
12eaef79e5Smrgin all copies or substantial portions of the Software.
13eaef79e5Smrg
14eaef79e5SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15eaef79e5SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16eaef79e5SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17eaef79e5SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18eaef79e5SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19eaef79e5SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20eaef79e5SmrgOTHER DEALINGS IN THE SOFTWARE.
21eaef79e5Smrg
22eaef79e5SmrgExcept as contained in this notice, the name of The Open Group shall
23eaef79e5Smrgnot be used in advertising or otherwise to promote the sale, use or
24eaef79e5Smrgother dealings in this Software without prior written authorization
25eaef79e5Smrgfrom The Open Group.
26eaef79e5Smrg
27eaef79e5Smrg*/
28eaef79e5Smrg
29eaef79e5Smrg/*
30eaef79e5Smrg * atobm - ascii to bitmap filter
31eaef79e5Smrg * Author:  Jim Fulton, MIT X Consortium
32eaef79e5Smrg */
33eaef79e5Smrg
34eaef79e5Smrg#include <stdio.h>
35eaef79e5Smrg#include <ctype.h>
36eaef79e5Smrg#include <X11/Xos.h>
37eaef79e5Smrg#include <stdlib.h>
38eaef79e5Smrg
392b32c8f7Smrgstatic char *ProgramName;
40eaef79e5Smrg
41eaef79e5Smrgstatic void doit(FILE *fp, char *filename, char *chars,
42eaef79e5Smrg		 int xhot, int yhot, char *name);
43eaef79e5Smrg
44eaef79e5Smrgstatic void
45eaef79e5Smrgusage (void)
46eaef79e5Smrg{
47eaef79e5Smrg    fprintf (stderr, "usage:  %s [-options ...] [filename]\n\n",
48eaef79e5Smrg	     ProgramName);
49eaef79e5Smrg    fprintf (stderr,
50eaef79e5Smrg	"where options include:\n");
51eaef79e5Smrg    fprintf (stderr,
52eaef79e5Smrg	"    -chars cc        chars to use for 0 and 1 bits, respectively\n");
53eaef79e5Smrg    fprintf (stderr,
54eaef79e5Smrg	"    -name variable   name to use in bitmap file\n");
55eaef79e5Smrg    fprintf (stderr,
56eaef79e5Smrg	"    -xhot number     x position of hotspot\n");
57eaef79e5Smrg    fprintf (stderr,
58eaef79e5Smrg	"    -yhot number     y position of hotspot\n");
59eaef79e5Smrg    fprintf (stderr, "\n");
60eaef79e5Smrg    exit (1);
61eaef79e5Smrg}
62eaef79e5Smrg
63eaef79e5Smrg
64eaef79e5Smrgstatic char *
65eaef79e5Smrgcify_name (char *name)
66eaef79e5Smrg{
67eaef79e5Smrg    int length = name ? strlen (name) : 0;
68eaef79e5Smrg    int i;
69eaef79e5Smrg
70eaef79e5Smrg    for (i = 0; i < length; i++) {	/* strncpy (result, begin, length); */
71eaef79e5Smrg	char c = name[i];
72eaef79e5Smrg	if (!((isascii(c) && isalnum(c)) || c == '_')) name[i] = '_';
73eaef79e5Smrg    }
74eaef79e5Smrg    return name;
75eaef79e5Smrg}
76eaef79e5Smrg
77eaef79e5Smrgstatic char *
78eaef79e5SmrgStripName(char *name)
79eaef79e5Smrg{
80eaef79e5Smrg  char *begin = strrchr(name, '/');
81eaef79e5Smrg  char *end, *result;
82eaef79e5Smrg  int length;
83eaef79e5Smrg
84eaef79e5Smrg  begin = (begin ? begin+1 : name);
85eaef79e5Smrg  end = strchr(begin, '.');	/* change to strrchr to allow longer names */
86eaef79e5Smrg  length = (end ? (end - begin) : strlen (begin));
87eaef79e5Smrg  result = (char *) malloc (length + 1);
88eaef79e5Smrg  strncpy (result, begin, length);
89eaef79e5Smrg  result [length] = '\0';
90eaef79e5Smrg  return (result);
91eaef79e5Smrg}
92eaef79e5Smrg
93eaef79e5Smrgint
94eaef79e5Smrgmain (int argc, char *argv[])
95eaef79e5Smrg{
96eaef79e5Smrg    int i;
97eaef79e5Smrg    int xhot = -1, yhot = -1;
98eaef79e5Smrg    char *filename = NULL;
99eaef79e5Smrg    char *chars = "-#";
100eaef79e5Smrg    char *name = NULL;
101eaef79e5Smrg    FILE *fp;
102eaef79e5Smrg
103eaef79e5Smrg    ProgramName = argv[0];
104eaef79e5Smrg
105eaef79e5Smrg    for (i = 1; i < argc; i++) {
106eaef79e5Smrg	char *arg = argv[i];
107eaef79e5Smrg
108eaef79e5Smrg	if (arg[0] == '-') {
109eaef79e5Smrg	    switch (arg[1]) {
110eaef79e5Smrg	      case '\0':
111eaef79e5Smrg		filename = NULL;
112eaef79e5Smrg		continue;
113eaef79e5Smrg	      case 'c':
114eaef79e5Smrg		if (++i >= argc) usage ();
115eaef79e5Smrg		chars = argv[i];
116eaef79e5Smrg		continue;
117eaef79e5Smrg	      case 'n':
118eaef79e5Smrg		if (++i >= argc) usage ();
119eaef79e5Smrg		name = argv[i];
120eaef79e5Smrg		continue;
121eaef79e5Smrg	      case 'x':
122eaef79e5Smrg		if (++i >= argc) usage ();
123eaef79e5Smrg		xhot = atoi (argv[i]);
124eaef79e5Smrg		continue;
125eaef79e5Smrg	      case 'y':
126eaef79e5Smrg		if (++i >= argc) usage ();
127eaef79e5Smrg		yhot = atoi (argv[i]);
128eaef79e5Smrg		continue;
129eaef79e5Smrg	      default:
130eaef79e5Smrg		usage ();
131eaef79e5Smrg	    }
132eaef79e5Smrg	} else {
133eaef79e5Smrg	    filename = arg;
134eaef79e5Smrg	}
135eaef79e5Smrg    }
136eaef79e5Smrg
137eaef79e5Smrg    if (strlen (chars) != 2) {
138eaef79e5Smrg	fprintf (stderr,
139eaef79e5Smrg	 "%s:  bad character list \"%s\", must have exactly 2 characters\n",
140eaef79e5Smrg		 ProgramName, chars);
141eaef79e5Smrg	exit (1);
142eaef79e5Smrg    }
143eaef79e5Smrg
144eaef79e5Smrg    if (filename) {
145eaef79e5Smrg	fp = fopen (filename, "r");
146eaef79e5Smrg	if (!fp) {
147eaef79e5Smrg	    fprintf (stderr, "%s:  unable to open file \"%s\".\n",
148eaef79e5Smrg		     ProgramName, filename);
149eaef79e5Smrg	    exit (1);
150eaef79e5Smrg	}
151eaef79e5Smrg    } else {
152eaef79e5Smrg	fp = stdin;
153eaef79e5Smrg    }
154eaef79e5Smrg
155eaef79e5Smrg    if (!name) name = filename ? StripName (filename) : "";
156eaef79e5Smrg    cify_name (name);
157eaef79e5Smrg    doit (fp, filename, chars, xhot, yhot, name);
158eaef79e5Smrg
159eaef79e5Smrg    if (filename) (void) fclose (fp);
160eaef79e5Smrg    exit (0);
161eaef79e5Smrg}
162eaef79e5Smrg
163eaef79e5Smrg
164eaef79e5Smrgstatic void
165eaef79e5Smrgdoit (FILE *fp,
166eaef79e5Smrg      char *filename,
167eaef79e5Smrg      char *chars,
168eaef79e5Smrg      int xhot, int yhot,
169eaef79e5Smrg      char *name)
170eaef79e5Smrg{
171eaef79e5Smrg    int i, j;
172eaef79e5Smrg    int last_character;
173eaef79e5Smrg    char buf[BUFSIZ];
174eaef79e5Smrg    char *cp, *newline;
175eaef79e5Smrg    int width = 0, height = 0;
176eaef79e5Smrg    int len;
177eaef79e5Smrg    int removespace = (((isascii(chars[0]) && isspace(chars[0])) ||
178eaef79e5Smrg			(isascii(chars[1]) && isspace(chars[1]))) ? 0 : 1);
179eaef79e5Smrg    int lineno = 0;
180eaef79e5Smrg    int bytes_per_scanline = 0;
181eaef79e5Smrg    struct _scan_list {
182eaef79e5Smrg	int allocated;
183eaef79e5Smrg	int used;
184eaef79e5Smrg	unsigned char *scanlines;
185eaef79e5Smrg	struct _scan_list *next;
186eaef79e5Smrg    } *head = NULL, *slist = NULL;
187eaef79e5Smrg    static unsigned char masktable[] = {
188eaef79e5Smrg	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
189eaef79e5Smrg    int padded = 0;
190eaef79e5Smrg
191eaef79e5Smrg#define NTOALLOC 16
192eaef79e5Smrg#define NewSList() \
193eaef79e5Smrg	    slist = (struct _scan_list *) calloc (1, sizeof *slist); \
194eaef79e5Smrg	    if (!slist) { \
195eaef79e5Smrg		fprintf (stderr, "%s:  unable to allocate scan list\n", \
196eaef79e5Smrg			 ProgramName); \
197eaef79e5Smrg		return; \
198eaef79e5Smrg	    } \
199eaef79e5Smrg	    slist->allocated = NTOALLOC * bytes_per_scanline; \
200eaef79e5Smrg	    slist->scanlines = (unsigned char *) calloc(slist->allocated, 1); \
201eaef79e5Smrg	    if (!slist->scanlines) { \
202eaef79e5Smrg		fprintf (stderr, "%s:  unable to allocate char array\n", \
203eaef79e5Smrg			 ProgramName); \
204eaef79e5Smrg		return; \
205eaef79e5Smrg	    } \
206eaef79e5Smrg	    slist->used = 0; \
207eaef79e5Smrg	    slist->next = NULL;
208eaef79e5Smrg
209eaef79e5Smrg    while (1) {
210eaef79e5Smrg	buf[0] = '\0';
211eaef79e5Smrg	lineno++;
212eaef79e5Smrg	if (fgets (buf, sizeof buf, fp) == NULL) break;
213eaef79e5Smrg
214eaef79e5Smrg	cp = buf;
215eaef79e5Smrg	if (removespace) {
216eaef79e5Smrg	    for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++) ;
217eaef79e5Smrg	}
218eaef79e5Smrg	if (*cp == '\n' || !*cp) continue;  /* empty line */
219eaef79e5Smrg
220eaef79e5Smrg	newline = strchr(cp, '\n');
221eaef79e5Smrg	if (!newline) {
222eaef79e5Smrg	    fprintf (stderr, "%s:  line %d too long.\n",
223eaef79e5Smrg		     ProgramName, lineno);
224eaef79e5Smrg	    return;
225eaef79e5Smrg	}
226eaef79e5Smrg
227eaef79e5Smrg	if (removespace) {
228eaef79e5Smrg	    for (; --newline > cp && isascii(*newline) && isspace(*newline); );
229eaef79e5Smrg	    newline++;
230eaef79e5Smrg	}
231eaef79e5Smrg
232eaef79e5Smrg	if (newline == cp + 1) continue;
233eaef79e5Smrg
234eaef79e5Smrg	*newline = '\0';
235eaef79e5Smrg	len = strlen (cp);
236eaef79e5Smrg
237eaef79e5Smrg	if (width == 0) {
238eaef79e5Smrg	    width = len;
239eaef79e5Smrg	    padded = ((width & 7) != 0);
240eaef79e5Smrg	    bytes_per_scanline = (len + 7) / 8;
241eaef79e5Smrg	    NewSList ();
242eaef79e5Smrg	    head = slist;
243eaef79e5Smrg	} else if (width != len) {
244eaef79e5Smrg	    fprintf (stderr,
245eaef79e5Smrg		     "%s:  line %d is %d characters wide instead of %d\n",
246eaef79e5Smrg		     ProgramName, lineno, len, width);
247eaef79e5Smrg	    return;
248eaef79e5Smrg	}
249eaef79e5Smrg
250eaef79e5Smrg	if (slist->used + 1 >= slist->allocated) {
251eaef79e5Smrg	    struct _scan_list *old = slist;
252eaef79e5Smrg	    NewSList ();
253eaef79e5Smrg	    old->next = slist;
254eaef79e5Smrg	}
255eaef79e5Smrg
256eaef79e5Smrg	/* okay, parse the line and stick values into the scanline array */
257eaef79e5Smrg	for (i = 0; i < width; i++) {
258eaef79e5Smrg	    int ind = (i & 7);
259eaef79e5Smrg	    int on = 0;
260eaef79e5Smrg
261eaef79e5Smrg	    if (cp[i] == chars[1]) {
262eaef79e5Smrg		on = 1;
263eaef79e5Smrg	    } else if (cp[i] != chars[0]) {
264eaef79e5Smrg		fprintf (stderr, "%s:  bad character '%c' on line %d\n",
265eaef79e5Smrg			 ProgramName, cp[i], lineno);
266eaef79e5Smrg	    }
267eaef79e5Smrg
268eaef79e5Smrg	    if (on) slist->scanlines[slist->used] |= masktable[ind];
269eaef79e5Smrg	    if (ind == 7) slist->used++;
270eaef79e5Smrg	}
271eaef79e5Smrg	if (padded) slist->used++;
272eaef79e5Smrg	height++;
273eaef79e5Smrg    }
274eaef79e5Smrg
275eaef79e5Smrg    printf ("#define %s_width %d\n", name, width);
276eaef79e5Smrg    printf ("#define %s_height %d\n", name, height);
277eaef79e5Smrg    if (xhot >= 0) printf ("#define %s_x_hot %d\n", name, xhot);
278eaef79e5Smrg    if (yhot >= 0) printf ("#define %s_y_hot %d\n", name, yhot);
279eaef79e5Smrg    printf ("\n");
280eaef79e5Smrg    printf ("static unsigned char %s_bits[] = {\n", name);
281eaef79e5Smrg
282eaef79e5Smrg    j = 0;
283eaef79e5Smrg    last_character = height * bytes_per_scanline - 1;
284eaef79e5Smrg    for (slist = head; slist; slist = slist->next) {
285eaef79e5Smrg	for (i = 0; i < slist->used; i++) {
286eaef79e5Smrg	    printf (" 0x%02x", slist->scanlines[i]);
287eaef79e5Smrg	    if (j != last_character) putchar (',');
288eaef79e5Smrg	    if ((j % 12) == 11) putchar ('\n');
289eaef79e5Smrg	    j++;
290eaef79e5Smrg	}
291eaef79e5Smrg    }
292eaef79e5Smrg    printf (" };\n");
293eaef79e5Smrg    return;
294eaef79e5Smrg}
295