XEmacs 21.2.32 "Kastor & Polydeukes".
[chise/xemacs-chise.git.1] / src / console-msw.c
1 /* Console functions for mswindows.
2    Copyright (C) 1996, 2000 Ben Wing.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: Not in FSF. */
22
23 /* Authorship:
24
25    Ben Wing: January 1996, for 19.14.
26    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0
27  */
28
29 #include <config.h>
30 #include "lisp.h"
31 #include "events.h"
32 #include "opaque.h"
33
34 #include "console-msw.h"
35
36 DEFINE_CONSOLE_TYPE (mswindows);
37 DEFINE_CONSOLE_TYPE (msprinter);
38
39 /************************************************************************/
40 /*                       mswindows console methods                      */
41 /************************************************************************/
42
43 static int
44 mswindows_initially_selected_for_input (struct console *con)
45 {
46   return 1;
47 }
48
49 static HWND msw_console_hwnd = 0;
50
51 #define KLUDGE_BUFSIZE 1024 /* buffer size for console window titles */
52
53 /* Direct from the horse's mouth: Microsoft KB article Q124103 */
54 static HWND
55 GetConsoleHwnd (void)
56
57   HWND hwndFound;         /* this is what is returned to the caller */
58   char pszNewWindowTitle[KLUDGE_BUFSIZE]; /* contains fabricated WindowTitle */
59   char pszOldWindowTitle[KLUDGE_BUFSIZE]; /* contains original WindowTitle */
60
61   /* fetch current window title */
62
63   GetConsoleTitle(pszOldWindowTitle, KLUDGE_BUFSIZE);
64
65   /* format a "unique" NewWindowTitle */
66
67   wsprintf(pszNewWindowTitle,"%d/%d",
68            GetTickCount(),
69            GetCurrentProcessId());
70
71   /* change current window title */
72
73   SetConsoleTitle(pszNewWindowTitle);
74
75   /* ensure window title has been updated */
76
77   Sleep(40);
78
79   /* look for NewWindowTitle */
80
81   hwndFound=FindWindow(NULL, pszNewWindowTitle);
82
83   /* restore original window title */
84
85   SetConsoleTitle(pszOldWindowTitle);
86
87   return(hwndFound);
88
89
90 HWND
91 msw_get_console_hwnd (void)
92 {
93   if (!msw_console_hwnd)
94     msw_console_hwnd = GetConsoleHwnd ();
95   return msw_console_hwnd;
96 }
97
98 int
99 msw_ensure_console_allocated (void)
100 {
101   HWND fgwin = GetForegroundWindow ();
102   /* stupid mswin api won't let you create the console window
103      hidden!  creating it changes the focus!  fuck me! */
104   if (AllocConsole ())
105     {
106       SetForegroundWindow (fgwin);
107       return 1;
108     }
109   return 0;
110 }
111
112 static Lisp_Object
113 mswindows_canonicalize_console_connection (Lisp_Object connection,
114                                            Error_behavior errb)
115 {
116   /* Do not allow more than one mswindows device, by explicitly
117      requiring that CONNECTION is nil, the only allowed connection in
118      Windows. */
119   if (!NILP (connection))
120     {
121       if (ERRB_EQ (errb, ERROR_ME))
122         signal_simple_error
123           ("Invalid (non-nil) connection for mswindows device/console",
124            connection);
125       else
126         return Qunbound;
127     }
128
129   return Qnil;
130 }
131
132 static Lisp_Object
133 mswindows_canonicalize_device_connection (Lisp_Object connection,
134                                           Error_behavior errb)
135 {
136   return mswindows_canonicalize_console_connection (connection, errb);
137 }
138
139 void
140 msw_hide_console (void)
141 {
142   ShowWindow (msw_get_console_hwnd (), SW_HIDE);
143 }
144
145 void
146 msw_show_console (void)
147 {
148   HWND hwnd = msw_get_console_hwnd ();
149   ShowWindow (hwnd, SW_SHOWNA);
150
151   /* I tried to raise the window to the top without activating
152      it, but this fails.  Apparently Windows just doesn't like
153      having the active window not be on top.  So instead, we
154      at least put it just below our own window, where part of it
155      will likely be seen. */
156   SetWindowPos (hwnd, GetForegroundWindow (), 0, 0, 0, 0,
157                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING |
158                 SWP_NOACTIVATE);
159 }
160
161 static int msw_console_buffered = 0;
162 HANDLE msw_console_buffer;
163
164 static void
165 msw_ensure_console_buffered (void)
166 {
167   if (!msw_console_buffered)
168     {
169       COORD new_size;
170
171       new_size.X = 80;
172       new_size.Y = 1000;
173       msw_ensure_console_allocated ();
174       msw_console_buffer =
175         CreateConsoleScreenBuffer (GENERIC_WRITE, 0, NULL,
176                                    CONSOLE_TEXTMODE_BUFFER, NULL);
177       SetConsoleScreenBufferSize (msw_console_buffer, new_size);
178       SetConsoleActiveScreenBuffer (msw_console_buffer);
179       msw_console_buffered = 1;
180     }
181 }
182
183 int
184 msw_output_console_string (CONST Extbyte *str, Extcount len)
185 {
186   DWORD num_written;
187
188   msw_ensure_console_buffered ();
189   msw_show_console ();
190   return WriteConsole (msw_console_buffer, str, len, &num_written, NULL);
191 }
192
193 /* Determine if running on Windows 9x and not NT */
194 int
195 msw_windows9x_p (void)
196 {
197   return GetVersion () & 0x80000000;
198 }
199
200
201 #ifdef DEBUG_XEMACS
202
203 /*
204  * Random helper functions for debugging.
205  * Intended for use in the MSVC "Watch" window which doesn't like
206  * the aborts that the error_check_foo() functions can make.
207  */
208 struct lrecord_header *
209 DHEADER (Lisp_Object obj)
210 {
211   return LRECORDP (obj) ? XRECORD_LHEADER (obj) : NULL;
212 }
213
214 void *
215 DOPAQUE_DATA (Lisp_Object obj)
216 {
217   return OPAQUEP (obj) ? OPAQUE_DATA (XOPAQUE (obj)) : NULL;
218 }
219
220 Lisp_Event *
221 DEVENT (Lisp_Object obj)
222 {
223   return EVENTP (obj) ? XEVENT (obj) : NULL;
224 }
225
226 Lisp_Cons *
227 DCONS (Lisp_Object obj)
228 {
229   return CONSP (obj) ? XCONS (obj) : NULL;
230 }
231
232 Lisp_Cons *
233 DCONSCDR (Lisp_Object obj)
234 {
235   return (CONSP (obj) && CONSP (XCDR (obj))) ? XCONS (XCDR (obj)) : 0;
236 }
237
238 Bufbyte *
239 DSTRING (Lisp_Object obj)
240 {
241   return STRINGP (obj) ? XSTRING_DATA (obj) : NULL;
242 }
243
244 Lisp_Vector *
245 DVECTOR (Lisp_Object obj)
246 {
247   return VECTORP (obj) ? XVECTOR (obj) : NULL;
248 }
249
250 Lisp_Symbol *
251 DSYMBOL (Lisp_Object obj)
252 {
253   return SYMBOLP (obj) ? XSYMBOL (obj) : NULL;
254 }
255
256 Bufbyte *
257 DSYMNAME (Lisp_Object obj)
258 {
259   return SYMBOLP (obj) ? string_data (XSYMBOL (obj)->name) : NULL;
260 }
261
262 #endif /* DEBUG_XEMACS */
263
264
265 \f
266 /************************************************************************/
267 /*                            initialization                            */
268 /************************************************************************/
269
270 void
271 syms_of_console_mswindows (void)
272 {
273 }
274
275 void
276 console_type_create_mswindows (void)
277 {
278   INITIALIZE_CONSOLE_TYPE (mswindows, "mswindows", "console-mswindows-p");
279
280   /* console methods */
281 /*  CONSOLE_HAS_METHOD (mswindows, init_console); */
282 /*  CONSOLE_HAS_METHOD (mswindows, mark_console); */
283   CONSOLE_HAS_METHOD (mswindows, initially_selected_for_input);
284 /*  CONSOLE_HAS_METHOD (mswindows, delete_console); */
285   CONSOLE_HAS_METHOD (mswindows, canonicalize_console_connection);
286   CONSOLE_HAS_METHOD (mswindows, canonicalize_device_connection);
287 /*  CONSOLE_HAS_METHOD (mswindows, semi_canonicalize_console_connection); */
288 /*  CONSOLE_HAS_METHOD (mswindows, semi_canonicalize_device_connection); */
289
290   INITIALIZE_CONSOLE_TYPE (msprinter, "msprinter", "console-msprinter-p");
291 }
292
293 void
294 reinit_console_type_create_mswindows (void)
295 {
296   REINITIALIZE_CONSOLE_TYPE (mswindows);
297   REINITIALIZE_CONSOLE_TYPE (msprinter);
298 }
299
300 void
301 vars_of_console_mswindows (void)
302 {
303   Fprovide (Qmswindows);
304 }