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