xref: /aosp_15_r20/external/libpng/contrib/gregbook/wpng.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
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