atobm.c revision cbc4e2be
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>
37cbc4e2beSmrg#include <X11/Xfuncproto.h>
38eaef79e5Smrg#include <stdlib.h>
39eaef79e5Smrg
402b32c8f7Smrgstatic char *ProgramName;
41eaef79e5Smrg
42cbc4e2beSmrgstatic void doit(FILE *fp, const char *filename, const char *chars,
43cbc4e2beSmrg		 int xhot, int yhot, const char *name);
44eaef79e5Smrg
45cbc4e2beSmrgstatic void _X_NORETURN
46eaef79e5Smrgusage (void)
47eaef79e5Smrg{
48cbc4e2beSmrg    fprintf (stderr, "usage:  %s [-options ...] [filename]\n\n%s\n",
49cbc4e2beSmrg	     ProgramName,
50cbc4e2beSmrg             "where options include:\n"
51cbc4e2beSmrg             "    -chars cc        chars to use for 0 and 1 bits, respectively\n"
52cbc4e2beSmrg             "    -name variable   name to use in bitmap file\n"
53cbc4e2beSmrg             "    -xhot number     x position of hotspot\n"
54cbc4e2beSmrg             "    -yhot number     y position of hotspot\n");
55eaef79e5Smrg    exit (1);
56eaef79e5Smrg}
57eaef79e5Smrg
58eaef79e5Smrg
59eaef79e5Smrgstatic char *
60eaef79e5Smrgcify_name (char *name)
61eaef79e5Smrg{
62eaef79e5Smrg    int length = name ? strlen (name) : 0;
63eaef79e5Smrg    int i;
64eaef79e5Smrg
65eaef79e5Smrg    for (i = 0; i < length; i++) {	/* strncpy (result, begin, length); */
66eaef79e5Smrg	char c = name[i];
67eaef79e5Smrg	if (!((isascii(c) && isalnum(c)) || c == '_')) name[i] = '_';
68eaef79e5Smrg    }
69eaef79e5Smrg    return name;
70eaef79e5Smrg}
71eaef79e5Smrg
72eaef79e5Smrgstatic char *
73eaef79e5SmrgStripName(char *name)
74eaef79e5Smrg{
75eaef79e5Smrg  char *begin = strrchr(name, '/');
76eaef79e5Smrg  char *end, *result;
77eaef79e5Smrg  int length;
78eaef79e5Smrg
79eaef79e5Smrg  begin = (begin ? begin+1 : name);
80eaef79e5Smrg  end = strchr(begin, '.');	/* change to strrchr to allow longer names */
81eaef79e5Smrg  length = (end ? (end - begin) : strlen (begin));
82eaef79e5Smrg  result = (char *) malloc (length + 1);
83eaef79e5Smrg  strncpy (result, begin, length);
84eaef79e5Smrg  result [length] = '\0';
85eaef79e5Smrg  return (result);
86eaef79e5Smrg}
87eaef79e5Smrg
88eaef79e5Smrgint
89eaef79e5Smrgmain (int argc, char *argv[])
90eaef79e5Smrg{
91eaef79e5Smrg    int i;
92eaef79e5Smrg    int xhot = -1, yhot = -1;
93eaef79e5Smrg    char *filename = NULL;
94cbc4e2beSmrg    const char *chars = "-#";
95cbc4e2beSmrg    const char *name = NULL;
96eaef79e5Smrg    FILE *fp;
97eaef79e5Smrg
98eaef79e5Smrg    ProgramName = argv[0];
99eaef79e5Smrg
100eaef79e5Smrg    for (i = 1; i < argc; i++) {
101eaef79e5Smrg	char *arg = argv[i];
102eaef79e5Smrg
103eaef79e5Smrg	if (arg[0] == '-') {
104eaef79e5Smrg	    switch (arg[1]) {
105eaef79e5Smrg	      case '\0':
106eaef79e5Smrg		filename = NULL;
107eaef79e5Smrg		continue;
108eaef79e5Smrg	      case 'c':
109eaef79e5Smrg		if (++i >= argc) usage ();
110eaef79e5Smrg		chars = argv[i];
111eaef79e5Smrg		continue;
112eaef79e5Smrg	      case 'n':
113eaef79e5Smrg		if (++i >= argc) usage ();
114eaef79e5Smrg		name = argv[i];
115eaef79e5Smrg		continue;
116eaef79e5Smrg	      case 'x':
117eaef79e5Smrg		if (++i >= argc) usage ();
118eaef79e5Smrg		xhot = atoi (argv[i]);
119eaef79e5Smrg		continue;
120eaef79e5Smrg	      case 'y':
121eaef79e5Smrg		if (++i >= argc) usage ();
122eaef79e5Smrg		yhot = atoi (argv[i]);
123eaef79e5Smrg		continue;
124eaef79e5Smrg	      default:
125eaef79e5Smrg		usage ();
126eaef79e5Smrg	    }
127eaef79e5Smrg	} else {
128eaef79e5Smrg	    filename = arg;
129eaef79e5Smrg	}
130eaef79e5Smrg    }
131eaef79e5Smrg
132eaef79e5Smrg    if (strlen (chars) != 2) {
133eaef79e5Smrg	fprintf (stderr,
134eaef79e5Smrg	 "%s:  bad character list \"%s\", must have exactly 2 characters\n",
135eaef79e5Smrg		 ProgramName, chars);
136eaef79e5Smrg	exit (1);
137eaef79e5Smrg    }
138eaef79e5Smrg
139eaef79e5Smrg    if (filename) {
140eaef79e5Smrg	fp = fopen (filename, "r");
141eaef79e5Smrg	if (!fp) {
142eaef79e5Smrg	    fprintf (stderr, "%s:  unable to open file \"%s\".\n",
143eaef79e5Smrg		     ProgramName, filename);
144eaef79e5Smrg	    exit (1);
145eaef79e5Smrg	}
146eaef79e5Smrg    } else {
147eaef79e5Smrg	fp = stdin;
148eaef79e5Smrg    }
149eaef79e5Smrg
150cbc4e2beSmrg    if (!name)
151cbc4e2beSmrg	name = filename ? cify_name (StripName (filename)) : "";
152eaef79e5Smrg    doit (fp, filename, chars, xhot, yhot, name);
153eaef79e5Smrg
154eaef79e5Smrg    if (filename) (void) fclose (fp);
155eaef79e5Smrg    exit (0);
156eaef79e5Smrg}
157eaef79e5Smrg
158eaef79e5Smrg
159eaef79e5Smrgstatic void
160cbc4e2beSmrgdoit (FILE *fp,
161cbc4e2beSmrg      const char *filename,
162cbc4e2beSmrg      const char *chars,
163cbc4e2beSmrg      int xhot, int yhot,
164cbc4e2beSmrg      const char *name)
165eaef79e5Smrg{
166eaef79e5Smrg    int i, j;
167eaef79e5Smrg    int last_character;
168eaef79e5Smrg    char buf[BUFSIZ];
169eaef79e5Smrg    char *cp, *newline;
170eaef79e5Smrg    int width = 0, height = 0;
171eaef79e5Smrg    int len;
172eaef79e5Smrg    int removespace = (((isascii(chars[0]) && isspace(chars[0])) ||
173eaef79e5Smrg			(isascii(chars[1]) && isspace(chars[1]))) ? 0 : 1);
174eaef79e5Smrg    int lineno = 0;
175eaef79e5Smrg    int bytes_per_scanline = 0;
176eaef79e5Smrg    struct _scan_list {
177eaef79e5Smrg	int allocated;
178eaef79e5Smrg	int used;
179eaef79e5Smrg	unsigned char *scanlines;
180eaef79e5Smrg	struct _scan_list *next;
181eaef79e5Smrg    } *head = NULL, *slist = NULL;
182eaef79e5Smrg    static unsigned char masktable[] = {
183eaef79e5Smrg	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
184eaef79e5Smrg    int padded = 0;
185cbc4e2beSmrg
186eaef79e5Smrg#define NTOALLOC 16
187eaef79e5Smrg#define NewSList() \
188eaef79e5Smrg	    slist = (struct _scan_list *) calloc (1, sizeof *slist); \
189eaef79e5Smrg	    if (!slist) { \
190eaef79e5Smrg		fprintf (stderr, "%s:  unable to allocate scan list\n", \
191eaef79e5Smrg			 ProgramName); \
192eaef79e5Smrg		return; \
193eaef79e5Smrg	    } \
194eaef79e5Smrg	    slist->allocated = NTOALLOC * bytes_per_scanline; \
195eaef79e5Smrg	    slist->scanlines = (unsigned char *) calloc(slist->allocated, 1); \
196eaef79e5Smrg	    if (!slist->scanlines) { \
197eaef79e5Smrg		fprintf (stderr, "%s:  unable to allocate char array\n", \
198eaef79e5Smrg			 ProgramName); \
199eaef79e5Smrg		return; \
200eaef79e5Smrg	    } \
201eaef79e5Smrg	    slist->used = 0; \
202cbc4e2beSmrg	    slist->next = NULL;
203eaef79e5Smrg
204eaef79e5Smrg    while (1) {
205eaef79e5Smrg	buf[0] = '\0';
206eaef79e5Smrg	lineno++;
207eaef79e5Smrg	if (fgets (buf, sizeof buf, fp) == NULL) break;
208eaef79e5Smrg
209eaef79e5Smrg	cp = buf;
210eaef79e5Smrg	if (removespace) {
211eaef79e5Smrg	    for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++) ;
212eaef79e5Smrg	}
213eaef79e5Smrg	if (*cp == '\n' || !*cp) continue;  /* empty line */
214eaef79e5Smrg
215eaef79e5Smrg	newline = strchr(cp, '\n');
216eaef79e5Smrg	if (!newline) {
217eaef79e5Smrg	    fprintf (stderr, "%s:  line %d too long.\n",
218eaef79e5Smrg		     ProgramName, lineno);
219eaef79e5Smrg	    return;
220eaef79e5Smrg	}
221eaef79e5Smrg
222eaef79e5Smrg	if (removespace) {
223eaef79e5Smrg	    for (; --newline > cp && isascii(*newline) && isspace(*newline); );
224eaef79e5Smrg	    newline++;
225eaef79e5Smrg	}
226eaef79e5Smrg
227eaef79e5Smrg	if (newline == cp + 1) continue;
228eaef79e5Smrg
229eaef79e5Smrg	*newline = '\0';
230eaef79e5Smrg	len = strlen (cp);
231eaef79e5Smrg
232eaef79e5Smrg	if (width == 0) {
233eaef79e5Smrg	    width = len;
234eaef79e5Smrg	    padded = ((width & 7) != 0);
235eaef79e5Smrg	    bytes_per_scanline = (len + 7) / 8;
236eaef79e5Smrg	    NewSList ();
237eaef79e5Smrg	    head = slist;
238eaef79e5Smrg	} else if (width != len) {
239eaef79e5Smrg	    fprintf (stderr,
240eaef79e5Smrg		     "%s:  line %d is %d characters wide instead of %d\n",
241eaef79e5Smrg		     ProgramName, lineno, len, width);
242eaef79e5Smrg	    return;
243eaef79e5Smrg	}
244eaef79e5Smrg
245eaef79e5Smrg	if (slist->used + 1 >= slist->allocated) {
246eaef79e5Smrg	    struct _scan_list *old = slist;
247eaef79e5Smrg	    NewSList ();
248eaef79e5Smrg	    old->next = slist;
249eaef79e5Smrg	}
250eaef79e5Smrg
251eaef79e5Smrg	/* okay, parse the line and stick values into the scanline array */
252eaef79e5Smrg	for (i = 0; i < width; i++) {
253eaef79e5Smrg	    int ind = (i & 7);
254eaef79e5Smrg	    int on = 0;
255eaef79e5Smrg
256eaef79e5Smrg	    if (cp[i] == chars[1]) {
257eaef79e5Smrg		on = 1;
258eaef79e5Smrg	    } else if (cp[i] != chars[0]) {
259eaef79e5Smrg		fprintf (stderr, "%s:  bad character '%c' on line %d\n",
260eaef79e5Smrg			 ProgramName, cp[i], lineno);
261eaef79e5Smrg	    }
262eaef79e5Smrg
263eaef79e5Smrg	    if (on) slist->scanlines[slist->used] |= masktable[ind];
264eaef79e5Smrg	    if (ind == 7) slist->used++;
265eaef79e5Smrg	}
266eaef79e5Smrg	if (padded) slist->used++;
267eaef79e5Smrg	height++;
268eaef79e5Smrg    }
269eaef79e5Smrg
270eaef79e5Smrg    printf ("#define %s_width %d\n", name, width);
271eaef79e5Smrg    printf ("#define %s_height %d\n", name, height);
272eaef79e5Smrg    if (xhot >= 0) printf ("#define %s_x_hot %d\n", name, xhot);
273eaef79e5Smrg    if (yhot >= 0) printf ("#define %s_y_hot %d\n", name, yhot);
274eaef79e5Smrg    printf ("\n");
275eaef79e5Smrg    printf ("static unsigned char %s_bits[] = {\n", name);
276eaef79e5Smrg
277eaef79e5Smrg    j = 0;
278eaef79e5Smrg    last_character = height * bytes_per_scanline - 1;
279eaef79e5Smrg    for (slist = head; slist; slist = slist->next) {
280eaef79e5Smrg	for (i = 0; i < slist->used; i++) {
281eaef79e5Smrg	    printf (" 0x%02x", slist->scanlines[i]);
282eaef79e5Smrg	    if (j != last_character) putchar (',');
283eaef79e5Smrg	    if ((j % 12) == 11) putchar ('\n');
284eaef79e5Smrg	    j++;
285eaef79e5Smrg	}
286eaef79e5Smrg    }
287eaef79e5Smrg    printf (" };\n");
288eaef79e5Smrg    return;
289eaef79e5Smrg}
290