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