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 34433d0511Smrg#ifdef HAVE_CONFIG_H 35433d0511Smrg# include "config.h" 36433d0511Smrg#endif 37433d0511Smrg 38eaef79e5Smrg#include <stdio.h> 39eaef79e5Smrg#include <ctype.h> 40eaef79e5Smrg#include <X11/Xos.h> 41cbc4e2beSmrg#include <X11/Xfuncproto.h> 42eaef79e5Smrg#include <stdlib.h> 43eaef79e5Smrg 442b32c8f7Smrgstatic char *ProgramName; 45eaef79e5Smrg 46cbc4e2beSmrgstatic void doit(FILE *fp, const char *filename, const char *chars, 47cbc4e2beSmrg int xhot, int yhot, const char *name); 48eaef79e5Smrg 49d1a7ce7bSmrgstatic void _X_NORETURN _X_COLD 50433d0511Smrgusage (const char *msg, int exitval) 51eaef79e5Smrg{ 52d1a7ce7bSmrg if (msg) 53d1a7ce7bSmrg fprintf(stderr, "%s: %s\n", ProgramName, msg); 54cbc4e2beSmrg fprintf (stderr, "usage: %s [-options ...] [filename]\n\n%s\n", 55cbc4e2beSmrg ProgramName, 56cbc4e2beSmrg "where options include:\n" 57cbc4e2beSmrg " -chars cc chars to use for 0 and 1 bits, respectively\n" 58433d0511Smrg " -help print this message\n" 59cbc4e2beSmrg " -name variable name to use in bitmap file\n" 60433d0511Smrg " -version print version info\n" 61cbc4e2beSmrg " -xhot number x position of hotspot\n" 62cbc4e2beSmrg " -yhot number y position of hotspot\n"); 63433d0511Smrg exit(exitval); 64eaef79e5Smrg} 65eaef79e5Smrg 66d1a7ce7bSmrgstatic void _X_NORETURN _X_COLD 67d1a7ce7bSmrgmissing_arg (const char *option) 68d1a7ce7bSmrg{ 69d1a7ce7bSmrg char msg[32]; 70d1a7ce7bSmrg 71d1a7ce7bSmrg snprintf(msg, sizeof(msg), "%s requires an argument", option); 72433d0511Smrg usage(msg, 1); 73d1a7ce7bSmrg} 74eaef79e5Smrg 75eaef79e5Smrgstatic char * 76eaef79e5Smrgcify_name (char *name) 77eaef79e5Smrg{ 78eaef79e5Smrg int length = name ? strlen (name) : 0; 79eaef79e5Smrg int i; 80eaef79e5Smrg 81eaef79e5Smrg for (i = 0; i < length; i++) { /* strncpy (result, begin, length); */ 82eaef79e5Smrg char c = name[i]; 83eaef79e5Smrg if (!((isascii(c) && isalnum(c)) || c == '_')) name[i] = '_'; 84eaef79e5Smrg } 85eaef79e5Smrg return name; 86eaef79e5Smrg} 87eaef79e5Smrg 88eaef79e5Smrgstatic char * 89eaef79e5SmrgStripName(char *name) 90eaef79e5Smrg{ 91eaef79e5Smrg char *begin = strrchr(name, '/'); 92eaef79e5Smrg char *end, *result; 93eaef79e5Smrg int length; 94eaef79e5Smrg 95eaef79e5Smrg begin = (begin ? begin+1 : name); 96eaef79e5Smrg end = strchr(begin, '.'); /* change to strrchr to allow longer names */ 97eaef79e5Smrg length = (end ? (end - begin) : strlen (begin)); 98eaef79e5Smrg result = (char *) malloc (length + 1); 99eaef79e5Smrg strncpy (result, begin, length); 100eaef79e5Smrg result [length] = '\0'; 101eaef79e5Smrg return (result); 102eaef79e5Smrg} 103eaef79e5Smrg 104eaef79e5Smrgint 105eaef79e5Smrgmain (int argc, char *argv[]) 106eaef79e5Smrg{ 107eaef79e5Smrg int i; 108eaef79e5Smrg int xhot = -1, yhot = -1; 109eaef79e5Smrg char *filename = NULL; 110cbc4e2beSmrg const char *chars = "-#"; 111cbc4e2beSmrg const char *name = NULL; 112eaef79e5Smrg FILE *fp; 113eaef79e5Smrg 114eaef79e5Smrg ProgramName = argv[0]; 115eaef79e5Smrg 116eaef79e5Smrg for (i = 1; i < argc; i++) { 117eaef79e5Smrg char *arg = argv[i]; 118eaef79e5Smrg 119eaef79e5Smrg if (arg[0] == '-') { 120eaef79e5Smrg switch (arg[1]) { 121eaef79e5Smrg case '\0': 122eaef79e5Smrg filename = NULL; 123eaef79e5Smrg continue; 124eaef79e5Smrg case 'c': 125d1a7ce7bSmrg if (++i >= argc) missing_arg("-chars"); 126eaef79e5Smrg chars = argv[i]; 127eaef79e5Smrg continue; 128433d0511Smrg case 'h': 129433d0511Smrg if (strcmp(arg, "-help") == 0) { 130433d0511Smrg usage(NULL, 0); 131433d0511Smrg } 132433d0511Smrg goto unknown; 133eaef79e5Smrg case 'n': 134d1a7ce7bSmrg if (++i >= argc) missing_arg("-name"); 135eaef79e5Smrg name = argv[i]; 136eaef79e5Smrg continue; 137433d0511Smrg case 'v': 138433d0511Smrg if (strcmp(arg, "-version") == 0) { 139433d0511Smrg puts(PACKAGE_STRING); 140433d0511Smrg exit(0); 141433d0511Smrg } 142433d0511Smrg goto unknown; 143eaef79e5Smrg case 'x': 144d1a7ce7bSmrg if (++i >= argc) missing_arg("-xhot"); 145eaef79e5Smrg xhot = atoi (argv[i]); 146eaef79e5Smrg continue; 147eaef79e5Smrg case 'y': 148d1a7ce7bSmrg if (++i >= argc) missing_arg("-yhot"); 149eaef79e5Smrg yhot = atoi (argv[i]); 150eaef79e5Smrg continue; 151eaef79e5Smrg default: 152433d0511Smrg unknown: 153d1a7ce7bSmrg fprintf(stderr, "%s: unrecognized option '%s'\n", 154d1a7ce7bSmrg ProgramName, argv[i]); 155433d0511Smrg usage(NULL, 1); 156eaef79e5Smrg } 157eaef79e5Smrg } else { 158eaef79e5Smrg filename = arg; 159eaef79e5Smrg } 160eaef79e5Smrg } 161eaef79e5Smrg 162eaef79e5Smrg if (strlen (chars) != 2) { 163eaef79e5Smrg fprintf (stderr, 164eaef79e5Smrg "%s: bad character list \"%s\", must have exactly 2 characters\n", 165eaef79e5Smrg ProgramName, chars); 166eaef79e5Smrg exit (1); 167eaef79e5Smrg } 168eaef79e5Smrg 169eaef79e5Smrg if (filename) { 170eaef79e5Smrg fp = fopen (filename, "r"); 171eaef79e5Smrg if (!fp) { 172eaef79e5Smrg fprintf (stderr, "%s: unable to open file \"%s\".\n", 173eaef79e5Smrg ProgramName, filename); 174eaef79e5Smrg exit (1); 175eaef79e5Smrg } 176eaef79e5Smrg } else { 177eaef79e5Smrg fp = stdin; 178eaef79e5Smrg } 179eaef79e5Smrg 180cbc4e2beSmrg if (!name) 181cbc4e2beSmrg name = filename ? cify_name (StripName (filename)) : ""; 182eaef79e5Smrg doit (fp, filename, chars, xhot, yhot, name); 183eaef79e5Smrg 184eaef79e5Smrg if (filename) (void) fclose (fp); 185eaef79e5Smrg exit (0); 186eaef79e5Smrg} 187eaef79e5Smrg 188d1a7ce7bSmrgstruct _scan_list { 189d1a7ce7bSmrg int allocated; 190d1a7ce7bSmrg int used; 191d1a7ce7bSmrg unsigned char *scanlines; 192d1a7ce7bSmrg struct _scan_list *next; 193d1a7ce7bSmrg}; 194d1a7ce7bSmrg 195d1a7ce7bSmrg#define NTOALLOC 16 196d1a7ce7bSmrgstatic inline struct _scan_list * 197d1a7ce7bSmrg_new_scan_list(int bytes_per_scanline) { 198d1a7ce7bSmrg struct _scan_list *slist = (struct _scan_list *) calloc (1, sizeof(*slist)); 199d1a7ce7bSmrg if (!slist) { 200d1a7ce7bSmrg return NULL; 201d1a7ce7bSmrg } 202d1a7ce7bSmrg slist->allocated = NTOALLOC * bytes_per_scanline; 203d1a7ce7bSmrg slist->scanlines = (unsigned char *) calloc(slist->allocated, 1); 204d1a7ce7bSmrg if (!slist->scanlines) { 205d1a7ce7bSmrg free(slist); 206d1a7ce7bSmrg return NULL; 207d1a7ce7bSmrg } 208d1a7ce7bSmrg slist->used = 0; 209d1a7ce7bSmrg slist->next = NULL; 210d1a7ce7bSmrg 211d1a7ce7bSmrg return slist; 212d1a7ce7bSmrg} 213eaef79e5Smrg 214eaef79e5Smrgstatic void 215cbc4e2beSmrgdoit (FILE *fp, 216cbc4e2beSmrg const char *filename, 217cbc4e2beSmrg const char *chars, 218cbc4e2beSmrg int xhot, int yhot, 219cbc4e2beSmrg const char *name) 220eaef79e5Smrg{ 221eaef79e5Smrg int i, j; 222eaef79e5Smrg int last_character; 223eaef79e5Smrg char buf[BUFSIZ]; 224eaef79e5Smrg char *cp, *newline; 225eaef79e5Smrg int width = 0, height = 0; 226eaef79e5Smrg int len; 227eaef79e5Smrg int removespace = (((isascii(chars[0]) && isspace(chars[0])) || 228eaef79e5Smrg (isascii(chars[1]) && isspace(chars[1]))) ? 0 : 1); 229eaef79e5Smrg int lineno = 0; 230eaef79e5Smrg int bytes_per_scanline = 0; 231d1a7ce7bSmrg struct _scan_list *head = NULL, *slist = NULL; 232eaef79e5Smrg static unsigned char masktable[] = { 233eaef79e5Smrg 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; 234eaef79e5Smrg int padded = 0; 235cbc4e2beSmrg 236eaef79e5Smrg while (1) { 237eaef79e5Smrg buf[0] = '\0'; 238eaef79e5Smrg lineno++; 239eaef79e5Smrg if (fgets (buf, sizeof buf, fp) == NULL) break; 240eaef79e5Smrg 241eaef79e5Smrg cp = buf; 242eaef79e5Smrg if (removespace) { 243eaef79e5Smrg for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++) ; 244eaef79e5Smrg } 245eaef79e5Smrg if (*cp == '\n' || !*cp) continue; /* empty line */ 246eaef79e5Smrg 247eaef79e5Smrg newline = strchr(cp, '\n'); 248eaef79e5Smrg if (!newline) { 249eaef79e5Smrg fprintf (stderr, "%s: line %d too long.\n", 250eaef79e5Smrg ProgramName, lineno); 251eaef79e5Smrg return; 252eaef79e5Smrg } 253eaef79e5Smrg 254eaef79e5Smrg if (removespace) { 255eaef79e5Smrg for (; --newline > cp && isascii(*newline) && isspace(*newline); ); 256eaef79e5Smrg newline++; 257eaef79e5Smrg } 258eaef79e5Smrg 2597515ee80Smrg if (newline == cp) continue; 260eaef79e5Smrg 261eaef79e5Smrg *newline = '\0'; 262eaef79e5Smrg len = strlen (cp); 263eaef79e5Smrg 2647515ee80Smrg if (head == NULL) { 265eaef79e5Smrg width = len; 266eaef79e5Smrg padded = ((width & 7) != 0); 267eaef79e5Smrg bytes_per_scanline = (len + 7) / 8; 268d1a7ce7bSmrg head = slist = _new_scan_list(bytes_per_scanline); 269d1a7ce7bSmrg 270d1a7ce7bSmrg if (!slist) { 271d1a7ce7bSmrg fprintf (stderr, "%s: unable to allocate scan list\n", ProgramName); 272d1a7ce7bSmrg return; 273d1a7ce7bSmrg } 274eaef79e5Smrg } else if (width != len) { 275eaef79e5Smrg fprintf (stderr, 276eaef79e5Smrg "%s: line %d is %d characters wide instead of %d\n", 277eaef79e5Smrg ProgramName, lineno, len, width); 2787515ee80Smrg goto bail; 279eaef79e5Smrg } 280eaef79e5Smrg 281eaef79e5Smrg if (slist->used + 1 >= slist->allocated) { 282eaef79e5Smrg struct _scan_list *old = slist; 283d1a7ce7bSmrg old->next = slist = _new_scan_list(bytes_per_scanline); 284d1a7ce7bSmrg 285d1a7ce7bSmrg if (!slist) { 286d1a7ce7bSmrg fprintf (stderr, "%s: unable to allocate scan list\n", ProgramName); 2877515ee80Smrg goto bail; 288d1a7ce7bSmrg } 289eaef79e5Smrg } 290eaef79e5Smrg 291eaef79e5Smrg /* okay, parse the line and stick values into the scanline array */ 292eaef79e5Smrg for (i = 0; i < width; i++) { 293eaef79e5Smrg int ind = (i & 7); 294eaef79e5Smrg int on = 0; 295eaef79e5Smrg 296eaef79e5Smrg if (cp[i] == chars[1]) { 297eaef79e5Smrg on = 1; 298eaef79e5Smrg } else if (cp[i] != chars[0]) { 299eaef79e5Smrg fprintf (stderr, "%s: bad character '%c' on line %d\n", 300eaef79e5Smrg ProgramName, cp[i], lineno); 301eaef79e5Smrg } 302eaef79e5Smrg 303eaef79e5Smrg if (on) slist->scanlines[slist->used] |= masktable[ind]; 304eaef79e5Smrg if (ind == 7) slist->used++; 305eaef79e5Smrg } 306eaef79e5Smrg if (padded) slist->used++; 307eaef79e5Smrg height++; 308eaef79e5Smrg } 309eaef79e5Smrg 310eaef79e5Smrg printf ("#define %s_width %d\n", name, width); 311eaef79e5Smrg printf ("#define %s_height %d\n", name, height); 312eaef79e5Smrg if (xhot >= 0) printf ("#define %s_x_hot %d\n", name, xhot); 313eaef79e5Smrg if (yhot >= 0) printf ("#define %s_y_hot %d\n", name, yhot); 314eaef79e5Smrg printf ("\n"); 315eaef79e5Smrg printf ("static unsigned char %s_bits[] = {\n", name); 316eaef79e5Smrg 317eaef79e5Smrg j = 0; 318eaef79e5Smrg last_character = height * bytes_per_scanline - 1; 319eaef79e5Smrg for (slist = head; slist; slist = slist->next) { 320eaef79e5Smrg for (i = 0; i < slist->used; i++) { 321eaef79e5Smrg printf (" 0x%02x", slist->scanlines[i]); 322eaef79e5Smrg if (j != last_character) putchar (','); 323eaef79e5Smrg if ((j % 12) == 11) putchar ('\n'); 324eaef79e5Smrg j++; 325eaef79e5Smrg } 326eaef79e5Smrg } 327eaef79e5Smrg printf (" };\n"); 3287515ee80Smrg bail: 3297515ee80Smrg for (slist = head; slist != NULL; slist = head) { 3307515ee80Smrg head = slist->next; 3317515ee80Smrg free(slist->scanlines); 3327515ee80Smrg free(slist); 3337515ee80Smrg } 334eaef79e5Smrg return; 335eaef79e5Smrg} 336