1*a67afe4dSAndroid Build Coastguard Worker /*---------------------------------------------------------------------------
2*a67afe4dSAndroid Build Coastguard Worker
3*a67afe4dSAndroid Build Coastguard Worker wpng - simple PNG-writing program wpng.c
4*a67afe4dSAndroid Build Coastguard Worker
5*a67afe4dSAndroid Build Coastguard Worker This program converts certain NetPBM binary files (grayscale and RGB,
6*a67afe4dSAndroid Build Coastguard Worker maxval = 255) to PNG. Non-interlaced PNGs are written progressively;
7*a67afe4dSAndroid Build Coastguard Worker interlaced PNGs are read and written in one memory-intensive blast.
8*a67afe4dSAndroid Build Coastguard Worker
9*a67afe4dSAndroid Build Coastguard Worker Thanks to Jean-loup Gailly for providing the necessary trick to read
10*a67afe4dSAndroid Build Coastguard Worker interactive text from the keyboard while stdin is redirected. Thanks
11*a67afe4dSAndroid Build Coastguard Worker to Cosmin Truta for Cygwin fixes.
12*a67afe4dSAndroid Build Coastguard Worker
13*a67afe4dSAndroid Build Coastguard Worker NOTE: includes provisional support for PNM type "8" (portable alphamap)
14*a67afe4dSAndroid Build Coastguard Worker images, presumed to be a 32-bit interleaved RGBA format; no pro-
15*a67afe4dSAndroid Build Coastguard Worker vision for possible interleaved grayscale+alpha (16-bit) format.
16*a67afe4dSAndroid Build Coastguard Worker THIS IS UNLIKELY TO BECOME AN OFFICIAL NETPBM ALPHA FORMAT!
17*a67afe4dSAndroid Build Coastguard Worker
18*a67afe4dSAndroid Build Coastguard Worker to do:
19*a67afe4dSAndroid Build Coastguard Worker - delete output file if quit before calling any writepng routines
20*a67afe4dSAndroid Build Coastguard Worker - process backspace with -text option under DOS/Win? (currently get ^H)
21*a67afe4dSAndroid Build Coastguard Worker
22*a67afe4dSAndroid Build Coastguard Worker ---------------------------------------------------------------------------
23*a67afe4dSAndroid Build Coastguard Worker
24*a67afe4dSAndroid Build Coastguard Worker Changelog:
25*a67afe4dSAndroid Build Coastguard Worker - 1.01: initial public release
26*a67afe4dSAndroid Build Coastguard Worker - 1.02: modified to allow abbreviated options
27*a67afe4dSAndroid Build Coastguard Worker - 1.03: removed extraneous character from usage screen; fixed bug in
28*a67afe4dSAndroid Build Coastguard Worker command-line parsing
29*a67afe4dSAndroid Build Coastguard Worker - 1.04: fixed DOS/OS2/Win32 detection, including partial Cygwin fix
30*a67afe4dSAndroid Build Coastguard Worker (see http://home.att.net/~perlspinr/diffs/GregBook_cygwin.diff)
31*a67afe4dSAndroid Build Coastguard Worker - 2.00: dual-licensed (added GNU GPL)
32*a67afe4dSAndroid Build Coastguard Worker - 2.01: check for integer overflow (Glenn R-P)
33*a67afe4dSAndroid Build Coastguard Worker
34*a67afe4dSAndroid Build Coastguard Worker [REPORTED BUG (win32 only): "contrib/gregbook/wpng.c - cmd line
35*a67afe4dSAndroid Build Coastguard Worker dose not work! In order to do something useful I needed to redirect
36*a67afe4dSAndroid Build Coastguard Worker both input and output, with cygwin and with bcc32 as well. Under
37*a67afe4dSAndroid Build Coastguard Worker Linux, the same wpng appears to work fine. I don't know what is
38*a67afe4dSAndroid Build Coastguard Worker the problem."]
39*a67afe4dSAndroid Build Coastguard Worker
40*a67afe4dSAndroid Build Coastguard Worker ---------------------------------------------------------------------------
41*a67afe4dSAndroid Build Coastguard Worker
42*a67afe4dSAndroid Build Coastguard Worker Copyright (c) 1998-2007, 2017 Greg Roelofs. All rights reserved.
43*a67afe4dSAndroid Build Coastguard Worker
44*a67afe4dSAndroid Build Coastguard Worker This software is provided "as is," without warranty of any kind,
45*a67afe4dSAndroid Build Coastguard Worker express or implied. In no event shall the author or contributors
46*a67afe4dSAndroid Build Coastguard Worker be held liable for any damages arising in any way from the use of
47*a67afe4dSAndroid Build Coastguard Worker this software.
48*a67afe4dSAndroid Build Coastguard Worker
49*a67afe4dSAndroid Build Coastguard Worker The contents of this file are DUAL-LICENSED. You may modify and/or
50*a67afe4dSAndroid Build Coastguard Worker redistribute this software according to the terms of one of the
51*a67afe4dSAndroid Build Coastguard Worker following two licenses (at your option):
52*a67afe4dSAndroid Build Coastguard Worker
53*a67afe4dSAndroid Build Coastguard Worker
54*a67afe4dSAndroid Build Coastguard Worker LICENSE 1 ("BSD-like with advertising clause"):
55*a67afe4dSAndroid Build Coastguard Worker
56*a67afe4dSAndroid Build Coastguard Worker Permission is granted to anyone to use this software for any purpose,
57*a67afe4dSAndroid Build Coastguard Worker including commercial applications, and to alter it and redistribute
58*a67afe4dSAndroid Build Coastguard Worker it freely, subject to the following restrictions:
59*a67afe4dSAndroid Build Coastguard Worker
60*a67afe4dSAndroid Build Coastguard Worker 1. Redistributions of source code must retain the above copyright
61*a67afe4dSAndroid Build Coastguard Worker notice, disclaimer, and this list of conditions.
62*a67afe4dSAndroid Build Coastguard Worker 2. Redistributions in binary form must reproduce the above copyright
63*a67afe4dSAndroid Build Coastguard Worker notice, disclaimer, and this list of conditions in the documenta-
64*a67afe4dSAndroid Build Coastguard Worker tion and/or other materials provided with the distribution.
65*a67afe4dSAndroid Build Coastguard Worker 3. All advertising materials mentioning features or use of this
66*a67afe4dSAndroid Build Coastguard Worker software must display the following acknowledgment:
67*a67afe4dSAndroid Build Coastguard Worker
68*a67afe4dSAndroid Build Coastguard Worker This product includes software developed by Greg Roelofs
69*a67afe4dSAndroid Build Coastguard Worker and contributors for the book, "PNG: The Definitive Guide,"
70*a67afe4dSAndroid Build Coastguard Worker published by O'Reilly and Associates.
71*a67afe4dSAndroid Build Coastguard Worker
72*a67afe4dSAndroid Build Coastguard Worker
73*a67afe4dSAndroid Build Coastguard Worker LICENSE 2 (GNU GPL v2 or later):
74*a67afe4dSAndroid Build Coastguard Worker
75*a67afe4dSAndroid Build Coastguard Worker This program is free software; you can redistribute it and/or modify
76*a67afe4dSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
77*a67afe4dSAndroid Build Coastguard Worker the Free Software Foundation; either version 2 of the License, or
78*a67afe4dSAndroid Build Coastguard Worker (at your option) any later version.
79*a67afe4dSAndroid Build Coastguard Worker
80*a67afe4dSAndroid Build Coastguard Worker This program is distributed in the hope that it will be useful,
81*a67afe4dSAndroid Build Coastguard Worker but WITHOUT ANY WARRANTY; without even the implied warranty of
82*a67afe4dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83*a67afe4dSAndroid Build Coastguard Worker GNU General Public License for more details.
84*a67afe4dSAndroid Build Coastguard Worker
85*a67afe4dSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
86*a67afe4dSAndroid Build Coastguard Worker along with this program; if not, write to the Free Software Foundation,
87*a67afe4dSAndroid Build Coastguard Worker Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
88*a67afe4dSAndroid Build Coastguard Worker
89*a67afe4dSAndroid Build Coastguard Worker ---------------------------------------------------------------------------*/
90*a67afe4dSAndroid Build Coastguard Worker
91*a67afe4dSAndroid Build Coastguard Worker #define PROGNAME "wpng"
92*a67afe4dSAndroid Build Coastguard Worker #define VERSION "2.00 of 2 June 2007"
93*a67afe4dSAndroid Build Coastguard Worker #define APPNAME "Simple PGM/PPM/PAM to PNG Converter"
94*a67afe4dSAndroid Build Coastguard Worker
95*a67afe4dSAndroid Build Coastguard Worker #if defined(__MSDOS__) || defined(__OS2__)
96*a67afe4dSAndroid Build Coastguard Worker # define DOS_OS2_W32
97*a67afe4dSAndroid Build Coastguard Worker #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
98*a67afe4dSAndroid Build Coastguard Worker # ifndef __GNUC__ /* treat Win32 native ports of gcc as Unix environments */
99*a67afe4dSAndroid Build Coastguard Worker # define DOS_OS2_W32
100*a67afe4dSAndroid Build Coastguard Worker # endif
101*a67afe4dSAndroid Build Coastguard Worker #endif
102*a67afe4dSAndroid Build Coastguard Worker
103*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
104*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
105*a67afe4dSAndroid Build Coastguard Worker #include <string.h>
106*a67afe4dSAndroid Build Coastguard Worker #include <setjmp.h> /* for jmpbuf declaration in writepng.h */
107*a67afe4dSAndroid Build Coastguard Worker #include <time.h>
108*a67afe4dSAndroid Build Coastguard Worker
109*a67afe4dSAndroid Build Coastguard Worker #ifdef DOS_OS2_W32
110*a67afe4dSAndroid Build Coastguard Worker # include <io.h> /* for isatty(), setmode() prototypes */
111*a67afe4dSAndroid Build Coastguard Worker # include <fcntl.h> /* O_BINARY for fdopen() without text translation */
112*a67afe4dSAndroid Build Coastguard Worker # ifdef __EMX__
113*a67afe4dSAndroid Build Coastguard Worker # ifndef getch
114*a67afe4dSAndroid Build Coastguard Worker # define getch() _read_kbd(0, 1, 0) /* need getche() */
115*a67afe4dSAndroid Build Coastguard Worker # endif
116*a67afe4dSAndroid Build Coastguard Worker # else /* !__EMX__ */
117*a67afe4dSAndroid Build Coastguard Worker # ifdef __GO32__
118*a67afe4dSAndroid Build Coastguard Worker # include <pc.h>
119*a67afe4dSAndroid Build Coastguard Worker # define getch() getkey() /* GRR: need getche() */
120*a67afe4dSAndroid Build Coastguard Worker # else
121*a67afe4dSAndroid Build Coastguard Worker # include <conio.h> /* for getche() console input */
122*a67afe4dSAndroid Build Coastguard Worker # endif
123*a67afe4dSAndroid Build Coastguard Worker # endif /* ?__EMX__ */
124*a67afe4dSAndroid Build Coastguard Worker # define FGETS(buf,len,stream) dos_kbd_gets(buf,len)
125*a67afe4dSAndroid Build Coastguard Worker #else
126*a67afe4dSAndroid Build Coastguard Worker # include <unistd.h> /* for isatty() prototype */
127*a67afe4dSAndroid Build Coastguard Worker # define FGETS fgets
128*a67afe4dSAndroid Build Coastguard Worker #endif
129*a67afe4dSAndroid Build Coastguard Worker
130*a67afe4dSAndroid Build Coastguard Worker /* #define DEBUG : this enables the Trace() macros */
131*a67afe4dSAndroid Build Coastguard Worker
132*a67afe4dSAndroid Build Coastguard Worker /* #define FORBID_LATIN1_CTRL : this requires the user to re-enter any
133*a67afe4dSAndroid Build Coastguard Worker text that includes control characters discouraged by the PNG spec; text
134*a67afe4dSAndroid Build Coastguard Worker that includes an escape character (27) must be re-entered regardless */
135*a67afe4dSAndroid Build Coastguard Worker
136*a67afe4dSAndroid Build Coastguard Worker #include "writepng.h" /* typedefs, common macros, writepng prototypes */
137*a67afe4dSAndroid Build Coastguard Worker
138*a67afe4dSAndroid Build Coastguard Worker
139*a67afe4dSAndroid Build Coastguard Worker
140*a67afe4dSAndroid Build Coastguard Worker /* local prototypes */
141*a67afe4dSAndroid Build Coastguard Worker
142*a67afe4dSAndroid Build Coastguard Worker static int wpng_isvalid_latin1(uch *p, int len);
143*a67afe4dSAndroid Build Coastguard Worker static void wpng_cleanup(void);
144*a67afe4dSAndroid Build Coastguard Worker
145*a67afe4dSAndroid Build Coastguard Worker #ifdef DOS_OS2_W32
146*a67afe4dSAndroid Build Coastguard Worker static char *dos_kbd_gets(char *buf, int len);
147*a67afe4dSAndroid Build Coastguard Worker #endif
148*a67afe4dSAndroid Build Coastguard Worker
149*a67afe4dSAndroid Build Coastguard Worker
150*a67afe4dSAndroid Build Coastguard Worker
151*a67afe4dSAndroid Build Coastguard Worker static mainprog_info wpng_info; /* lone global */
152*a67afe4dSAndroid Build Coastguard Worker
153*a67afe4dSAndroid Build Coastguard Worker
154*a67afe4dSAndroid Build Coastguard Worker
main(int argc,char ** argv)155*a67afe4dSAndroid Build Coastguard Worker int main(int argc, char **argv)
156*a67afe4dSAndroid Build Coastguard Worker {
157*a67afe4dSAndroid Build Coastguard Worker #ifndef DOS_OS2_W32
158*a67afe4dSAndroid Build Coastguard Worker FILE *keybd;
159*a67afe4dSAndroid Build Coastguard Worker #endif
160*a67afe4dSAndroid Build Coastguard Worker #ifdef sgi
161*a67afe4dSAndroid Build Coastguard Worker FILE *tmpfile; /* or we could just use keybd, since no overlap */
162*a67afe4dSAndroid Build Coastguard Worker char tmpline[80];
163*a67afe4dSAndroid Build Coastguard Worker #endif
164*a67afe4dSAndroid Build Coastguard Worker char *inname = NULL, outname[256];
165*a67afe4dSAndroid Build Coastguard Worker char *p, pnmchar, pnmline[256];
166*a67afe4dSAndroid Build Coastguard Worker char *bgstr, *textbuf = NULL;
167*a67afe4dSAndroid Build Coastguard Worker ulg rowbytes;
168*a67afe4dSAndroid Build Coastguard Worker int rc, len = 0;
169*a67afe4dSAndroid Build Coastguard Worker int error = 0;
170*a67afe4dSAndroid Build Coastguard Worker int text = FALSE;
171*a67afe4dSAndroid Build Coastguard Worker int maxval;
172*a67afe4dSAndroid Build Coastguard Worker double LUT_exponent; /* just the lookup table */
173*a67afe4dSAndroid Build Coastguard Worker double CRT_exponent = 2.2; /* just the monitor */
174*a67afe4dSAndroid Build Coastguard Worker double default_display_exponent; /* whole display system */
175*a67afe4dSAndroid Build Coastguard Worker double default_gamma = 0.0;
176*a67afe4dSAndroid Build Coastguard Worker
177*a67afe4dSAndroid Build Coastguard Worker
178*a67afe4dSAndroid Build Coastguard Worker wpng_info.infile = NULL;
179*a67afe4dSAndroid Build Coastguard Worker wpng_info.outfile = NULL;
180*a67afe4dSAndroid Build Coastguard Worker wpng_info.image_data = NULL;
181*a67afe4dSAndroid Build Coastguard Worker wpng_info.row_pointers = NULL;
182*a67afe4dSAndroid Build Coastguard Worker wpng_info.filter = FALSE;
183*a67afe4dSAndroid Build Coastguard Worker wpng_info.interlaced = FALSE;
184*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_bg = FALSE;
185*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_time = FALSE;
186*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text = 0;
187*a67afe4dSAndroid Build Coastguard Worker wpng_info.gamma = 0.0;
188*a67afe4dSAndroid Build Coastguard Worker
189*a67afe4dSAndroid Build Coastguard Worker
190*a67afe4dSAndroid Build Coastguard Worker /* First get the default value for our display-system exponent, i.e.,
191*a67afe4dSAndroid Build Coastguard Worker * the product of the CRT exponent and the exponent corresponding to
192*a67afe4dSAndroid Build Coastguard Worker * the frame-buffer's lookup table (LUT), if any. If the PNM image
193*a67afe4dSAndroid Build Coastguard Worker * looks correct on the user's display system, its file gamma is the
194*a67afe4dSAndroid Build Coastguard Worker * inverse of this value. (Note that this is not an exhaustive list
195*a67afe4dSAndroid Build Coastguard Worker * of LUT values--e.g., OpenStep has a lot of weird ones--but it should
196*a67afe4dSAndroid Build Coastguard Worker * cover 99% of the current possibilities. This section must ensure
197*a67afe4dSAndroid Build Coastguard Worker * that default_display_exponent is positive.) */
198*a67afe4dSAndroid Build Coastguard Worker
199*a67afe4dSAndroid Build Coastguard Worker #if defined(NeXT)
200*a67afe4dSAndroid Build Coastguard Worker /* third-party utilities can modify the default LUT exponent */
201*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.0 / 2.2;
202*a67afe4dSAndroid Build Coastguard Worker /*
203*a67afe4dSAndroid Build Coastguard Worker if (some_next_function_that_returns_gamma(&next_gamma))
204*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.0 / next_gamma;
205*a67afe4dSAndroid Build Coastguard Worker */
206*a67afe4dSAndroid Build Coastguard Worker #elif defined(sgi)
207*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.0 / 1.7;
208*a67afe4dSAndroid Build Coastguard Worker /* there doesn't seem to be any documented function to
209*a67afe4dSAndroid Build Coastguard Worker * get the "gamma" value, so we do it the hard way */
210*a67afe4dSAndroid Build Coastguard Worker tmpfile = fopen("/etc/config/system.glGammaVal", "r");
211*a67afe4dSAndroid Build Coastguard Worker if (tmpfile) {
212*a67afe4dSAndroid Build Coastguard Worker double sgi_gamma;
213*a67afe4dSAndroid Build Coastguard Worker
214*a67afe4dSAndroid Build Coastguard Worker fgets(tmpline, 80, tmpfile);
215*a67afe4dSAndroid Build Coastguard Worker fclose(tmpfile);
216*a67afe4dSAndroid Build Coastguard Worker sgi_gamma = atof(tmpline);
217*a67afe4dSAndroid Build Coastguard Worker if (sgi_gamma > 0.0)
218*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.0 / sgi_gamma;
219*a67afe4dSAndroid Build Coastguard Worker }
220*a67afe4dSAndroid Build Coastguard Worker #elif defined(Macintosh)
221*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.8 / 2.61;
222*a67afe4dSAndroid Build Coastguard Worker /*
223*a67afe4dSAndroid Build Coastguard Worker if (some_mac_function_that_returns_gamma(&mac_gamma))
224*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = mac_gamma / 2.61;
225*a67afe4dSAndroid Build Coastguard Worker */
226*a67afe4dSAndroid Build Coastguard Worker #else
227*a67afe4dSAndroid Build Coastguard Worker LUT_exponent = 1.0; /* assume no LUT: most PCs */
228*a67afe4dSAndroid Build Coastguard Worker #endif
229*a67afe4dSAndroid Build Coastguard Worker
230*a67afe4dSAndroid Build Coastguard Worker /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
231*a67afe4dSAndroid Build Coastguard Worker default_display_exponent = LUT_exponent * CRT_exponent;
232*a67afe4dSAndroid Build Coastguard Worker
233*a67afe4dSAndroid Build Coastguard Worker
234*a67afe4dSAndroid Build Coastguard Worker /* If the user has set the SCREEN_GAMMA environment variable as suggested
235*a67afe4dSAndroid Build Coastguard Worker * (somewhat imprecisely) in the libpng documentation, use that; otherwise
236*a67afe4dSAndroid Build Coastguard Worker * use the default value we just calculated. Either way, the user may
237*a67afe4dSAndroid Build Coastguard Worker * override this via a command-line option. */
238*a67afe4dSAndroid Build Coastguard Worker
239*a67afe4dSAndroid Build Coastguard Worker if ((p = getenv("SCREEN_GAMMA")) != NULL) {
240*a67afe4dSAndroid Build Coastguard Worker double exponent = atof(p);
241*a67afe4dSAndroid Build Coastguard Worker
242*a67afe4dSAndroid Build Coastguard Worker if (exponent > 0.0)
243*a67afe4dSAndroid Build Coastguard Worker default_gamma = 1.0 / exponent;
244*a67afe4dSAndroid Build Coastguard Worker }
245*a67afe4dSAndroid Build Coastguard Worker
246*a67afe4dSAndroid Build Coastguard Worker if (default_gamma == 0.0)
247*a67afe4dSAndroid Build Coastguard Worker default_gamma = 1.0 / default_display_exponent;
248*a67afe4dSAndroid Build Coastguard Worker
249*a67afe4dSAndroid Build Coastguard Worker
250*a67afe4dSAndroid Build Coastguard Worker /* Now parse the command line for options and the PNM filename. */
251*a67afe4dSAndroid Build Coastguard Worker
252*a67afe4dSAndroid Build Coastguard Worker while (*++argv && !error) {
253*a67afe4dSAndroid Build Coastguard Worker if (!strncmp(*argv, "-i", 2)) {
254*a67afe4dSAndroid Build Coastguard Worker wpng_info.interlaced = TRUE;
255*a67afe4dSAndroid Build Coastguard Worker } else if (!strncmp(*argv, "-time", 3)) {
256*a67afe4dSAndroid Build Coastguard Worker wpng_info.modtime = time(NULL);
257*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_time = TRUE;
258*a67afe4dSAndroid Build Coastguard Worker } else if (!strncmp(*argv, "-text", 3)) {
259*a67afe4dSAndroid Build Coastguard Worker text = TRUE;
260*a67afe4dSAndroid Build Coastguard Worker } else if (!strncmp(*argv, "-gamma", 2)) {
261*a67afe4dSAndroid Build Coastguard Worker if (!*++argv)
262*a67afe4dSAndroid Build Coastguard Worker ++error;
263*a67afe4dSAndroid Build Coastguard Worker else {
264*a67afe4dSAndroid Build Coastguard Worker wpng_info.gamma = atof(*argv);
265*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.gamma <= 0.0)
266*a67afe4dSAndroid Build Coastguard Worker ++error;
267*a67afe4dSAndroid Build Coastguard Worker else if (wpng_info.gamma > 1.01)
268*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
269*a67afe4dSAndroid Build Coastguard Worker " warning: file gammas are usually less than 1.0\n");
270*a67afe4dSAndroid Build Coastguard Worker }
271*a67afe4dSAndroid Build Coastguard Worker } else if (!strncmp(*argv, "-bgcolor", 4)) {
272*a67afe4dSAndroid Build Coastguard Worker if (!*++argv)
273*a67afe4dSAndroid Build Coastguard Worker ++error;
274*a67afe4dSAndroid Build Coastguard Worker else {
275*a67afe4dSAndroid Build Coastguard Worker bgstr = *argv;
276*a67afe4dSAndroid Build Coastguard Worker if (strlen(bgstr) != 7 || bgstr[0] != '#')
277*a67afe4dSAndroid Build Coastguard Worker ++error;
278*a67afe4dSAndroid Build Coastguard Worker else {
279*a67afe4dSAndroid Build Coastguard Worker unsigned r, g, b; /* this way quiets compiler warnings */
280*a67afe4dSAndroid Build Coastguard Worker
281*a67afe4dSAndroid Build Coastguard Worker sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
282*a67afe4dSAndroid Build Coastguard Worker wpng_info.bg_red = (uch)r;
283*a67afe4dSAndroid Build Coastguard Worker wpng_info.bg_green = (uch)g;
284*a67afe4dSAndroid Build Coastguard Worker wpng_info.bg_blue = (uch)b;
285*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_bg = TRUE;
286*a67afe4dSAndroid Build Coastguard Worker }
287*a67afe4dSAndroid Build Coastguard Worker }
288*a67afe4dSAndroid Build Coastguard Worker } else {
289*a67afe4dSAndroid Build Coastguard Worker if (**argv != '-') {
290*a67afe4dSAndroid Build Coastguard Worker inname = *argv;
291*a67afe4dSAndroid Build Coastguard Worker if (argv[1]) /* shouldn't be any more args after filename */
292*a67afe4dSAndroid Build Coastguard Worker ++error;
293*a67afe4dSAndroid Build Coastguard Worker } else
294*a67afe4dSAndroid Build Coastguard Worker ++error; /* not expecting any other options */
295*a67afe4dSAndroid Build Coastguard Worker }
296*a67afe4dSAndroid Build Coastguard Worker }
297*a67afe4dSAndroid Build Coastguard Worker
298*a67afe4dSAndroid Build Coastguard Worker
299*a67afe4dSAndroid Build Coastguard Worker /* open the input and output files, or register an error and abort */
300*a67afe4dSAndroid Build Coastguard Worker
301*a67afe4dSAndroid Build Coastguard Worker if (!inname) {
302*a67afe4dSAndroid Build Coastguard Worker if (isatty(0)) {
303*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
304*a67afe4dSAndroid Build Coastguard Worker ": must give input filename or provide image data via stdin\n");
305*a67afe4dSAndroid Build Coastguard Worker ++error;
306*a67afe4dSAndroid Build Coastguard Worker } else {
307*a67afe4dSAndroid Build Coastguard Worker #ifdef DOS_OS2_W32
308*a67afe4dSAndroid Build Coastguard Worker /* some buggy C libraries require BOTH setmode() and fdopen(bin) */
309*a67afe4dSAndroid Build Coastguard Worker setmode(fileno(stdin), O_BINARY);
310*a67afe4dSAndroid Build Coastguard Worker setmode(fileno(stdout), O_BINARY);
311*a67afe4dSAndroid Build Coastguard Worker #endif
312*a67afe4dSAndroid Build Coastguard Worker if ((wpng_info.infile = fdopen(fileno(stdin), "rb")) == NULL) {
313*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
314*a67afe4dSAndroid Build Coastguard Worker ": unable to reopen stdin in binary mode\n");
315*a67afe4dSAndroid Build Coastguard Worker ++error;
316*a67afe4dSAndroid Build Coastguard Worker } else
317*a67afe4dSAndroid Build Coastguard Worker if ((wpng_info.outfile = fdopen(fileno(stdout), "wb")) == NULL) {
318*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
319*a67afe4dSAndroid Build Coastguard Worker ": unable to reopen stdout in binary mode\n");
320*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.infile);
321*a67afe4dSAndroid Build Coastguard Worker ++error;
322*a67afe4dSAndroid Build Coastguard Worker } else
323*a67afe4dSAndroid Build Coastguard Worker wpng_info.filter = TRUE;
324*a67afe4dSAndroid Build Coastguard Worker }
325*a67afe4dSAndroid Build Coastguard Worker } else if ((len = strlen(inname)) > 250) {
326*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": input filename is too long [%d chars]\n",
327*a67afe4dSAndroid Build Coastguard Worker len);
328*a67afe4dSAndroid Build Coastguard Worker ++error;
329*a67afe4dSAndroid Build Coastguard Worker } else if (!(wpng_info.infile = fopen(inname, "rb"))) {
330*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": can't open input file [%s]\n", inname);
331*a67afe4dSAndroid Build Coastguard Worker ++error;
332*a67afe4dSAndroid Build Coastguard Worker }
333*a67afe4dSAndroid Build Coastguard Worker
334*a67afe4dSAndroid Build Coastguard Worker if (!error) {
335*a67afe4dSAndroid Build Coastguard Worker fgets(pnmline, 256, wpng_info.infile);
336*a67afe4dSAndroid Build Coastguard Worker if (pnmline[0] != 'P' || ((pnmchar = pnmline[1]) != '5' &&
337*a67afe4dSAndroid Build Coastguard Worker pnmchar != '6' && pnmchar != '8'))
338*a67afe4dSAndroid Build Coastguard Worker {
339*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
340*a67afe4dSAndroid Build Coastguard Worker ": input file [%s] is not a binary PGM, PPM or PAM file\n",
341*a67afe4dSAndroid Build Coastguard Worker inname);
342*a67afe4dSAndroid Build Coastguard Worker ++error;
343*a67afe4dSAndroid Build Coastguard Worker } else {
344*a67afe4dSAndroid Build Coastguard Worker wpng_info.pnmtype = (int)(pnmchar - '0');
345*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.pnmtype != 8)
346*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_bg = FALSE; /* no need for bg if opaque */
347*a67afe4dSAndroid Build Coastguard Worker do {
348*a67afe4dSAndroid Build Coastguard Worker fgets(pnmline, 256, wpng_info.infile); /* lose any comments */
349*a67afe4dSAndroid Build Coastguard Worker } while (pnmline[0] == '#');
350*a67afe4dSAndroid Build Coastguard Worker sscanf(pnmline, "%ld %ld", &wpng_info.width, &wpng_info.height);
351*a67afe4dSAndroid Build Coastguard Worker do {
352*a67afe4dSAndroid Build Coastguard Worker fgets(pnmline, 256, wpng_info.infile); /* more comment lines */
353*a67afe4dSAndroid Build Coastguard Worker } while (pnmline[0] == '#');
354*a67afe4dSAndroid Build Coastguard Worker sscanf(pnmline, "%d", &maxval);
355*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.width <= 0L || wpng_info.height <= 0L ||
356*a67afe4dSAndroid Build Coastguard Worker maxval != 255)
357*a67afe4dSAndroid Build Coastguard Worker {
358*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
359*a67afe4dSAndroid Build Coastguard Worker ": only positive width/height, maxval == 255 allowed \n");
360*a67afe4dSAndroid Build Coastguard Worker ++error;
361*a67afe4dSAndroid Build Coastguard Worker }
362*a67afe4dSAndroid Build Coastguard Worker wpng_info.sample_depth = 8; /* <==> maxval 255 */
363*a67afe4dSAndroid Build Coastguard Worker
364*a67afe4dSAndroid Build Coastguard Worker if (!wpng_info.filter) {
365*a67afe4dSAndroid Build Coastguard Worker /* make outname from inname */
366*a67afe4dSAndroid Build Coastguard Worker if ((p = strrchr(inname, '.')) == NULL ||
367*a67afe4dSAndroid Build Coastguard Worker (p - inname) != (len - 4))
368*a67afe4dSAndroid Build Coastguard Worker {
369*a67afe4dSAndroid Build Coastguard Worker strcpy(outname, inname);
370*a67afe4dSAndroid Build Coastguard Worker strcpy(outname+len, ".png");
371*a67afe4dSAndroid Build Coastguard Worker } else {
372*a67afe4dSAndroid Build Coastguard Worker len -= 4;
373*a67afe4dSAndroid Build Coastguard Worker strncpy(outname, inname, len);
374*a67afe4dSAndroid Build Coastguard Worker strcpy(outname+len, ".png");
375*a67afe4dSAndroid Build Coastguard Worker }
376*a67afe4dSAndroid Build Coastguard Worker /* check if outname already exists; if not, open */
377*a67afe4dSAndroid Build Coastguard Worker if ((wpng_info.outfile = fopen(outname, "rb")) != NULL) {
378*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": output file exists [%s]\n",
379*a67afe4dSAndroid Build Coastguard Worker outname);
380*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.outfile);
381*a67afe4dSAndroid Build Coastguard Worker ++error;
382*a67afe4dSAndroid Build Coastguard Worker } else if (!(wpng_info.outfile = fopen(outname, "wb"))) {
383*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": can't open output file [%s]\n",
384*a67afe4dSAndroid Build Coastguard Worker outname);
385*a67afe4dSAndroid Build Coastguard Worker ++error;
386*a67afe4dSAndroid Build Coastguard Worker }
387*a67afe4dSAndroid Build Coastguard Worker }
388*a67afe4dSAndroid Build Coastguard Worker }
389*a67afe4dSAndroid Build Coastguard Worker if (error) {
390*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.infile);
391*a67afe4dSAndroid Build Coastguard Worker wpng_info.infile = NULL;
392*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.filter) {
393*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.outfile);
394*a67afe4dSAndroid Build Coastguard Worker wpng_info.outfile = NULL;
395*a67afe4dSAndroid Build Coastguard Worker }
396*a67afe4dSAndroid Build Coastguard Worker }
397*a67afe4dSAndroid Build Coastguard Worker }
398*a67afe4dSAndroid Build Coastguard Worker
399*a67afe4dSAndroid Build Coastguard Worker
400*a67afe4dSAndroid Build Coastguard Worker /* if we had any errors, print usage and die horrible death...arrr! */
401*a67afe4dSAndroid Build Coastguard Worker
402*a67afe4dSAndroid Build Coastguard Worker if (error) {
403*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, APPNAME);
404*a67afe4dSAndroid Build Coastguard Worker writepng_version_info();
405*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "\n"
406*a67afe4dSAndroid Build Coastguard Worker "Usage: %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] pnmfile\n"
407*a67afe4dSAndroid Build Coastguard Worker "or: ... | %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] | ...\n"
408*a67afe4dSAndroid Build Coastguard Worker " exp \ttransfer-function exponent (``gamma'') of the image in\n"
409*a67afe4dSAndroid Build Coastguard Worker "\t\t floating-point format (e.g., ``%.5f''); if image looks\n"
410*a67afe4dSAndroid Build Coastguard Worker "\t\t correct on given display system, image gamma is equal to\n"
411*a67afe4dSAndroid Build Coastguard Worker "\t\t inverse of display-system exponent, i.e., 1 / (LUT * CRT)\n"
412*a67afe4dSAndroid Build Coastguard Worker "\t\t (where LUT = lookup-table exponent and CRT = CRT exponent;\n"
413*a67afe4dSAndroid Build Coastguard Worker "\t\t first varies, second is usually 2.2, all are positive)\n"
414*a67afe4dSAndroid Build Coastguard Worker " bg \tdesired background color for alpha-channel images, in\n"
415*a67afe4dSAndroid Build Coastguard Worker "\t\t 7-character hex RGB format (e.g., ``#ff7700'' for orange:\n"
416*a67afe4dSAndroid Build Coastguard Worker "\t\t same as HTML colors)\n"
417*a67afe4dSAndroid Build Coastguard Worker " -text\tprompt interactively for text info (tEXt chunks)\n"
418*a67afe4dSAndroid Build Coastguard Worker " -time\tinclude a tIME chunk (last modification time)\n"
419*a67afe4dSAndroid Build Coastguard Worker " -interlace\twrite interlaced PNG image\n"
420*a67afe4dSAndroid Build Coastguard Worker "\n"
421*a67afe4dSAndroid Build Coastguard Worker "pnmfile or stdin must be a binary PGM (`P5'), PPM (`P6') or (extremely\n"
422*a67afe4dSAndroid Build Coastguard Worker "unofficial and unsupported!) PAM (`P8') file. Currently it is required\n"
423*a67afe4dSAndroid Build Coastguard Worker "to have maxval == 255 (i.e., no scaling). If pnmfile is specified, it\n"
424*a67afe4dSAndroid Build Coastguard Worker "is converted to the corresponding PNG file with the same base name but a\n"
425*a67afe4dSAndroid Build Coastguard Worker "``.png'' extension; files read from stdin are converted and sent to stdout.\n"
426*a67afe4dSAndroid Build Coastguard Worker "The conversion is progressive (low memory usage) unless interlacing is\n"
427*a67afe4dSAndroid Build Coastguard Worker "requested; in that case the whole image will be buffered in memory and\n"
428*a67afe4dSAndroid Build Coastguard Worker "written in one call.\n"
429*a67afe4dSAndroid Build Coastguard Worker "\n", PROGNAME, PROGNAME, default_gamma);
430*a67afe4dSAndroid Build Coastguard Worker exit(1);
431*a67afe4dSAndroid Build Coastguard Worker }
432*a67afe4dSAndroid Build Coastguard Worker
433*a67afe4dSAndroid Build Coastguard Worker
434*a67afe4dSAndroid Build Coastguard Worker /* prepare the text buffers for libpng's use; note that even though
435*a67afe4dSAndroid Build Coastguard Worker * PNG's png_text struct includes a length field, we don't have to fill
436*a67afe4dSAndroid Build Coastguard Worker * it out */
437*a67afe4dSAndroid Build Coastguard Worker
438*a67afe4dSAndroid Build Coastguard Worker if (text &&
439*a67afe4dSAndroid Build Coastguard Worker #ifndef DOS_OS2_W32
440*a67afe4dSAndroid Build Coastguard Worker (keybd = fdopen(fileno(stderr), "r")) != NULL &&
441*a67afe4dSAndroid Build Coastguard Worker #endif
442*a67afe4dSAndroid Build Coastguard Worker (textbuf = (char *)malloc((5 + 9)*75)) != NULL)
443*a67afe4dSAndroid Build Coastguard Worker {
444*a67afe4dSAndroid Build Coastguard Worker int i, valid, result;
445*a67afe4dSAndroid Build Coastguard Worker
446*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr,
447*a67afe4dSAndroid Build Coastguard Worker "Enter text info (no more than 72 characters per line);\n");
448*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "to skip a field, hit the <Enter> key.\n");
449*a67afe4dSAndroid Build Coastguard Worker /* note: just <Enter> leaves len == 1 */
450*a67afe4dSAndroid Build Coastguard Worker
451*a67afe4dSAndroid Build Coastguard Worker do {
452*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
453*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_TITLE_OFFSET;
454*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " Title: ");
455*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
456*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
457*a67afe4dSAndroid Build Coastguard Worker if (p[len-1] == '\n')
458*a67afe4dSAndroid Build Coastguard Worker p[--len] = '\0';
459*a67afe4dSAndroid Build Coastguard Worker wpng_info.title = p;
460*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_TITLE;
461*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
462*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
463*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
464*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
465*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
466*a67afe4dSAndroid Build Coastguard Worker result+1);
467*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
468*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
469*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_TITLE;
470*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
471*a67afe4dSAndroid Build Coastguard Worker #else
472*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
473*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_TITLE;
474*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
475*a67afe4dSAndroid Build Coastguard Worker }
476*a67afe4dSAndroid Build Coastguard Worker #endif
477*a67afe4dSAndroid Build Coastguard Worker }
478*a67afe4dSAndroid Build Coastguard Worker }
479*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
480*a67afe4dSAndroid Build Coastguard Worker
481*a67afe4dSAndroid Build Coastguard Worker do {
482*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
483*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_AUTHOR_OFFSET;
484*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " Author: ");
485*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
486*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
487*a67afe4dSAndroid Build Coastguard Worker if (p[len-1] == '\n')
488*a67afe4dSAndroid Build Coastguard Worker p[--len] = '\0';
489*a67afe4dSAndroid Build Coastguard Worker wpng_info.author = p;
490*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_AUTHOR;
491*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
492*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
493*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
494*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
495*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
496*a67afe4dSAndroid Build Coastguard Worker result+1);
497*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
498*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
499*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_AUTHOR;
500*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
501*a67afe4dSAndroid Build Coastguard Worker #else
502*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
503*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_AUTHOR;
504*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
505*a67afe4dSAndroid Build Coastguard Worker }
506*a67afe4dSAndroid Build Coastguard Worker #endif
507*a67afe4dSAndroid Build Coastguard Worker }
508*a67afe4dSAndroid Build Coastguard Worker }
509*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
510*a67afe4dSAndroid Build Coastguard Worker
511*a67afe4dSAndroid Build Coastguard Worker do {
512*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
513*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_DESC_OFFSET;
514*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " Description (up to 9 lines):\n");
515*a67afe4dSAndroid Build Coastguard Worker for (i = 1; i < 10; ++i) {
516*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " [%d] ", i);
517*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
518*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1)
519*a67afe4dSAndroid Build Coastguard Worker p += len; /* now points at NULL; char before is newline */
520*a67afe4dSAndroid Build Coastguard Worker else
521*a67afe4dSAndroid Build Coastguard Worker break;
522*a67afe4dSAndroid Build Coastguard Worker }
523*a67afe4dSAndroid Build Coastguard Worker if ((len = p - (textbuf + TEXT_DESC_OFFSET)) > 1) {
524*a67afe4dSAndroid Build Coastguard Worker if (p[-1] == '\n') {
525*a67afe4dSAndroid Build Coastguard Worker p[-1] = '\0';
526*a67afe4dSAndroid Build Coastguard Worker --len;
527*a67afe4dSAndroid Build Coastguard Worker }
528*a67afe4dSAndroid Build Coastguard Worker wpng_info.desc = textbuf + TEXT_DESC_OFFSET;
529*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_DESC;
530*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_DESC_OFFSET;
531*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
532*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
533*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
534*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
535*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
536*a67afe4dSAndroid Build Coastguard Worker result+1);
537*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
538*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
539*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_DESC;
540*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
541*a67afe4dSAndroid Build Coastguard Worker #else
542*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
543*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_DESC;
544*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
545*a67afe4dSAndroid Build Coastguard Worker }
546*a67afe4dSAndroid Build Coastguard Worker #endif
547*a67afe4dSAndroid Build Coastguard Worker }
548*a67afe4dSAndroid Build Coastguard Worker }
549*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
550*a67afe4dSAndroid Build Coastguard Worker
551*a67afe4dSAndroid Build Coastguard Worker do {
552*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
553*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_COPY_OFFSET;
554*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " Copyright: ");
555*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
556*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
557*a67afe4dSAndroid Build Coastguard Worker if (p[len-1] == '\n')
558*a67afe4dSAndroid Build Coastguard Worker p[--len] = '\0';
559*a67afe4dSAndroid Build Coastguard Worker wpng_info.copyright = p;
560*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_COPY;
561*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
562*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
563*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
564*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
565*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
566*a67afe4dSAndroid Build Coastguard Worker result+1);
567*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
568*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
569*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_COPY;
570*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
571*a67afe4dSAndroid Build Coastguard Worker #else
572*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
573*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_COPY;
574*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
575*a67afe4dSAndroid Build Coastguard Worker }
576*a67afe4dSAndroid Build Coastguard Worker #endif
577*a67afe4dSAndroid Build Coastguard Worker }
578*a67afe4dSAndroid Build Coastguard Worker }
579*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
580*a67afe4dSAndroid Build Coastguard Worker
581*a67afe4dSAndroid Build Coastguard Worker do {
582*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
583*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_EMAIL_OFFSET;
584*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " E-mail: ");
585*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
586*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
587*a67afe4dSAndroid Build Coastguard Worker if (p[len-1] == '\n')
588*a67afe4dSAndroid Build Coastguard Worker p[--len] = '\0';
589*a67afe4dSAndroid Build Coastguard Worker wpng_info.email = p;
590*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_EMAIL;
591*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
592*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
593*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
594*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
595*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
596*a67afe4dSAndroid Build Coastguard Worker result+1);
597*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
598*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
599*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_EMAIL;
600*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
601*a67afe4dSAndroid Build Coastguard Worker #else
602*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
603*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_EMAIL;
604*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
605*a67afe4dSAndroid Build Coastguard Worker }
606*a67afe4dSAndroid Build Coastguard Worker #endif
607*a67afe4dSAndroid Build Coastguard Worker }
608*a67afe4dSAndroid Build Coastguard Worker }
609*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
610*a67afe4dSAndroid Build Coastguard Worker
611*a67afe4dSAndroid Build Coastguard Worker do {
612*a67afe4dSAndroid Build Coastguard Worker valid = TRUE;
613*a67afe4dSAndroid Build Coastguard Worker p = textbuf + TEXT_URL_OFFSET;
614*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " URL: ");
615*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
616*a67afe4dSAndroid Build Coastguard Worker if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
617*a67afe4dSAndroid Build Coastguard Worker if (p[len-1] == '\n')
618*a67afe4dSAndroid Build Coastguard Worker p[--len] = '\0';
619*a67afe4dSAndroid Build Coastguard Worker wpng_info.url = p;
620*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text |= TEXT_URL;
621*a67afe4dSAndroid Build Coastguard Worker if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
622*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " " PROGNAME " warning: character code"
623*a67afe4dSAndroid Build Coastguard Worker " %u is %sdiscouraged by the PNG\n specification "
624*a67afe4dSAndroid Build Coastguard Worker "[first occurrence was at character position #%d]\n",
625*a67afe4dSAndroid Build Coastguard Worker (unsigned)p[result], (p[result] == 27)? "strongly " : "",
626*a67afe4dSAndroid Build Coastguard Worker result+1);
627*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
628*a67afe4dSAndroid Build Coastguard Worker #ifdef FORBID_LATIN1_CTRL
629*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_URL;
630*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
631*a67afe4dSAndroid Build Coastguard Worker #else
632*a67afe4dSAndroid Build Coastguard Worker if (p[result] == 27) { /* escape character */
633*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text &= ~TEXT_URL;
634*a67afe4dSAndroid Build Coastguard Worker valid = FALSE;
635*a67afe4dSAndroid Build Coastguard Worker }
636*a67afe4dSAndroid Build Coastguard Worker #endif
637*a67afe4dSAndroid Build Coastguard Worker }
638*a67afe4dSAndroid Build Coastguard Worker }
639*a67afe4dSAndroid Build Coastguard Worker } while (!valid);
640*a67afe4dSAndroid Build Coastguard Worker
641*a67afe4dSAndroid Build Coastguard Worker #ifndef DOS_OS2_W32
642*a67afe4dSAndroid Build Coastguard Worker fclose(keybd);
643*a67afe4dSAndroid Build Coastguard Worker #endif
644*a67afe4dSAndroid Build Coastguard Worker
645*a67afe4dSAndroid Build Coastguard Worker } else if (text) {
646*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": unable to allocate memory for text\n");
647*a67afe4dSAndroid Build Coastguard Worker text = FALSE;
648*a67afe4dSAndroid Build Coastguard Worker wpng_info.have_text = 0;
649*a67afe4dSAndroid Build Coastguard Worker }
650*a67afe4dSAndroid Build Coastguard Worker
651*a67afe4dSAndroid Build Coastguard Worker
652*a67afe4dSAndroid Build Coastguard Worker /* allocate libpng stuff, initialize transformations, write pre-IDAT data */
653*a67afe4dSAndroid Build Coastguard Worker
654*a67afe4dSAndroid Build Coastguard Worker if ((rc = writepng_init(&wpng_info)) != 0) {
655*a67afe4dSAndroid Build Coastguard Worker switch (rc) {
656*a67afe4dSAndroid Build Coastguard Worker case 2:
657*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
658*a67afe4dSAndroid Build Coastguard Worker ": libpng initialization problem (longjmp)\n");
659*a67afe4dSAndroid Build Coastguard Worker break;
660*a67afe4dSAndroid Build Coastguard Worker case 4:
661*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": insufficient memory\n");
662*a67afe4dSAndroid Build Coastguard Worker break;
663*a67afe4dSAndroid Build Coastguard Worker case 11:
664*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
665*a67afe4dSAndroid Build Coastguard Worker ": internal logic error (unexpected PNM type)\n");
666*a67afe4dSAndroid Build Coastguard Worker break;
667*a67afe4dSAndroid Build Coastguard Worker default:
668*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
669*a67afe4dSAndroid Build Coastguard Worker ": unknown writepng_init() error\n");
670*a67afe4dSAndroid Build Coastguard Worker break;
671*a67afe4dSAndroid Build Coastguard Worker }
672*a67afe4dSAndroid Build Coastguard Worker exit(rc);
673*a67afe4dSAndroid Build Coastguard Worker }
674*a67afe4dSAndroid Build Coastguard Worker
675*a67afe4dSAndroid Build Coastguard Worker
676*a67afe4dSAndroid Build Coastguard Worker /* free textbuf, since it's a completely local variable and all text info
677*a67afe4dSAndroid Build Coastguard Worker * has just been written to the PNG file */
678*a67afe4dSAndroid Build Coastguard Worker
679*a67afe4dSAndroid Build Coastguard Worker if (text && textbuf) {
680*a67afe4dSAndroid Build Coastguard Worker free(textbuf);
681*a67afe4dSAndroid Build Coastguard Worker textbuf = NULL;
682*a67afe4dSAndroid Build Coastguard Worker }
683*a67afe4dSAndroid Build Coastguard Worker
684*a67afe4dSAndroid Build Coastguard Worker
685*a67afe4dSAndroid Build Coastguard Worker /* calculate rowbytes on basis of image type; note that this becomes much
686*a67afe4dSAndroid Build Coastguard Worker * more complicated if we choose to support PBM type, ASCII PNM types, or
687*a67afe4dSAndroid Build Coastguard Worker * 16-bit-per-sample binary data [currently not an official NetPBM type] */
688*a67afe4dSAndroid Build Coastguard Worker
689*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.pnmtype == 5)
690*a67afe4dSAndroid Build Coastguard Worker rowbytes = wpng_info.width;
691*a67afe4dSAndroid Build Coastguard Worker else if (wpng_info.pnmtype == 6)
692*a67afe4dSAndroid Build Coastguard Worker rowbytes = wpng_info.width * 3;
693*a67afe4dSAndroid Build Coastguard Worker else /* if (wpng_info.pnmtype == 8) */
694*a67afe4dSAndroid Build Coastguard Worker rowbytes = wpng_info.width * 4;
695*a67afe4dSAndroid Build Coastguard Worker
696*a67afe4dSAndroid Build Coastguard Worker
697*a67afe4dSAndroid Build Coastguard Worker /* read and write the image, either in its entirety (if writing interlaced
698*a67afe4dSAndroid Build Coastguard Worker * PNG) or row by row (if non-interlaced) */
699*a67afe4dSAndroid Build Coastguard Worker
700*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "Encoding image data...\n");
701*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
702*a67afe4dSAndroid Build Coastguard Worker
703*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.interlaced) {
704*a67afe4dSAndroid Build Coastguard Worker long i;
705*a67afe4dSAndroid Build Coastguard Worker ulg bytes;
706*a67afe4dSAndroid Build Coastguard Worker ulg image_bytes;
707*a67afe4dSAndroid Build Coastguard Worker
708*a67afe4dSAndroid Build Coastguard Worker /* Guard against integer overflow */
709*a67afe4dSAndroid Build Coastguard Worker if (wpng_info_height > ((size_t)(-1)/rowbytes ||
710*a67afe4dSAndroid Build Coastguard Worker wpng_info_height > ((ulg)(-1)/rowbytes) {
711*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": image_data buffer too large\n");
712*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
713*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
714*a67afe4dSAndroid Build Coastguard Worker exit(5);
715*a67afe4dSAndroid Build Coastguard Worker }
716*a67afe4dSAndroid Build Coastguard Worker
717*a67afe4dSAndroid Build Coastguard Worker image_bytes = rowbytes * wpng_info.height;
718*a67afe4dSAndroid Build Coastguard Worker
719*a67afe4dSAndroid Build Coastguard Worker wpng_info.image_data = (uch *)malloc(image_bytes);
720*a67afe4dSAndroid Build Coastguard Worker wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *));
721*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.image_data == NULL || wpng_info.row_pointers == NULL) {
722*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": insufficient memory for image data\n");
723*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
724*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
725*a67afe4dSAndroid Build Coastguard Worker exit(5);
726*a67afe4dSAndroid Build Coastguard Worker }
727*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < wpng_info.height; ++i)
728*a67afe4dSAndroid Build Coastguard Worker wpng_info.row_pointers[i] = wpng_info.image_data + i*rowbytes;
729*a67afe4dSAndroid Build Coastguard Worker bytes = fread(wpng_info.image_data, 1, image_bytes, wpng_info.infile);
730*a67afe4dSAndroid Build Coastguard Worker if (bytes != image_bytes) {
731*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": expected %lu bytes, got %lu bytes\n",
732*a67afe4dSAndroid Build Coastguard Worker image_bytes, bytes);
733*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, " (continuing anyway)\n");
734*a67afe4dSAndroid Build Coastguard Worker }
735*a67afe4dSAndroid Build Coastguard Worker if (writepng_encode_image(&wpng_info) != 0) {
736*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
737*a67afe4dSAndroid Build Coastguard Worker ": libpng problem (longjmp) while writing image data\n");
738*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
739*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
740*a67afe4dSAndroid Build Coastguard Worker exit(2);
741*a67afe4dSAndroid Build Coastguard Worker }
742*a67afe4dSAndroid Build Coastguard Worker
743*a67afe4dSAndroid Build Coastguard Worker } else /* not interlaced: write progressively (row by row) */ {
744*a67afe4dSAndroid Build Coastguard Worker long j;
745*a67afe4dSAndroid Build Coastguard Worker ulg bytes;
746*a67afe4dSAndroid Build Coastguard Worker
747*a67afe4dSAndroid Build Coastguard Worker wpng_info.image_data = (uch *)malloc(rowbytes);
748*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.image_data == NULL) {
749*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": insufficient memory for row data\n");
750*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
751*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
752*a67afe4dSAndroid Build Coastguard Worker exit(5);
753*a67afe4dSAndroid Build Coastguard Worker }
754*a67afe4dSAndroid Build Coastguard Worker error = 0;
755*a67afe4dSAndroid Build Coastguard Worker for (j = wpng_info.height; j > 0L; --j) {
756*a67afe4dSAndroid Build Coastguard Worker bytes = fread(wpng_info.image_data, 1, rowbytes, wpng_info.infile);
757*a67afe4dSAndroid Build Coastguard Worker if (bytes != rowbytes) {
758*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
759*a67afe4dSAndroid Build Coastguard Worker ": expected %lu bytes, got %lu bytes (row %ld)\n", rowbytes,
760*a67afe4dSAndroid Build Coastguard Worker bytes, wpng_info.height-j);
761*a67afe4dSAndroid Build Coastguard Worker ++error;
762*a67afe4dSAndroid Build Coastguard Worker break;
763*a67afe4dSAndroid Build Coastguard Worker }
764*a67afe4dSAndroid Build Coastguard Worker if (writepng_encode_row(&wpng_info) != 0) {
765*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME
766*a67afe4dSAndroid Build Coastguard Worker ": libpng problem (longjmp) while writing row %ld\n",
767*a67afe4dSAndroid Build Coastguard Worker wpng_info.height-j);
768*a67afe4dSAndroid Build Coastguard Worker ++error;
769*a67afe4dSAndroid Build Coastguard Worker break;
770*a67afe4dSAndroid Build Coastguard Worker }
771*a67afe4dSAndroid Build Coastguard Worker }
772*a67afe4dSAndroid Build Coastguard Worker if (error) {
773*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
774*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
775*a67afe4dSAndroid Build Coastguard Worker exit(2);
776*a67afe4dSAndroid Build Coastguard Worker }
777*a67afe4dSAndroid Build Coastguard Worker if (writepng_encode_finish(&wpng_info) != 0) {
778*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, PROGNAME ": error on final libpng call\n");
779*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
780*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
781*a67afe4dSAndroid Build Coastguard Worker exit(2);
782*a67afe4dSAndroid Build Coastguard Worker }
783*a67afe4dSAndroid Build Coastguard Worker }
784*a67afe4dSAndroid Build Coastguard Worker
785*a67afe4dSAndroid Build Coastguard Worker
786*a67afe4dSAndroid Build Coastguard Worker /* OK, we're done (successfully): clean up all resources and quit */
787*a67afe4dSAndroid Build Coastguard Worker
788*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "Done.\n");
789*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
790*a67afe4dSAndroid Build Coastguard Worker
791*a67afe4dSAndroid Build Coastguard Worker writepng_cleanup(&wpng_info);
792*a67afe4dSAndroid Build Coastguard Worker wpng_cleanup();
793*a67afe4dSAndroid Build Coastguard Worker
794*a67afe4dSAndroid Build Coastguard Worker return 0;
795*a67afe4dSAndroid Build Coastguard Worker }
796*a67afe4dSAndroid Build Coastguard Worker
797*a67afe4dSAndroid Build Coastguard Worker
798*a67afe4dSAndroid Build Coastguard Worker
799*a67afe4dSAndroid Build Coastguard Worker
800*a67afe4dSAndroid Build Coastguard Worker
801*a67afe4dSAndroid Build Coastguard Worker static int wpng_isvalid_latin1(uch *p, int len)
802*a67afe4dSAndroid Build Coastguard Worker {
803*a67afe4dSAndroid Build Coastguard Worker int i, result = -1;
804*a67afe4dSAndroid Build Coastguard Worker
805*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < len; ++i) {
806*a67afe4dSAndroid Build Coastguard Worker if (p[i] == 10 || (p[i] > 31 && p[i] < 127) || p[i] > 160)
807*a67afe4dSAndroid Build Coastguard Worker continue; /* character is completely OK */
808*a67afe4dSAndroid Build Coastguard Worker if (result < 0 || (p[result] != 27 && p[i] == 27))
809*a67afe4dSAndroid Build Coastguard Worker result = i; /* mark location of first questionable one */
810*a67afe4dSAndroid Build Coastguard Worker } /* or of first escape character (bad) */
811*a67afe4dSAndroid Build Coastguard Worker
812*a67afe4dSAndroid Build Coastguard Worker return result;
813*a67afe4dSAndroid Build Coastguard Worker }
814*a67afe4dSAndroid Build Coastguard Worker
815*a67afe4dSAndroid Build Coastguard Worker
816*a67afe4dSAndroid Build Coastguard Worker
817*a67afe4dSAndroid Build Coastguard Worker
818*a67afe4dSAndroid Build Coastguard Worker
819*a67afe4dSAndroid Build Coastguard Worker static void wpng_cleanup(void)
820*a67afe4dSAndroid Build Coastguard Worker {
821*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.outfile) {
822*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.outfile);
823*a67afe4dSAndroid Build Coastguard Worker wpng_info.outfile = NULL;
824*a67afe4dSAndroid Build Coastguard Worker }
825*a67afe4dSAndroid Build Coastguard Worker
826*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.infile) {
827*a67afe4dSAndroid Build Coastguard Worker fclose(wpng_info.infile);
828*a67afe4dSAndroid Build Coastguard Worker wpng_info.infile = NULL;
829*a67afe4dSAndroid Build Coastguard Worker }
830*a67afe4dSAndroid Build Coastguard Worker
831*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.image_data) {
832*a67afe4dSAndroid Build Coastguard Worker free(wpng_info.image_data);
833*a67afe4dSAndroid Build Coastguard Worker wpng_info.image_data = NULL;
834*a67afe4dSAndroid Build Coastguard Worker }
835*a67afe4dSAndroid Build Coastguard Worker
836*a67afe4dSAndroid Build Coastguard Worker if (wpng_info.row_pointers) {
837*a67afe4dSAndroid Build Coastguard Worker free(wpng_info.row_pointers);
838*a67afe4dSAndroid Build Coastguard Worker wpng_info.row_pointers = NULL;
839*a67afe4dSAndroid Build Coastguard Worker }
840*a67afe4dSAndroid Build Coastguard Worker }
841*a67afe4dSAndroid Build Coastguard Worker
842*a67afe4dSAndroid Build Coastguard Worker
843*a67afe4dSAndroid Build Coastguard Worker
844*a67afe4dSAndroid Build Coastguard Worker
845*a67afe4dSAndroid Build Coastguard Worker #ifdef DOS_OS2_W32
846*a67afe4dSAndroid Build Coastguard Worker
847*a67afe4dSAndroid Build Coastguard Worker static char *dos_kbd_gets(char *buf, int len)
848*a67afe4dSAndroid Build Coastguard Worker {
849*a67afe4dSAndroid Build Coastguard Worker int ch, count=0;
850*a67afe4dSAndroid Build Coastguard Worker
851*a67afe4dSAndroid Build Coastguard Worker do {
852*a67afe4dSAndroid Build Coastguard Worker buf[count++] = ch = getche();
853*a67afe4dSAndroid Build Coastguard Worker } while (ch != '\r' && count < len-1);
854*a67afe4dSAndroid Build Coastguard Worker
855*a67afe4dSAndroid Build Coastguard Worker buf[count--] = '\0'; /* terminate string */
856*a67afe4dSAndroid Build Coastguard Worker if (buf[count] == '\r') /* Enter key makes CR, so change to newline */
857*a67afe4dSAndroid Build Coastguard Worker buf[count] = '\n';
858*a67afe4dSAndroid Build Coastguard Worker
859*a67afe4dSAndroid Build Coastguard Worker fprintf(stderr, "\n"); /* Enter key does *not* cause a newline */
860*a67afe4dSAndroid Build Coastguard Worker fflush(stderr);
861*a67afe4dSAndroid Build Coastguard Worker
862*a67afe4dSAndroid Build Coastguard Worker return buf;
863*a67afe4dSAndroid Build Coastguard Worker }
864*a67afe4dSAndroid Build Coastguard Worker
865*a67afe4dSAndroid Build Coastguard Worker #endif /* DOS_OS2_W32 */
866