1 /* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gp_msio.c,v 1.6 2002/06/16 05:48:55 lpd Exp $ */
18 /*
19 * Streams for Windows text window
20 *
21 * Original version by Russell Lang and Maurice Castro with help from
22 * Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
23 * initially created from gp_dosfb.c and gp_itbc.c 5th June 1992.
24 */
25
26 /* Modified for Win32 & Microsoft C/C++ 8.0 32-Bit, 26.Okt.1994 */
27 /* by Friedrich Nowak */
28
29 /* Factored out from gp_mswin.c by JD 6/25/97 */
30
31 /*
32 * The MSVC compiler, when invoked with the /MD switch, considers that the
33 * dllimport qualifier on fprintf in stdio.h and the dllexport qualifier
34 * on the definition of fprintf in this file are incompatible.
35 * We use a hack (similar to the one in stdpre.h to deal with sys/types.h)
36 * to work around this.
37 */
38 #define fprintf UNDEFINE_fprintf
39 #include "stdio_.h"
40 #undef fprintf
41
42 #include <stdlib.h>
43 #include "gx.h"
44 #include "gp.h"
45 #include "windows_.h"
46 #include <shellapi.h>
47 #ifdef __WIN32__
48 #include <winspool.h>
49 #endif
50 #include "gp_mswin.h"
51 #include "gsdll.h"
52
53 #include "stream.h"
54 #include "gxiodev.h" /* must come after stream.h */
55
56 /* Imported from gp_msdos.c */
57 int gp_file_is_console(FILE *);
58
59
60 /* ====== Substitute for stdio ====== */
61
62 /* Forward references */
63 private void win_std_init(void);
64 private stream_proc_process(win_std_read_process);
65 private stream_proc_process(win_std_write_process);
66 private stream_proc_available(win_std_available);
67
68 /* Use a pseudo IODevice to get win_stdio_init called at the right time. */
69 /* This is bad architecture; we'll fix it later. */
70 private iodev_proc_init(win_stdio_init);
71 const gx_io_device gs_iodev_wstdio = {
72 /* The name is null to keep this from showing up as a resource. */
73 0, "Special",
74 {win_stdio_init, iodev_no_open_device,
75 iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,
76 iodev_no_delete_file, iodev_no_rename_file,
77 iodev_no_file_status, iodev_no_enumerate_files
78 }
79 };
80
81 /* Do one-time initialization */
82 private int
win_stdio_init(gx_io_device * iodev,gs_memory_t * mem)83 win_stdio_init(gx_io_device * iodev, gs_memory_t * mem)
84 {
85 win_std_init(); /* redefine stdin/out/err to our window routines */
86 return 0;
87 }
88
89 /* Define alternate 'open' routines for our stdin/out/err streams. */
90
91 extern const gx_io_device gs_iodev_stdin;
92 private int
win_stdin_open(gx_io_device * iodev,const char * access,stream ** ps,gs_memory_t * mem)93 win_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
94 gs_memory_t * mem)
95 {
96 int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
97 stream *s = *ps;
98
99 if (code != 1)
100 return code;
101 s->procs.process = win_std_read_process;
102 s->procs.available = win_std_available;
103 s->file = NULL;
104 return 0;
105 }
106
107 extern const gx_io_device gs_iodev_stdout;
108 private int
win_stdout_open(gx_io_device * iodev,const char * access,stream ** ps,gs_memory_t * mem)109 win_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
110 gs_memory_t * mem)
111 {
112 int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
113 stream *s = *ps;
114
115 if (code != 1)
116 return code;
117 s->procs.process = win_std_write_process;
118 s->procs.available = win_std_available;
119 s->procs.flush = s_std_write_flush;
120 s->file = NULL;
121 return 0;
122 }
123
124 extern const gx_io_device gs_iodev_stderr;
125 private int
win_stderr_open(gx_io_device * iodev,const char * access,stream ** ps,gs_memory_t * mem)126 win_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
127 gs_memory_t * mem)
128 {
129 int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
130 stream *s = *ps;
131
132 if (code != 1)
133 return code;
134 s->procs.process = win_std_write_process;
135 s->procs.available = win_std_available;
136 s->procs.flush = s_std_write_flush;
137 s->file = NULL;
138 return 0;
139 }
140
141 /* Patch stdin/out/err to use our windows. */
142 private void
win_std_init(void)143 win_std_init(void)
144 {
145 /* If stdxxx is the console, replace the 'open' routines, */
146 /* which haven't gotten called yet. */
147
148 if (gp_file_is_console(gs_stdin))
149 gs_findiodevice((const byte *)"%stdin", 6)->procs.open_device =
150 win_stdin_open;
151
152 if (gp_file_is_console(gs_stdout))
153 gs_findiodevice((const byte *)"%stdout", 7)->procs.open_device =
154 win_stdout_open;
155
156 if (gp_file_is_console(gs_stderr))
157 gs_findiodevice((const byte *)"%stderr", 7)->procs.open_device =
158 win_stderr_open;
159 }
160
161 private int
win_std_read_process(stream_state * st,stream_cursor_read * ignore_pr,stream_cursor_write * pw,bool last)162 win_std_read_process(stream_state * st, stream_cursor_read * ignore_pr,
163 stream_cursor_write * pw, bool last)
164 {
165 int count = pw->limit - pw->ptr;
166
167 if (count == 0) /* empty buffer */
168 return 1;
169
170 /* callback to get more input */
171 count = (*pgsdll_callback) (GSDLL_STDIN, pw->ptr + 1, count);
172 if (count == 0) {
173 /* EOF */
174 /* what should we do? */
175 return EOFC;
176 }
177 pw->ptr += count;
178 return 1;
179 }
180
181 private int
win_std_available(register stream * s,long * pl)182 win_std_available(register stream * s, long *pl)
183 {
184 *pl = -1; // EOF, since we can't do it
185 return 0; // OK
186 }
187
188
189 private int
win_std_write_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * ignore_pw,bool last)190 win_std_write_process(stream_state * st, stream_cursor_read * pr,
191 stream_cursor_write * ignore_pw, bool last)
192 {
193 uint count = pr->limit - pr->ptr;
194
195 (*pgsdll_callback) (GSDLL_STDOUT, (char *)(pr->ptr + 1), count);
196 pr->ptr = pr->limit;
197 return 0;
198 }
199
200 /* This is used instead of the stdio version. */
201 /* The declaration must be identical to that in <stdio.h>. */
202 #if defined(_WIN32) && (defined(_MSC_VER) || defined(_WATCOM_))
203 #if defined(_CRTAPI2)
204 int _CRTAPI2
fprintf(FILE * file,const char * fmt,...)205 fprintf(FILE * file, const char *fmt,...)
206 #else
207 _CRTIMP int __cdecl
208 fprintf(FILE * file, const char *fmt,...)
209 #endif
210 #else
211 int _Cdecl _FARFUNC
212 fprintf(FILE _FAR * file, const char *fmt,...)
213 #endif
214 {
215 int count;
216 va_list args;
217
218 va_start(args, fmt);
219 if (gp_file_is_console(file)) {
220 char buf[1024];
221
222 count = vsprintf(buf, fmt, args);
223 (*pgsdll_callback) (GSDLL_STDOUT, buf, count);
224 } else
225 count = vfprintf(file, fmt, args);
226 va_end(args);
227 return count;
228 }
229