1 /* Console functions for mswindows.
2 Copyright (C) 1996, 2000 Ben Wing.
4 This file is part of XEmacs.
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
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
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. */
21 /* Synched up with: Not in FSF. */
25 Ben Wing: January 1996, for 19.14.
26 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0
33 #include "console-msw.h"
37 DEFINE_CONSOLE_TYPE (mswindows);
38 DEFINE_CONSOLE_TYPE (msprinter);
40 Lisp_Object Qabortretryignore;
41 Lisp_Object Qapplmodal;
42 Lisp_Object Qdefault_desktop_only;
43 Lisp_Object Qdefbutton1;
44 Lisp_Object Qdefbutton2;
45 Lisp_Object Qdefbutton3;
46 Lisp_Object Qdefbutton4;
47 /* Lisp_Object Qhelp; */
48 Lisp_Object Qiconasterisk;
49 Lisp_Object Qiconexclamation;
50 Lisp_Object Qiconhand;
51 Lisp_Object Qiconinformation;
52 Lisp_Object Qiconquestion;
53 Lisp_Object Qiconstop;
54 /* Lisp_Object Qok; */
55 Lisp_Object Qokcancel;
56 Lisp_Object Qretrycancel;
57 /* Lisp_Object Qright; */
58 Lisp_Object Qrtlreading;
59 Lisp_Object Qservice_notification;
60 Lisp_Object Qsetforeground;
61 Lisp_Object Qsystemmodal;
62 Lisp_Object Qtaskmodal;
65 Lisp_Object Qyesnocancel;
67 /* Lisp_Object Qabort; */
68 /* Lisp_Object Qcancel; */
69 /* Lisp_Object Qignore; */
70 /* Lisp_Object Qno; */
71 /* Lisp_Object Qok; */
72 /* Lisp_Object Qretry; */
73 /* Lisp_Object Qyes; */
76 /************************************************************************/
77 /* mswindows console methods */
78 /************************************************************************/
81 mswindows_initially_selected_for_input (struct console *con)
86 static HWND msw_console_hwnd = 0;
88 #define KLUDGE_BUFSIZE 1024 /* buffer size for console window titles */
90 /* Direct from the horse's mouth: Microsoft KB article Q124103 */
94 HWND hwndFound; /* this is what is returned to the caller */
95 char pszNewWindowTitle[KLUDGE_BUFSIZE]; /* contains fabricated WindowTitle */
96 char pszOldWindowTitle[KLUDGE_BUFSIZE]; /* contains original WindowTitle */
98 /* fetch current window title */
100 GetConsoleTitle(pszOldWindowTitle, KLUDGE_BUFSIZE);
102 /* format a "unique" NewWindowTitle */
104 wsprintf(pszNewWindowTitle,"%d/%d",
106 GetCurrentProcessId());
108 /* change current window title */
110 SetConsoleTitle(pszNewWindowTitle);
112 /* ensure window title has been updated */
116 /* look for NewWindowTitle */
118 hwndFound=FindWindow(NULL, pszNewWindowTitle);
120 /* restore original window title */
122 SetConsoleTitle(pszOldWindowTitle);
128 msw_get_console_hwnd (void)
130 if (!msw_console_hwnd)
131 msw_console_hwnd = GetConsoleHwnd ();
132 return msw_console_hwnd;
136 msw_ensure_console_allocated (void)
138 HWND fgwin = GetForegroundWindow ();
139 /* stupid mswin api won't let you create the console window
140 hidden! creating it changes the focus! fuck me! */
143 SetForegroundWindow (fgwin);
150 mswindows_canonicalize_console_connection (Lisp_Object connection,
153 /* Do not allow more than one mswindows device, by explicitly
154 requiring that CONNECTION is nil, the only allowed connection in
156 if (!NILP (connection))
158 if (ERRB_EQ (errb, ERROR_ME))
160 ("Invalid (non-nil) connection for mswindows device/console",
170 mswindows_canonicalize_device_connection (Lisp_Object connection,
173 return mswindows_canonicalize_console_connection (connection, errb);
177 msw_hide_console (void)
179 ShowWindow (msw_get_console_hwnd (), SW_HIDE);
183 msw_show_console (void)
185 HWND hwnd = msw_get_console_hwnd ();
186 ShowWindow (hwnd, SW_SHOWNA);
188 /* I tried to raise the window to the top without activating
189 it, but this fails. Apparently Windows just doesn't like
190 having the active window not be on top. So instead, we
191 at least put it just below our own window, where part of it
192 will likely be seen. */
193 SetWindowPos (hwnd, GetForegroundWindow (), 0, 0, 0, 0,
194 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING |
198 static int msw_console_buffered = 0;
199 HANDLE msw_console_buffer;
202 msw_ensure_console_buffered (void)
204 if (!msw_console_buffered)
210 msw_ensure_console_allocated ();
212 CreateConsoleScreenBuffer (GENERIC_WRITE, 0, NULL,
213 CONSOLE_TEXTMODE_BUFFER, NULL);
214 SetConsoleScreenBufferSize (msw_console_buffer, new_size);
215 SetConsoleActiveScreenBuffer (msw_console_buffer);
216 msw_console_buffered = 1;
221 msw_output_console_string (CONST Extbyte *str, Extcount len)
225 msw_ensure_console_buffered ();
227 return WriteConsole (msw_console_buffer, str, len, &num_written, NULL);
230 /* Determine if running on Windows 9x and not NT */
232 msw_windows9x_p (void)
234 return GetVersion () & 0x80000000;
241 * Random helper functions for debugging.
242 * Intended for use in the MSVC "Watch" window which doesn't like
243 * the aborts that the error_check_foo() functions can make.
245 struct lrecord_header *
246 DHEADER (Lisp_Object obj)
248 return LRECORDP (obj) ? XRECORD_LHEADER (obj) : NULL;
252 DOPAQUE_DATA (Lisp_Object obj)
254 return OPAQUEP (obj) ? OPAQUE_DATA (XOPAQUE (obj)) : NULL;
258 DEVENT (Lisp_Object obj)
260 return EVENTP (obj) ? XEVENT (obj) : NULL;
264 DCONS (Lisp_Object obj)
266 return CONSP (obj) ? XCONS (obj) : NULL;
270 DCONSCDR (Lisp_Object obj)
272 return (CONSP (obj) && CONSP (XCDR (obj))) ? XCONS (XCDR (obj)) : 0;
276 DSTRING (Lisp_Object obj)
278 return STRINGP (obj) ? XSTRING_DATA (obj) : NULL;
282 DVECTOR (Lisp_Object obj)
284 return VECTORP (obj) ? XVECTOR (obj) : NULL;
288 DSYMBOL (Lisp_Object obj)
290 return SYMBOLP (obj) ? XSYMBOL (obj) : NULL;
294 DSYMNAME (Lisp_Object obj)
296 return SYMBOLP (obj) ? string_data (XSYMBOL (obj)->name) : NULL;
299 #endif /* DEBUG_XEMACS */
301 DEFUN ("mswindows-message-box", Fmswindows_message_box, 1, 3, 0, /*
302 Pop up an MS Windows message box.
303 MESSAGE is the string to display. Optional argument FLAG controls
304 what appears in the box and how it behaves; it is a symbol or list of
305 symbols, described below. Second optional argument TITLE controls the
306 title bar; if omitted, a standard title bar will be used, probably
312 -- To specify the buttons in the message box:
315 The message box contains three push buttons: Abort, Retry, and Ignore.
317 The message box contains one push button: OK. This is the default.
319 The message box contains two push buttons: OK and Cancel.
321 The message box contains two push buttons: Retry and Cancel.
323 The message box contains two push buttons: Yes and No.
325 The message box contains three push buttons: Yes, No, and Cancel.
328 -- To display an icon in the message box:
330 iconexclamation, iconwarning
331 An exclamation-point icon appears in the message box.
332 iconinformation, iconasterisk
333 An icon consisting of a lowercase letter i in a circle appears in
336 A question-mark icon appears in the message box.
337 iconstop, iconerror, iconhand
338 A stop-sign icon appears in the message box.
341 -- To indicate the default button:
344 The first button is the default button. This is the default.
346 The second button is the default button.
348 The third button is the default button.
350 The fourth button is the default button.
353 -- To indicate the modality of the dialog box:
356 The user must respond to the message box before continuing work in
357 the window identified by the hWnd parameter. However, the user can
358 move to the windows of other applications and work in those windows.
359 Depending on the hierarchy of windows in the application, the user
360 may be able to move to other windows within the application. All
361 child windows of the parent of the message box are automatically
362 disabled, but popup windows are not. This is the default.
364 Same as applmodal except that the message box has the WS_EX_TOPMOST
365 style. Use system-modal message boxes to notify the user of serious,
366 potentially damaging errors that require immediate attention (for
367 example, running out of memory). This flag has no effect on the
368 user's ability to interact with windows other than those associated
371 Same as applmodal except that all the top-level windows belonging to
372 the current task are disabled if the hWnd parameter is NULL. Use
373 this flag when the calling application or library does not have a
374 window handle available but still needs to prevent input to other
375 windows in the current application without suspending other
379 In addition, you can specify the following flags:
382 The desktop currently receiving input must be a default desktop;
383 otherwise, the function fails. A default desktop is one an
384 application runs on after the user has logged on.
386 Adds a Help button to the message box. Choosing the Help button or
387 pressing F1 generates a Help event.
389 The text is right-justified.
391 Displays message and caption text using right-to-left reading order
392 on Hebrew and Arabic systems.
394 The message box becomes the foreground window. Internally, Windows
395 calls the SetForegroundWindow function for the message box.
397 The message box is created with the WS_EX_TOPMOST window style.
399 Windows NT only: The caller is a service notifying the user of an
400 event. The function displays a message box on the current active
401 desktop, even if there is no user logged on to the computer. If
402 this flag is set, the hWnd parameter must be NULL. This is so the
403 message box can appear on a desktop other than the desktop
404 corresponding to the hWnd.
408 The return value is one of the following menu-item values returned by
412 Abort button was selected.
414 Cancel button was selected.
416 Ignore button was selected.
418 No button was selected.
420 OK button was selected.
422 Retry button was selected.
424 Yes button was selected.
426 If a message box has a Cancel button, the function returns the
427 `cancel' value if either the ESC key is pressed or the Cancel button
428 is selected. If the message box has no Cancel button, pressing ESC has
430 (message_, flags, title))
434 Extbyte *titleout = 0;
442 CHECK_SYMBOL (flags);
443 flags = list1 (flags);
446 CHECK_STRING (message_);
447 TO_EXTERNAL_FORMAT (LISP_STRING, message_,
448 C_STRING_ALLOCA, msgout,
453 CHECK_STRING (title);
454 TO_EXTERNAL_FORMAT (LISP_STRING, title,
455 C_STRING_ALLOCA, titleout,
459 EXTERNAL_LIST_LOOP (tail, flags)
461 Lisp_Object st = XCAR (tail);
465 #define FROB(sym, val) else if (EQ (st, sym)) sty |= val
466 FROB (Qabortretryignore, MB_ABORTRETRYIGNORE);
467 FROB (Qapplmodal, MB_APPLMODAL);
468 FROB (Qdefault_desktop_only, MB_DEFAULT_DESKTOP_ONLY);
469 FROB (Qdefbutton1, MB_DEFBUTTON1);
470 FROB (Qdefbutton2, MB_DEFBUTTON2);
471 FROB (Qdefbutton3, MB_DEFBUTTON3);
472 FROB (Qdefbutton4, MB_DEFBUTTON4);
473 FROB (Qhelp, MB_HELP);
474 FROB (Qiconasterisk, MB_ICONASTERISK);
475 FROB (Qiconexclamation, MB_ICONEXCLAMATION);
476 FROB (Qiconhand, MB_ICONHAND);
477 FROB (Qiconinformation, MB_ICONINFORMATION);
478 FROB (Qiconquestion, MB_ICONQUESTION);
479 FROB (Qiconstop, MB_ICONSTOP);
481 FROB (Qokcancel, MB_OKCANCEL);
482 FROB (Qretrycancel, MB_RETRYCANCEL);
483 FROB (Qright, MB_RIGHT);
484 FROB (Qrtlreading, MB_RTLREADING);
485 FROB (Qservice_notification, MB_SERVICE_NOTIFICATION);
486 FROB (Qsetforeground, MB_SETFOREGROUND);
487 FROB (Qsystemmodal, MB_SYSTEMMODAL);
488 FROB (Qtaskmodal, MB_TASKMODAL);
489 FROB (Qtopmost, MB_TOPMOST);
490 FROB (Qyesno, MB_YESNO);
491 FROB (Qyesnocancel, MB_YESNOCANCEL);
495 signal_simple_error ("Unrecognized flag", st);
499 int retval = MessageBox (NULL, msgout, titleout, sty);
502 error ("Out of memory when calling `mswindows-message-box'");
504 #define FROB(sym, val) if (retval == val) return sym
505 FROB (Qabort, IDABORT);
506 FROB (Qcancel, IDCANCEL);
507 FROB (Qignore, IDIGNORE);
510 FROB (Qretry, IDRETRY);
514 signal_simple_error ("Unknown return value from MessageBox()",
522 mswindows_output_last_error (char *frob)
525 int errval = GetLastError();
527 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
528 | FORMAT_MESSAGE_FROM_SYSTEM,
530 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
534 stderr_out ("last error during %s is %d: %s\n",
535 frob, errval, (char*)lpMsgBuf);
539 /************************************************************************/
541 /************************************************************************/
544 syms_of_console_mswindows (void)
546 defsymbol (&Qabortretryignore, "abortretryignore");
547 defsymbol (&Qapplmodal, "applmodal");
548 defsymbol (&Qdefault_desktop_only, "default-desktop-only");
549 defsymbol (&Qdefbutton1, "defbutton1");
550 defsymbol (&Qdefbutton2, "defbutton2");
551 defsymbol (&Qdefbutton3, "defbutton3");
552 defsymbol (&Qdefbutton4, "defbutton4");
553 /* defsymbol (&Qhelp, "help"); */
554 defsymbol (&Qiconasterisk, "iconasterisk");
555 defsymbol (&Qiconexclamation, "iconexclamation");
556 defsymbol (&Qiconhand, "iconhand");
557 defsymbol (&Qiconinformation, "iconinformation");
558 defsymbol (&Qiconquestion, "iconquestion");
559 defsymbol (&Qiconstop, "iconstop");
560 /* defsymbol (&Qok, "ok"); */
561 defsymbol (&Qokcancel, "okcancel");
562 defsymbol (&Qretrycancel, "retrycancel");
563 /* defsymbol (&Qright, "right"); */
564 defsymbol (&Qrtlreading, "rtlreading");
565 defsymbol (&Qservice_notification, "service-notification");
566 defsymbol (&Qsetforeground, "setforeground");
567 defsymbol (&Qsystemmodal, "systemmodal");
568 defsymbol (&Qtaskmodal, "taskmodal");
569 defsymbol (&Qtopmost, "topmost");
570 defsymbol (&Qyesno, "yesno");
571 defsymbol (&Qyesnocancel, "yesnocancel");
573 /* defsymbol (&Qabort, "abort"); */
574 /* defsymbol (&Qcancel, "cancel"); */
575 /* defsymbol (&Qignore, "ignore"); */
576 /* defsymbol (&Qno, "no"); */
577 /* defsymbol (&Qok, "ok"); */
578 /* defsymbol (&Qretry, "retry"); */
579 /* defsymbol (&Qyes, "yes"); */
581 DEFSUBR (Fmswindows_message_box);
585 console_type_create_mswindows (void)
587 INITIALIZE_CONSOLE_TYPE (mswindows, "mswindows", "console-mswindows-p");
589 /* console methods */
590 /* CONSOLE_HAS_METHOD (mswindows, init_console); */
591 /* CONSOLE_HAS_METHOD (mswindows, mark_console); */
592 CONSOLE_HAS_METHOD (mswindows, initially_selected_for_input);
593 /* CONSOLE_HAS_METHOD (mswindows, delete_console); */
594 CONSOLE_HAS_METHOD (mswindows, canonicalize_console_connection);
595 CONSOLE_HAS_METHOD (mswindows, canonicalize_device_connection);
596 /* CONSOLE_HAS_METHOD (mswindows, semi_canonicalize_console_connection); */
597 /* CONSOLE_HAS_METHOD (mswindows, semi_canonicalize_device_connection); */
599 INITIALIZE_CONSOLE_TYPE (msprinter, "msprinter", "console-msprinter-p");
603 reinit_console_type_create_mswindows (void)
605 REINITIALIZE_CONSOLE_TYPE (mswindows);
606 REINITIALIZE_CONSOLE_TYPE (msprinter);
610 vars_of_console_mswindows (void)
612 Fprovide (Qmswindows);