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