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 * bmtoa - bitmap to ascii filter
31eaef79e5Smrg * Author:  Jim Fulton, MIT X Consortium
32eaef79e5Smrg */
33eaef79e5Smrg
34eaef79e5Smrg#ifdef HAVE_CONFIG_H
35eaef79e5Smrg# include "config.h"
36eaef79e5Smrg#endif
37eaef79e5Smrg
38eaef79e5Smrg#include <stdio.h>
39eaef79e5Smrg#include <X11/Xlib.h>
40eaef79e5Smrg#include <X11/Xutil.h>
41eaef79e5Smrg#include <X11/Xos.h>
42eaef79e5Smrg
43eaef79e5Smrg#include <X11/Xmu/Drawing.h>
44eaef79e5Smrg
45eaef79e5Smrg#include <stdlib.h>
46eaef79e5Smrg#include <unistd.h>
47cbc4e2beSmrg#ifndef HAVE_MKSTEMP
48eaef79e5Smrgextern char *mktemp();
49eaef79e5Smrg#endif
50eaef79e5Smrg
512b32c8f7Smrgstatic char *ProgramName;
52eaef79e5Smrg
53cbc4e2beSmrgstatic void print_scanline (unsigned int width, unsigned int height,
54cbc4e2beSmrg			    unsigned const char *data, const char *chars);
55eaef79e5Smrg
56cbc4e2beSmrgstatic void _X_NORETURN
57433d0511Smrgusage (int exitval)
58eaef79e5Smrg{
59cbc4e2beSmrg    fprintf (stderr, "usage:  %s [-options ...] [filename]\n\n%s\n",
60cbc4e2beSmrg	     ProgramName,
61cbc4e2beSmrg	"where options include:\n"
62433d0511Smrg	"    -chars cc        chars to use for 0 and 1 bits, respectively\n"
63433d0511Smrg	"    -help            print this usage message\n"
64433d0511Smrg	"    -version         print version information\n"
65433d0511Smrg        );
66433d0511Smrg    exit (exitval);
67eaef79e5Smrg}
68eaef79e5Smrg
69eaef79e5Smrgstatic char *
70eaef79e5Smrgcopy_stdin (void)
71eaef79e5Smrg{
72eaef79e5Smrg#ifdef WIN32
73eaef79e5Smrg    static char tmpfilename[] = "/temp/bmtoa.XXXXXX";
74eaef79e5Smrg#else
75eaef79e5Smrg    static char tmpfilename[] = "/tmp/bmtoa.XXXXXX";
76eaef79e5Smrg#endif
77eaef79e5Smrg    char buf[BUFSIZ];
78cbc4e2beSmrg    FILE *fp = NULL;
79eaef79e5Smrg    int nread, nwritten;
80eaef79e5Smrg
81cbc4e2beSmrg#ifndef HAVE_MKSTEMP
82cbc4e2beSmrg    if (mktemp (tmpfilename) != NULL)
83cbc4e2beSmrg	fp = fopen (tmpfilename, "w");
84eaef79e5Smrg#else
85eaef79e5Smrg    int fd;
86cbc4e2beSmrg    if ((fd = mkstemp(tmpfilename)) >= 0)
87cbc4e2beSmrg	fp = fdopen(fd, "w");
88cbc4e2beSmrg#endif
89cbc4e2beSmrg    if (fp == NULL) {
90eaef79e5Smrg	fprintf (stderr,
91cbc4e2beSmrg		 "%s:  unable to generate temporary file for stdin.\n",
92eaef79e5Smrg		 ProgramName);
93eaef79e5Smrg	exit (1);
94eaef79e5Smrg    }
95eaef79e5Smrg    while (1) {
96eaef79e5Smrg	buf[0] = '\0';
97eaef79e5Smrg	nread = fread (buf, 1, sizeof buf, stdin);
98eaef79e5Smrg	if (nread <= 0) break;
99eaef79e5Smrg	nwritten = fwrite (buf, 1, nread, fp);
100eaef79e5Smrg	if (nwritten != nread) {
101eaef79e5Smrg	    fprintf (stderr,
102eaef79e5Smrg		     "%s:  error copying stdin to file (%d of %d chars)\n",
103eaef79e5Smrg		     ProgramName, nwritten, nread);
104eaef79e5Smrg	    (void) fclose (fp);
105eaef79e5Smrg	    (void) unlink (tmpfilename);
106eaef79e5Smrg	    exit (1);
107eaef79e5Smrg	}
108eaef79e5Smrg    }
109eaef79e5Smrg    (void) fclose (fp);
110eaef79e5Smrg    return tmpfilename;
111eaef79e5Smrg}
112eaef79e5Smrg
113eaef79e5Smrgint
114cbc4e2beSmrgmain (int argc, char *argv[])
115eaef79e5Smrg{
116cbc4e2beSmrg    const char *filename = NULL;
117eaef79e5Smrg    int isstdin = 0;
118cbc4e2beSmrg    const char *chars = "-#";
119eaef79e5Smrg    int i;
120eaef79e5Smrg    unsigned int width, height;
121eaef79e5Smrg    unsigned char *data;
122eaef79e5Smrg    int x_hot, y_hot;
123eaef79e5Smrg    int status;
124eaef79e5Smrg
125eaef79e5Smrg    ProgramName = argv[0];
126eaef79e5Smrg
127eaef79e5Smrg    for (i = 1; i < argc; i++) {
128cbc4e2beSmrg	const char *arg = argv[i];
129eaef79e5Smrg
130eaef79e5Smrg	if (arg[0] == '-') {
131eaef79e5Smrg	    switch (arg[1]) {
132eaef79e5Smrg	      case '\0':
133eaef79e5Smrg		filename = NULL;
134eaef79e5Smrg		continue;
135eaef79e5Smrg	      case 'c':
136d1a7ce7bSmrg		if (++i >= argc) {
137d1a7ce7bSmrg		    fprintf(stderr, "%s: -chars requires an argument\n",
138d1a7ce7bSmrg			    ProgramName);
139433d0511Smrg		    usage(1);
140d1a7ce7bSmrg		}
141eaef79e5Smrg		chars = argv[i];
142eaef79e5Smrg		continue;
143433d0511Smrg	      case 'h':
144433d0511Smrg		if (strcmp(arg, "-help") == 0) {
145433d0511Smrg		    usage(0);
146433d0511Smrg		}
147433d0511Smrg		goto unknown;
148433d0511Smrg	      case 'v':
149433d0511Smrg		if (strcmp(arg, "-version") == 0) {
150433d0511Smrg		    puts(PACKAGE_STRING);
151433d0511Smrg		    exit(0);
152433d0511Smrg		}
153433d0511Smrg                goto unknown;
154eaef79e5Smrg	      default:
155433d0511Smrg	      unknown:
156d1a7ce7bSmrg		fprintf(stderr, "%s: unrecognized option '%s'\n",
157d1a7ce7bSmrg			ProgramName, argv[i]);
158433d0511Smrg		usage(1);
159eaef79e5Smrg	    }
160eaef79e5Smrg	} else {
161eaef79e5Smrg	    filename = arg;
162eaef79e5Smrg	}
163eaef79e5Smrg    }
164eaef79e5Smrg
165eaef79e5Smrg    if (strlen (chars) != 2) {
166eaef79e5Smrg	fprintf (stderr,
167eaef79e5Smrg	 "%s:  bad character list \"%s\", must have exactly 2 characters\n",
168eaef79e5Smrg		 ProgramName, chars);
169eaef79e5Smrg	exit (1);
170eaef79e5Smrg    }
171eaef79e5Smrg
172eaef79e5Smrg    if (!filename) {
173eaef79e5Smrg	filename = copy_stdin ();
174eaef79e5Smrg	isstdin = 1;
175eaef79e5Smrg    }
176eaef79e5Smrg
177eaef79e5Smrg    status = XmuReadBitmapDataFromFile (filename, &width, &height, &data,
178eaef79e5Smrg					&x_hot, &y_hot);
179eaef79e5Smrg    if (isstdin) (void) unlink (filename);  /* don't need it anymore */
180eaef79e5Smrg    if (status != BitmapSuccess) {
181eaef79e5Smrg	fprintf (stderr, "%s:  unable to read bitmap from file \"%s\"\n",
182eaef79e5Smrg		 ProgramName, isstdin ? "(stdin)" : filename);
183eaef79e5Smrg	exit (1);
184eaef79e5Smrg    }
185eaef79e5Smrg
186eaef79e5Smrg    print_scanline (width, height, data, chars);
187eaef79e5Smrg    exit (0);
188eaef79e5Smrg}
189eaef79e5Smrg
190eaef79e5Smrgstatic void
191cbc4e2beSmrgprint_scanline (unsigned int width,
192cbc4e2beSmrg		unsigned int height,
193cbc4e2beSmrg		unsigned const char *data,
194cbc4e2beSmrg		const char *chars)
195eaef79e5Smrg{
196cbc4e2beSmrg    unsigned const char *dp = data;
197eaef79e5Smrg    int row, column;
198cbc4e2beSmrg    static unsigned const char masktable[] = {
199eaef79e5Smrg	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
200eaef79e5Smrg    int padded = ((width & 7) != 0);
201eaef79e5Smrg
202eaef79e5Smrg    for (row = 0; row < height; row++) {
203eaef79e5Smrg	for (column = 0; column < width; column++) {
204eaef79e5Smrg	    int i = (column & 7);
205eaef79e5Smrg
206eaef79e5Smrg	    if (*dp & masktable[i]) {
207eaef79e5Smrg		putchar (chars[1]);
208eaef79e5Smrg	    } else {
209eaef79e5Smrg		putchar (chars[0]);
210eaef79e5Smrg	    }
211eaef79e5Smrg
212eaef79e5Smrg	    if (i == 7) dp++;
213eaef79e5Smrg	}
214eaef79e5Smrg	putchar ('\n');
215eaef79e5Smrg	if (padded) dp++;
216eaef79e5Smrg    }
217eaef79e5Smrg    return;
218eaef79e5Smrg}
219eaef79e5Smrg
220