1 /* -*-C-*-
2
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6 Institute of Technology
7
8 This file is part of MIT/GNU Scheme.
9
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24
25 */
26
27 #include "nt.h"
28 #include "ntscreen.h"
29 #include "ntgui.h"
30 #include <windowsx.h>
31
32 /* constant definitions */
33
34 #define GWL_SCREEN 0
35 #define SCREENEXTRABYTES (sizeof(LONG))
36
37 #define MAXCOLS 180
38 #define MAXROWS 100
39
40 /* ascii definitions */
41
42 #define ASCII_BEL (0x07)
43 #define ASCII_BS (0x08)
44 #define ASCII_LF (0x0A)
45 #define ASCII_FF (0x0C)
46 #define ASCII_CR (0x0D)
47 #define ASCII_ESC (0x1B)
48 #define ASCII_DEL (0x7F)
49
50 #define ASCII_CONTROLIFY(ascii) ((ascii) - '@')
51 #define ASCII_METAFY(ascii) ((ascii) | 0200)
52
53 /* data structures */
54
55 #ifndef MAX_FREE_EVENTS
56 #define MAX_FREE_EVENTS 1024
57 #endif
58
59 typedef struct tagSCREEN_EVENT_LINK
60 {
61 SCREEN_EVENT event;
62 struct tagSCREEN_EVENT_LINK * next;
63 } SCREEN_EVENT_LINK;
64
65 #define MAX_COMMANDS 30
66
67 #define MAX_BINDINGS 10
68
69 #define MAX_LINEINPUT 1024
70
71 #define COMPUTE_SCROLL_LINES(height) ((((height) * 2) + 4) / 5)
72
73 #define DEFAULT_ICON "DEFAULT_ICON"
74
75 typedef struct tagSCREENINFO
76 {
77 SCREEN registry_link;
78
79 HWND hWnd;
80 HICON hIcon;
81
82 char * chars;
83 SCREEN_ATTRIBUTE * attrs;
84 unsigned long mode_flags; /* event types & modes */
85 SCREEN_ATTRIBUTE write_attribute;
86
87 BOOL cursor_visible;
88 BOOL has_focus;
89
90 HFONT hFont;
91 LOGFONT lfFont;
92 DWORD rgbFGColour;
93 DWORD rgbBGColour;
94 int xSize, ySize;
95 int xScroll, yScroll;
96 int xOffset, yOffset; /* coords of top left corner of client area wrt */
97 /* character area */
98 int column, row; /* caret position */
99 int xChar, yChar; /* size of characters in pixels */
100 int width, height; /* size of text ares in characters */
101
102 int n_commands;
103 struct
104 {
105 WORD wID;
106 COMMAND_HANDLER thunk;
107 } commands[MAX_COMMANDS];
108
109 int n_bindings;
110 struct
111 {
112 char key;
113 WORD command;
114 } bindings[MAX_BINDINGS];
115
116 /* for line input */
117 int n_chars;
118 char * line_buffer;
119
120 /* ANSI emulator overflow */
121 int n_pending;
122 LPSTR pending;
123
124 HBRUSH bkgnd_brush;
125 int scroll_lines;
126
127 } SCREEN_STRUCT;
128
129 /* #define WIDTH(screen) (screen->width) */
130 #define WIDTH(screen) MAXCOLS
131 #define HEIGHT(screen) MAXROWS
132 /* macros ( for easier readability ) */
133
134 #define GETSCREEN( x ) ((SCREEN) GetWindowLong( x, GWL_SCREEN ))
135 #define SETSCREEN( x, y ) SetWindowLong( x, GWL_SCREEN, (LONG) y )
136
137 /* CRT mappings to NT API */
138
139 #define _fmemset memset
140 #define _fmemmove memmove
141
142 static LRESULT CreateScreenInfo (HWND);
143 static VOID DestroyScreenInfo (HWND);
144 static BOOL ResetScreen (SCREEN);
145 extern BOOL KillScreenFocus (HWND);
146 static VOID PaintScreen (HWND);
147 /* static VOID EraseScreen (HWND, HDC); */
148 static BOOL SetScreenFocus (HWND);
149 static BOOL ScrollScreenHorz (HWND, WORD, WORD);
150 static BOOL ScrollScreenVert (HWND, WORD, WORD);
151 static BOOL SizeScreen (HWND, WORD, WORD);
152 static BOOL handle_window_pos_changing (HWND, LPWINDOWPOS);
153 static void reset_modifiers (void);
154 static void record_modifier_transition (WPARAM, LPARAM, BOOL);
155 static int process_keydown (HWND, UINT, WPARAM, LPARAM);
156 static void process_character (HWND, UINT, WPARAM, LPARAM);
157 static VOID ProcessMouseButton (HWND, UINT, UINT, LONG, BOOL);
158 static VOID ProcessCloseMessage (SCREEN);
159 static void process_focus_message (HWND, int);
160 static void process_show_message (HWND, int);
161 static BOOL WriteScreenBlock (HWND, LPSTR, int);
162 static int ReadScreen (SCREEN, char*, int);
163 static VOID MoveScreenCursor (SCREEN);
164 extern UINT ScreenPeekOrRead
165 (SCREEN, int count, SCREEN_EVENT* buffer, BOOL remove);
166 extern void flush_typeahead (SCREEN);
167 static COMMAND_HANDLER ScreenSetCommand
168 (SCREEN, WORD cmd, COMMAND_HANDLER handler);
169 static WORD ScreenSetBinding (SCREEN, char key, WORD command);
170 static VOID GetMinMaxSizes(HWND,LPPOINT,LPPOINT);
171 static BOOL AdjustedSize (SCREEN,int*,int*);
172 extern VOID Screen_Clear (SCREEN,int);
173 static BOOL SelectScreenFont (SCREEN, HWND);
174 static BOOL SelectScreenBackColor (SCREEN, HWND);
175
176 static HFONT set_font_1 (char *, LOGFONT *);
177 static BOOL parse_logfont (char *, LOGFONT *);
178 static long points_to_logical_units (long);
179 static BOOL search_for_font (LOGFONT *);
180 static int CALLBACK search_for_font_proc
181 (ENUMLOGFONT *, NEWTEXTMETRIC *, int, LPARAM);
182
183 extern LRESULT ScreenCommand_ChooseFont (HWND, WORD);
184 extern LRESULT ScreenCommand_ChooseBackColor (HWND, WORD);
185
186 static SCREEN_EVENT * allocate_event (SCREEN, SCREEN_EVENT_TYPE);
187 static int read_event (SCREEN, SCREEN_EVENT_TYPE, int, SCREEN_EVENT *);
188
189 /* void *xmalloc (int size); */
190 /* void xfree (void*); */
191 #define xfree free
192 #define xmalloc malloc
193
194 extern LRESULT FAR CALLBACK ScreenWndProc (HWND, UINT, WPARAM, LPARAM);
195
196 static VOID RegisterScreen (SCREEN);
197 static VOID UnregisterScreen (SCREEN);
198
199 static const char * translate_message_code (UINT);
200
201 /* FILE GLOBAL VARIABLES */
202
203 static HANDLE ghInstance;
204 static HICON ghDefaultIcon;
205
206 static LOGFONT lfDefaultLogFont;
207
208 static unsigned int n_free_events;
209 static SCREEN_EVENT_LINK * free_events;
210 static SCREEN_EVENT_LINK * event_queue_head;
211 static SCREEN_EVENT_LINK * event_queue_tail;
212
213 FILE * win32_trace_file;
214 unsigned long win32_trace_level;
215
216 static long
screen_x_extra(SCREEN screen)217 screen_x_extra (SCREEN screen)
218 {
219 return ((GetSystemMetrics (SM_CXFRAME)) * 2);
220 }
221
222 static long
screen_y_extra(SCREEN screen)223 screen_y_extra (SCREEN screen)
224 {
225 return (((GetSystemMetrics (SM_CYFRAME)) * 2)
226 + (GetSystemMetrics (SM_CYCAPTION))
227 + ((GetMenu (screen -> hWnd)) ? (GetSystemMetrics (SM_CYMENU)) : 0)
228 #ifdef __WATCOMC__
229 /* Magic: when the combination of cyframe*2 and cycaption is
230 28, AdjustWindowRect indicates that it should be 27. I
231 don't know why this only happens under Watcom. */
232 - 1
233 #endif
234 );
235 }
236
237 static long
pixel_to_char_width(SCREEN screen,long pixel_width)238 pixel_to_char_width (SCREEN screen, long pixel_width)
239 {
240 return
241 (((pixel_width - (screen_x_extra (screen))) + (screen -> xOffset))
242 / (screen -> xChar));
243 }
244
245 static long
pixel_to_char_height(SCREEN screen,long pixel_height)246 pixel_to_char_height (SCREEN screen, long pixel_height)
247 {
248 return
249 (((pixel_height - (screen_y_extra (screen))) + (screen -> yOffset))
250 / (screen -> yChar));
251 }
252
253 static long
char_to_pixel_width(SCREEN screen,long char_width)254 char_to_pixel_width (SCREEN screen, long char_width)
255 {
256 return
257 (((char_width * (screen -> xChar)) - (screen -> xOffset))
258 + (screen_x_extra (screen)));
259 }
260
261 static long
char_to_pixel_height(SCREEN screen,long char_height)262 char_to_pixel_height (SCREEN screen, long char_height)
263 {
264 return
265 (((char_height * (screen -> yChar)) - (screen -> yOffset))
266 + (screen_y_extra (screen)));
267 }
268
269 static void
init_LOGFONT(LOGFONT * lf)270 init_LOGFONT (LOGFONT *lf)
271 {
272 lf->lfHeight = 0;
273 lf->lfWidth = 0;
274 lf->lfEscapement = 0;
275 lf->lfOrientation = 0;
276 lf->lfWeight = FW_NORMAL;
277 lf->lfItalic = 0;
278 lf->lfUnderline = 0;
279 lf->lfStrikeOut = 0;
280 lf->lfCharSet = ANSI_CHARSET;
281 lf->lfOutPrecision = OUT_RASTER_PRECIS;
282 lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
283 lf->lfQuality = PROOF_QUALITY;
284 lf->lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
285 lstrcpy (lf->lfFaceName, "");
286 }
287
288 static BOOL
init_color(char * color_symbol,HWND hWnd,DWORD * color)289 init_color (char *color_symbol, HWND hWnd, DWORD *color)
290 {
291 HDC hdc;
292 char * envvar = getenv (color_symbol);
293 if (envvar == NULL)
294 return FALSE;
295 /* Use GetNearestColor to ensure consistency with the background
296 text color. */
297 hdc = GetDC (hWnd);
298 *color = GetNearestColor (hdc, strtoul (envvar, NULL, 0));
299 ReleaseDC (hWnd, hdc);
300 return TRUE;
301 }
302
303 static BOOL
init_geometry(char * geom_symbol,int * params)304 init_geometry (char *geom_symbol, int *params)
305 {
306 int ctr;
307 char * token;
308 char * envvar = getenv (geom_symbol);
309 char tempvar[100];
310
311 if (envvar == NULL)
312 return FALSE;
313
314 envvar = lstrcpy (tempvar, envvar);
315
316 for (ctr = 0, token = (strtok (envvar, ",;*+ \t\n"));
317 ((ctr < 4) && (token != ((char *) NULL)));
318 ctr++, token = (strtok (((char *) NULL), ",;*+ \t\n")))
319 params[ctr] = strtoul (token, NULL, 0);
320 return FALSE;
321 }
322
323 #ifdef WINDOWSLOSES
324
325 static BOOL
326 MIT_trap_alt_tab = ((BOOL) 1),
327 MIT_trap_alt_escape = ((BOOL) 1);
328
329 static VOID
init_flag(char * flag_symbol,BOOL * flag)330 init_flag (char *flag_symbol, BOOL *flag)
331 {
332 extern int strcmp_ci (char *, char *);
333 char *envvar = getenv (flag_symbol);
334 if (envvar != NULL)
335 {
336 if ((strcmp_ci (envvar, "true")) || (strcmp_ci (envvar, "yes")))
337 *flag = (BOOL) 1;
338 else if ((strcmp_ci (envvar, "false")) || (strcmp_ci (envvar, "no")))
339 *flag = (BOOL) 0;
340 }
341 }
342
343 VOID
init_MIT_Keyboard(VOID)344 init_MIT_Keyboard (VOID)
345 {
346 init_flag ("MITSCHEME_TRAP_ALT_TAB", (& MIT_trap_alt_tab));
347 init_flag ("MITSCHEME_TRAP_ALT_ESCAPE", (& MIT_trap_alt_escape));
348 }
349 #endif /* WINDOWSLOSES */
350
351 /* BOOL Screen_InitApplication (HANDLE hInstance)
352
353 Description:
354 First time initialization stuff for screen class.
355 This registers information such as window classes.
356
357 Parameters:
358 HANDLE hInstance
359 Handle to this instance of the application.
360 */
361
362 BOOL
Screen_InitApplication(HANDLE hInstance)363 Screen_InitApplication (HANDLE hInstance)
364 {
365 WNDCLASSEX wndclass;
366 char * font_name = getenv ("MITSCHEME_FONT");
367
368 init_LOGFONT (&lfDefaultLogFont);
369 if (font_name)
370 ScreenSetDefaultFont (font_name);
371
372 win32_trace_file = 0;
373 win32_trace_level = 0;
374
375 #ifdef WINDOWSLOSES
376 init_MIT_Keyboard ();
377 #endif /* WINDOWSLOSES */
378
379 wndclass.cbSize = (sizeof (wndclass));
380 wndclass.style = 0;
381 wndclass.lpfnWndProc = ScreenWndProc;
382 wndclass.cbClsExtra = 0;
383 wndclass.cbWndExtra = SCREENEXTRABYTES;
384 wndclass.hInstance = hInstance;
385 wndclass.hIcon = (LoadIcon (hInstance, DEFAULT_ICON));
386 wndclass.hCursor = (LoadCursor (NULL, IDC_ARROW));
387 wndclass.hbrBackground = 0;
388 wndclass.lpszMenuName = 0;
389 wndclass.lpszClassName = "MIT-SCREEN";
390 wndclass.hIconSm = (wndclass . hIcon);
391
392 n_free_events = 0;
393 free_events = 0;
394 event_queue_head = 0;
395 event_queue_tail = 0;
396
397 return (RegisterClassEx (&wndclass));
398 }
399
400 /* BOOL Screen_InitInstance (HANDLE hInstance, int nCmdShow )
401
402 Description:
403 Initializes instance specific information for the screen class.
404 returns TRUE on success.
405
406 Parameters:
407 HANDLE hInstance
408 Handle to instance
409
410 int nCmdShow
411 How do we show the window?
412 */
413
414 BOOL
Screen_InitInstance(HANDLE hInstance,int nCmdShow)415 Screen_InitInstance (HANDLE hInstance, int nCmdShow )
416 {
417 ghInstance = hInstance;
418 ghDefaultIcon = LoadIcon (hInstance, DEFAULT_ICON);
419 return TRUE;
420 }
421
422 /* SCREEN Screen_Create (HANDLE hParent, LPCSTR title, int nCmdShow)
423
424 Description:
425 Create a screen window with a given parent.
426
427 Parameters:
428 hParent
429 Handle to parent window
430 */
431
432 static int def_params[4] =
433 {
434 CW_USEDEFAULT, /* Left */
435 CW_USEDEFAULT, /* Top */
436 CW_USEDEFAULT, /* Width */
437 CW_USEDEFAULT /* Height */
438 };
439
440 HANDLE
Screen_Create(HANDLE hParent,LPCSTR title,int nCmdShow)441 Screen_Create (HANDLE hParent, LPCSTR title, int nCmdShow)
442 {
443 HWND hwnd;
444 int ctr, params[4] = {-1, -1, -1, -1};
445
446 if (hParent == ((HANDLE) NULL))
447 init_geometry ("MITSCHEME_GEOMETRY", ¶ms[0]);
448
449 for (ctr = 0; ctr < 4; ctr++)
450 if (params[ctr] == -1)
451 params[ctr] = def_params[ctr];
452
453 hwnd = CreateWindow ("MIT-SCREEN", title,
454 WS_OVERLAPPEDWINDOW,
455 params[0], params[1],
456 params[2], params[3],
457 hParent, NULL, ghInstance,
458 ((LPVOID) nCmdShow));
459 return hwnd;
460 }
461
462 VOID
Screen_Destroy(BOOL root,HANDLE hwnd)463 Screen_Destroy (BOOL root, HANDLE hwnd)
464 {
465 DestroyWindow (hwnd);
466 }
467
468 /* Registry of screen handles */
469
470 static SCREEN registered_screens = 0;
471
472 static VOID
RegisterScreen(SCREEN screen)473 RegisterScreen (SCREEN screen)
474 {
475 screen->registry_link = registered_screens;
476 registered_screens = screen;
477 }
478
479 static SCREEN*
head_to_registered_screen(HWND hWnd)480 head_to_registered_screen (HWND hWnd)
481 {
482 SCREEN *link = ®istered_screens;
483 while (*link)
484 if ((*link)->hWnd == hWnd)
485 return link;
486 else
487 link = &((*link)->registry_link);
488 return 0;
489 }
490
491 static VOID
UnregisterScreen(SCREEN screen)492 UnregisterScreen (SCREEN screen)
493 {
494 SCREEN *link = head_to_registered_screen (screen->hWnd);
495 /* if (link) */
496 *link = screen->registry_link;
497 }
498
499 BOOL
Screen_IsScreenHandle(HANDLE handle)500 Screen_IsScreenHandle (HANDLE handle)
501 {
502 return head_to_registered_screen (handle) != 0;
503 }
504
505 /* LRESULT FAR CALLBACK ScreenWndProc (HWND hWnd, UINT uMsg,
506 WPARAM wParam, LPARAM lParam )
507
508 This is the TTY Window Proc. This handles ALL messages to the tty
509 window.
510 */
511
512 LRESULT FAR CALLBACK
ScreenWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)513 ScreenWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
514 {
515 SCREEN screen = GETSCREEN (hWnd);
516
517 /* Ignore common but uninteresting messages. */
518 if (win32_trace_level
519 > (((uMsg == WM_SCHEME_INTERRUPT)
520 || (uMsg == WM_PAINT)
521 || (uMsg == WM_TIMER)
522 || (uMsg == WM_NCHITTEST)
523 || (uMsg == WM_SETCURSOR)
524 || (uMsg == WM_MOUSEMOVE))
525 ? 2
526 : 0))
527 {
528 const char * name = (translate_message_code (uMsg));
529 fprintf (win32_trace_file, "ScreenWndProc: ");
530 fprintf (win32_trace_file, "hWnd=0x%x, ", hWnd);
531 if (name)
532 fprintf (win32_trace_file, "uMsg=%s, ", name);
533 else
534 fprintf (win32_trace_file, "uMsg=0x%x, ", uMsg);
535 fprintf (win32_trace_file, "wParam=0x%x, lParam=0x%x\n",
536 wParam, lParam);
537 fflush (win32_trace_file);
538 }
539 switch (uMsg)
540 {
541 case WM_CREATE:
542 {
543 LRESULT result = CreateScreenInfo (hWnd);
544 ShowWindow (hWnd,
545 ((int) ((LPCREATESTRUCT) lParam) -> lpCreateParams));
546 UpdateWindow (hWnd);
547 return result;
548 }
549
550 case WM_SCHEME_INTERRUPT:
551 return (0);
552
553 case SCREEN_SETPOSITION:
554 return (LRESULT)Screen_SetPosition
555 (screen, HIWORD(lParam), LOWORD(lParam));
556
557 case SCREEN_GETPOSITION:
558 return MAKELRESULT(screen->column, screen->row);
559
560 case SCREEN_SETATTRIBUTE:
561 screen->write_attribute = (SCREEN_ATTRIBUTE) wParam;
562 return 0;
563
564 case SCREEN_GETATTRIBUTE:
565 return (LRESULT) screen->write_attribute;
566
567 case SCREEN_SETMODES:
568 (screen -> mode_flags) = ((unsigned long) wParam);
569 return (0);
570
571 case SCREEN_GETMODES:
572 return (LRESULT) screen->mode_flags;
573
574 case SCREEN_SETCOMMAND:
575 return (LRESULT)
576 ScreenSetCommand(screen, LOWORD(wParam), (COMMAND_HANDLER)lParam);
577
578 case SCREEN_GETCOMMAND:
579 return (LRESULT)
580 ScreenSetCommand(screen, LOWORD(wParam), (COMMAND_HANDLER)-1);
581
582 case SCREEN_SETBINDING:
583 return (LRESULT)
584 ScreenSetBinding(screen, LOBYTE(wParam), (WORD)lParam);
585
586 case SCREEN_GETBINDING:
587 return (LRESULT)
588 ScreenSetBinding(screen, LOBYTE(wParam), (WORD)-1);
589
590 case SCREEN_PEEKEVENT:
591 return (LRESULT)
592 ScreenPeekOrRead(screen, (int)wParam, (SCREEN_EVENT*)lParam, FALSE);
593
594 case SCREEN_READEVENT:
595 return (LRESULT)
596 ScreenPeekOrRead(screen, (int)wParam, (SCREEN_EVENT*)lParam, TRUE);
597
598 case SCREEN_WRITE:
599 return (LRESULT)WriteScreenBlock (hWnd, (LPSTR)lParam, (int)wParam);
600
601 case SCREEN_READ:
602 return (LRESULT)ReadScreen (screen, (LPSTR)lParam, (int)wParam);
603
604 case SCREEN_SETMENU:
605 Screen_SetMenu (screen, (HMENU)lParam);
606 return 0L;
607
608 case SCREEN_CLEAR:
609 Screen_Clear (screen, (int)wParam);
610 return 0L;
611
612 case WM_MOUSEACTIVATE:
613 if ((LOWORD (lParam)) == HTCLIENT)
614 return (MA_ACTIVATEANDEAT);
615 break;
616
617 case WM_LBUTTONDOWN:
618 case WM_MBUTTONDOWN:
619 case WM_RBUTTONDOWN:
620 if (IsIconic (hWnd)) goto use_default;
621 ProcessMouseButton (hWnd, uMsg, wParam, lParam, FALSE);
622 break;
623
624 case WM_LBUTTONUP:
625 case WM_MBUTTONUP:
626 case WM_RBUTTONUP:
627 if (IsIconic (hWnd)) goto use_default;
628 ProcessMouseButton (hWnd, uMsg, wParam, lParam, TRUE);
629 break;
630
631 case WM_COMMAND:
632 case WM_SYSCOMMAND:
633 {
634 WORD wID = LOWORD (wParam);
635 int i;
636 for (i=0; i<screen->n_commands; i++)
637 if (screen->commands[i].wID == wID)
638 {
639 LRESULT intrpt = (screen->commands[i].thunk(hWnd, wID));
640
641 if (intrpt)
642 flush_typeahead (screen);
643 return intrpt;
644 }
645 return DefWindowProc (hWnd, uMsg, wParam, lParam);
646 }
647 break;
648
649 case WM_GETMINMAXINFO:
650 {
651 LPMINMAXINFO info = ((LPMINMAXINFO) lParam);
652 GetMinMaxSizes (hWnd, &info->ptMinTrackSize, &info->ptMaxTrackSize);
653 }
654 break;
655
656 case WM_PAINT:
657 PaintScreen (hWnd);
658 break;
659
660 case WM_ERASEBKGND:
661 /* We now do this in PaintScreen as it reduces flicker after
662 resizing. */
663 break;
664
665 case WM_QUERYDRAGICON:
666 return (LRESULT) (screen->hIcon ? screen->hIcon : ghDefaultIcon);
667
668 case WM_SIZE:
669 if (wParam!=SIZE_MINIMIZED)
670 SizeScreen (hWnd, HIWORD(lParam), LOWORD(lParam));
671 break;
672
673 HANDLE_MSG (hWnd, WM_WINDOWPOSCHANGING, handle_window_pos_changing);
674
675 case WM_HSCROLL:
676 ScrollScreenHorz (hWnd, LOWORD(wParam), HIWORD(wParam));
677 break;
678
679 case WM_VSCROLL:
680 ScrollScreenVert (hWnd, LOWORD(wParam), HIWORD(wParam));
681 break;
682
683 case WM_SYSKEYDOWN:
684 case WM_KEYDOWN:
685 record_modifier_transition (wParam, lParam, 1);
686 if ((IsIconic (hWnd))
687 || (!process_keydown (hWnd, uMsg, wParam, lParam)))
688 goto use_default;
689 break;
690
691 case WM_SYSKEYUP:
692 case WM_KEYUP:
693 record_modifier_transition (wParam, lParam, 0);
694 goto use_default;
695
696 case WM_SYSCHAR:
697 case WM_CHAR:
698 if (IsIconic (hWnd)) goto use_default;
699 process_character (hWnd, uMsg, wParam, lParam);
700 break;
701
702 case WM_NCACTIVATE:
703 /* Windows doesn't send us focus messages when putting up and
704 taking down a system popup dialog as for Ctrl-Alt-Del on
705 Windows 95. The only indication we get that something
706 happened is receiving this message afterwards. So this is a
707 good time to reset our keyboard modifiers' state. */
708 reset_modifiers ();
709 goto use_default;
710
711 case WM_INPUTLANGCHANGE:
712 /* Clear dead keys in the keyboard state; for simplicity only
713 preserve modifier key states. */
714 {
715 BYTE keystate [256];
716 GetKeyboardState (keystate);
717 {
718 unsigned int i;
719 for (i = 0; (i < 256); i += 1)
720 switch (i)
721 {
722 case VK_SHIFT:
723 case VK_LSHIFT:
724 case VK_RSHIFT:
725 case VK_CAPITAL:
726 case VK_NUMLOCK:
727 case VK_SCROLL:
728 case VK_CONTROL:
729 case VK_LCONTROL:
730 case VK_RCONTROL:
731 case VK_MENU:
732 case VK_LMENU:
733 case VK_RMENU:
734 case VK_LWIN:
735 case VK_RWIN:
736 (keystate[i]) = 0;
737 break;
738 }
739 }
740 SetKeyboardState (keystate);
741 }
742 goto use_default;
743
744 case WM_SETFOCUS:
745 SetScreenFocus (hWnd);
746 reset_modifiers ();
747 process_focus_message (hWnd, 1);
748 goto use_default;
749
750 case WM_KILLFOCUS:
751 KillScreenFocus (hWnd);
752 process_focus_message (hWnd, 0);
753 goto use_default;
754
755 case WM_SHOWWINDOW:
756 process_show_message (hWnd, ((int) wParam));
757 goto use_default;
758
759 case WM_DESTROY:
760 DestroyScreenInfo (hWnd);
761 break;
762
763 case WM_CATATONIC:
764 {
765 extern void catatonia_trigger (void);
766 catatonia_trigger ();
767 }
768 break;
769
770 case WM_CLOSE:
771 {
772 extern HANDLE master_tty_window;
773
774 if (!(screen->mode_flags & SCREEN_EVENT_TYPE_CLOSE))
775 {
776 if (IDOK !=
777 MessageBox (hWnd,
778 hWnd==(HWND)master_tty_window
779 ? ("Closing this window will terminate Scheme.\n"
780 "Changes to Edwin buffers might be lost.\n"
781 "\n"
782 "Really Exit Scheme?")
783 : "OK to close this window?",
784 "MIT/GNU Scheme",
785 (MB_ICONQUESTION | MB_OKCANCEL)))
786 break;
787 }
788 else
789 {
790 ProcessCloseMessage (screen);
791 break;
792 }
793
794 if (hWnd == ((HWND) master_tty_window))
795 termination_normal (0);
796 goto use_default;
797 }
798
799 #ifdef USE_WM_TIMER
800 case WM_TIMER:
801 {
802 extern void TimerProc (HWND, UINT, UINT, DWORD);
803 TimerProc (hWnd, uMsg, wParam, lParam);
804 }
805 break;
806 #endif /* USE_WM_TIMER */
807
808 case WM_HOTKEY:
809 {
810 extern int signal_keyboard_character_interrupt (int);
811 signal_keyboard_character_interrupt (-2);
812 }
813
814 use_default:
815 default:
816 return (DefWindowProc (hWnd, uMsg, wParam, lParam));
817 }
818 return (0L);
819 }
820
821 static VOID
ClearScreen_internal(SCREEN screen)822 ClearScreen_internal (SCREEN screen)
823 {
824 screen->row = 0;
825 screen->column = 0;
826 _fmemset (screen->chars, ' ', MAXROWS * MAXCOLS);
827 _fmemset (screen->attrs, screen->write_attribute,
828 MAXROWS * MAXCOLS * sizeof(SCREEN_ATTRIBUTE));
829 }
830
831 /* LRESULT CreateScreenInfo (HWND hWnd)
832
833 Description:
834 Creates the tty information structure and sets
835 menu option availability. Returns -1 if unsuccessful.
836
837 Parameters:
838 HWND hWnd
839 */
840
841 static LRESULT
CreateScreenInfo(HWND hWnd)842 CreateScreenInfo (HWND hWnd)
843 {
844 HMENU hMenu;
845 SCREEN screen;
846
847 if (NULL == (screen =
848 (SCREEN) LocalAlloc (LPTR, sizeof(SCREEN_STRUCT) )))
849 return (LRESULT) -1;
850
851 screen->hWnd = hWnd;
852 screen->hIcon =
853 LoadIcon ((HINSTANCE) GetWindowLong(hWnd,GWL_HINSTANCE), DEFAULT_ICON);
854 screen->chars = NULL;
855 screen->attrs = NULL;
856 screen->write_attribute = 0;
857 screen->cursor_visible = TRUE;
858 screen->has_focus = TRUE;
859 #if 0
860 screen->mode_flags = (SCREEN_EVENT_TYPE_MASK
861 #endif
862 screen->mode_flags = (SCREEN_EVENT_TYPE_KEY
863 | SCREEN_MODE_AUTOWRAP
864 | SCREEN_MODE_ECHO
865 #if 0
866 | SCREEN_MODE_CR_NEWLINES
867 #endif
868 | SCREEN_MODE_LINE_INPUT
869 | SCREEN_MODE_PROCESS_OUTPUT
870 | SCREEN_MODE_EAGER_UPDATE
871 | SCREEN_MODE_NEWLINE_CRS);
872 screen->xSize = 0;
873 screen->ySize = 0;
874 screen->xScroll = 0;
875 screen->yScroll = 0;
876 screen->xOffset = 0;
877 screen->yOffset = 0;
878 screen->hFont = NULL;
879 if (! (init_color ("MITSCHEME_FOREGROUND", hWnd, &screen->rgbFGColour)))
880 screen->rgbFGColour = GetSysColor (COLOR_WINDOWTEXT);
881 if (! (init_color ("MITSCHEME_BACKGROUND", hWnd, &screen->rgbBGColour)))
882 screen->rgbBGColour = GetSysColor (COLOR_WINDOW);
883 screen->width = 0;
884 screen->height = 0;
885 screen->scroll_lines = 1;
886
887 screen->chars = xmalloc (MAXROWS * MAXCOLS);
888 screen->attrs = xmalloc (MAXROWS * MAXCOLS * sizeof(SCREEN_ATTRIBUTE));
889
890 /* clear screen space */
891 ClearScreen_internal (screen);
892
893 /* setup default font information */
894 screen->lfFont = lfDefaultLogFont;
895
896 /* set handle before any further message processing. */
897 SETSCREEN (hWnd, screen);
898 RegisterScreen (screen);
899
900 screen->n_commands = 0;
901 screen->n_bindings = 0;
902 /* reset the character information, etc. */
903
904 screen->bkgnd_brush = NULL;
905 ResetScreen (screen);
906
907 hMenu = GetSystemMenu (hWnd, FALSE);
908 AppendMenu (hMenu, MF_SEPARATOR, 0, 0);
909 /* AppendMenu (hMenu, MF_STRING, IDM_SETTINGS, "&Settings..."); */
910 AppendMenu (hMenu, MF_STRING, SCREEN_COMMAND_CHOOSEFONT, "&Font...");
911 AppendMenu (hMenu, MF_STRING, SCREEN_COMMAND_CHOOSEBACKCOLOR,
912 "&Background...");
913
914 SendMessage (hWnd, SCREEN_SETCOMMAND,
915 SCREEN_COMMAND_CHOOSEFONT, (LPARAM)ScreenCommand_ChooseFont);
916 /* SendMessage (hWnd, SCREEN_SETBINDING, 6, SCREEN_COMMAND_CHOOSEFONT); */
917 SendMessage (hWnd, SCREEN_SETCOMMAND, SCREEN_COMMAND_CHOOSEBACKCOLOR,
918 (LPARAM)ScreenCommand_ChooseBackColor);
919 /* SendMessage (hWnd, SCREEN_SETBINDING, 7, SCREEN_COMMAND_CHOOSEBACKCOLOR); */
920
921 screen->n_chars = 0;
922 screen->line_buffer = xmalloc (MAX_LINEINPUT + 1);
923
924 screen->n_pending = 0;
925 screen->pending = ((LPSTR) NULL);
926 return (LRESULT) TRUE;
927 }
928
929 /* VOID DestroyScreenInfo (HWND hWnd )
930
931 Description:
932 Destroys block associated with TTY window handle.
933
934 Parameters:
935 HWND hWnd
936 handle to TTY window
937 */
938
939 static VOID
DestroyScreenInfo(HWND hWnd)940 DestroyScreenInfo (HWND hWnd)
941 {
942 SCREEN screen = GETSCREEN (hWnd);
943
944 if (NULL == screen)
945 return;
946
947 /* KillScreenFocus (hWnd); */
948 UnregisterScreen (screen);
949 DeleteObject (screen->hFont);
950
951 if (screen->chars)
952 xfree (screen->chars);
953 if (screen->attrs)
954 xfree (screen->attrs);
955
956 LocalFree (screen);
957 }
958
959 /* COMMAND_HANDLER ScreenSetCommand (SCREEN, WORD cmd, COMMAND_HANDLER h) */
960
961 static COMMAND_HANDLER
ScreenSetCommand(SCREEN screen,WORD cmd,COMMAND_HANDLER thunk)962 ScreenSetCommand (SCREEN screen, WORD cmd, COMMAND_HANDLER thunk)
963 {
964 int i;
965 for (i = 0; i < screen->n_commands; i++)
966 if (screen->commands[i].wID == cmd)
967 {
968 COMMAND_HANDLER result = screen->commands[i].thunk;
969 if (thunk == 0)
970 {
971 /* remove by overwriting with last in list */
972 screen->commands[i] = screen->commands[screen->n_commands-1];
973 screen->n_commands--;
974 }
975 else if (thunk == ((COMMAND_HANDLER) -1))
976 {
977 /* just leave it alone */
978 }
979 else
980 /* redefine */
981 screen->commands[i].thunk = thunk;
982 return result;
983 }
984
985 /* didnt find it */
986 if ((thunk == 0) || (thunk == ((COMMAND_HANDLER) -1)))
987 return 0;
988 /* add new command */
989 if (screen->n_commands == MAX_COMMANDS)
990 return ((COMMAND_HANDLER) - 1);
991
992 screen->commands[screen->n_commands].wID = cmd;
993 screen->commands[screen->n_commands].thunk = thunk;
994 screen->n_commands++;
995
996 return 0;
997 }
998
999 /* WORD ScreenSetBinding (SCREEN, char key, WORD command) */
1000
1001 static WORD
ScreenSetBinding(SCREEN screen,char key,WORD command)1002 ScreenSetBinding (SCREEN screen, char key, WORD command)
1003 {
1004 int i;
1005 for (i=0; i < screen->n_bindings; i++)
1006 if (screen->bindings[i].key == key)
1007 {
1008 WORD result = screen->bindings[i].command;
1009 if (command == 0)
1010 {
1011 /* remove by blatting with last in list */
1012 screen->bindings[i] = screen->bindings[screen->n_bindings-1];
1013 screen->n_bindings--;
1014 }
1015 else if (command == ((WORD) -1))
1016 {
1017 /* let it be */
1018 }
1019 else
1020 /* redefine */
1021 screen->bindings[i].command = command;
1022 return result;
1023 }
1024
1025 /* no existing binding for key */
1026 if ((command == 0) || (command == ((WORD) -1)))
1027 return 0;
1028 /* add new binding */
1029 if (screen->n_bindings == MAX_BINDINGS)
1030 return ((WORD) - 1);
1031
1032 screen->bindings[screen->n_bindings].key = key;
1033 screen->bindings[screen->n_bindings].command = command;
1034 screen->n_bindings++;
1035
1036 return 0;
1037 }
1038
1039 /* Standard commands */
1040
1041 LRESULT
ScreenCommand_ChooseFont(HWND hWnd,WORD command)1042 ScreenCommand_ChooseFont (HWND hWnd, WORD command)
1043 {
1044 SCREEN screen = GETSCREEN (hWnd);
1045 if (screen == 0)
1046 return 1L;
1047 SelectScreenFont (screen, hWnd);
1048 return 0L;
1049 }
1050
1051 LRESULT
ScreenCommand_ChooseBackColor(HWND hWnd,WORD command)1052 ScreenCommand_ChooseBackColor (HWND hWnd, WORD command)
1053 {
1054 SCREEN screen = GETSCREEN (hWnd);
1055 if (screen == 0)
1056 return 1L;
1057 SelectScreenBackColor (screen, hWnd);
1058 return 0L;
1059 }
1060
1061 VOID
Screen_SetMenu(SCREEN screen,HMENU hMenu)1062 Screen_SetMenu (SCREEN screen, HMENU hMenu)
1063 {
1064 HMENU hOld = GetMenu (screen->hWnd);
1065 SetMenu (screen->hWnd, hMenu);
1066 if (hOld)
1067 DestroyMenu (hOld);
1068 }
1069
1070 /* BOOL AdjustedSize
1071 make sure that proposed width & height of screen are ok.
1072 return TRUE if adjusted, FALSE if OK. */
1073 static BOOL
AdjustedSize(SCREEN screen,int * width,int * height)1074 AdjustedSize (SCREEN screen, int *width, int *height)
1075 {
1076 POINT minsz, maxsz;
1077 GetMinMaxSizes (screen->hWnd, &minsz, &maxsz);
1078 if (*width<minsz.x || *width>maxsz.x || *height<minsz.y || *height>maxsz.y)
1079 {
1080 *width = min (maxsz.x, max(minsz.x, *width));
1081 *height = min (maxsz.y, max(minsz.y, *height));
1082 return (TRUE);
1083 }
1084 return (FALSE);
1085 }
1086
1087 /* BOOL ResetScreen (SCREEN screen)
1088 Description:
1089 Resets the SCREEN character information and causes the
1090 screen to resize to update the scroll information. */
1091
1092 static BOOL
ResetScreen(SCREEN screen)1093 ResetScreen (SCREEN screen)
1094 {
1095 HWND hWnd;
1096 HDC hDC;
1097 TEXTMETRIC tm;
1098 RECT rcWindow;
1099
1100 if (NULL == screen)
1101 return FALSE;
1102
1103 hWnd = screen->hWnd;
1104
1105 if (screen->hFont)
1106 DeleteObject (screen->hFont);
1107
1108 screen->hFont = CreateFontIndirect (&screen->lfFont);
1109
1110 hDC = GetDC (hWnd);
1111 SelectObject (hDC, screen->hFont);
1112 GetTextMetrics (hDC, &tm);
1113 ReleaseDC (hWnd, hDC);
1114
1115 screen->xChar = tm.tmAveCharWidth;
1116 screen->yChar = tm.tmHeight /* + tm.tmExternalLeading */;
1117
1118 /* a slimy hack to make the caret the correct size: un- and re- focus */
1119 if (screen->cursor_visible) {
1120 KillScreenFocus (hWnd);
1121 SetScreenFocus (hWnd);
1122 }
1123
1124 if (screen->bkgnd_brush != NULL)
1125 DeleteObject (screen->bkgnd_brush);
1126 screen->bkgnd_brush = CreateSolidBrush (screen->rgbBGColour);
1127
1128 /* a slimy hack to force the scroll position, region to */
1129 /* be recalculated based on the new character sizes ???? */
1130
1131 /* Veto screens that are too small or too large */
1132 {
1133 int width, height;
1134 GetWindowRect (hWnd, &rcWindow);
1135 width = (rcWindow.right - rcWindow.left - (screen_x_extra (screen)));
1136 height = (rcWindow.bottom - rcWindow.top - (screen_y_extra (screen)));
1137 if (AdjustedSize (screen, &width, &height))
1138 MoveWindow (hWnd, rcWindow.left, rcWindow.top, width, height, TRUE);
1139 else
1140 SendMessage (hWnd, WM_SIZE, SIZENORMAL,
1141 ((LPARAM) (MAKELONG (width,height))));
1142 }
1143 return TRUE;
1144 }
1145
1146 static VOID
Do_PaintScreen(HWND hWnd,SCREEN screen,HDC hDC,PAINTSTRUCT * ps)1147 Do_PaintScreen (HWND hWnd, SCREEN screen, HDC hDC, PAINTSTRUCT * ps)
1148 {
1149 RECT rect;
1150
1151 int nRow, nCol, nEndRow, nEndCol, nCount;
1152 int nHorzPos, nVertPos, bias;
1153 HFONT hOldFont;
1154
1155 hOldFont = SelectObject (hDC, screen->hFont);
1156 rect = ps->rcPaint;
1157
1158 { /* paint the background on the area surrounding the character grid */
1159 /* left strip */
1160 if (rect.left < - screen->xOffset) {
1161 RECT r = rect;
1162 r.right = -screen->xOffset;
1163 FillRect (hDC, &r, screen->bkgnd_brush);
1164 }
1165 /* right strip */
1166 if (rect.right > (screen->width * screen->xChar + screen->xOffset)) {
1167 RECT r = rect;
1168 r.left = (screen->width * screen->xChar + screen->xOffset);
1169 FillRect (hDC, &r, screen->bkgnd_brush);
1170 }
1171 /* top strip */
1172 if (rect.top < - screen->yOffset) {
1173 RECT r = rect;
1174 r.bottom = - screen->yOffset;
1175 FillRect (hDC, &r, screen->bkgnd_brush);
1176 }
1177 /* bottom strip */
1178 if (rect.bottom > (screen->height * screen->yChar + screen->yOffset)) {
1179 RECT r = rect;
1180 r.top = (screen->height * screen->yChar + screen->yOffset);
1181 FillRect (hDC, &r, screen->bkgnd_brush);
1182 }
1183 }
1184
1185 nRow =
1186 min (screen->height - 1,
1187 max (0, (rect.top + screen->yOffset) / screen->yChar));
1188 nEndRow =
1189 min (screen->height - 1,
1190 max (0, (rect.bottom + screen->yOffset - 1) / screen->yChar));
1191 nCol =
1192 min (screen->width - 1,
1193 max (0, (rect.left + screen->xOffset) / screen->xChar));
1194 nEndCol =
1195 min (screen->width - 1,
1196 max (0, (rect.right + screen->xOffset - 1) / screen->xChar));
1197 nCount = ((nEndCol - nCol) + 1);
1198 SetBkMode (hDC, OPAQUE);
1199 SetTextColor (hDC, screen->rgbFGColour);
1200 SetBkColor (hDC, screen->rgbBGColour);
1201
1202 for (bias = ((nRow * MAXCOLS) + nCol),
1203 nVertPos = ((nRow * screen->yChar) - screen->yOffset);
1204 nRow <= nEndRow;
1205 nRow++, bias += MAXCOLS, nVertPos += screen->yChar)
1206 {
1207 int pos = 0;
1208 while (pos < nCount)
1209 {
1210 /* find consistent run of attributes */
1211 SCREEN_ATTRIBUTE *attribp = &screen->attrs[bias + pos];
1212 SCREEN_ATTRIBUTE attrib = *attribp;
1213 int nposn = (pos + 1);
1214 int run_length;
1215
1216 while ((nposn < nCount) && (*++attribp == attrib))
1217 nposn++;
1218
1219 run_length = (nposn - pos);
1220 nHorzPos = (((nCol + pos) * screen->xChar) - screen->xOffset);
1221 rect.top = nVertPos;
1222 rect.bottom = nVertPos + screen->yChar;
1223 rect.left = nHorzPos;
1224 rect.right = nHorzPos + (screen->xChar * run_length);
1225 if (attrib&1)
1226 {
1227 SetTextColor (hDC, screen->rgbBGColour);
1228 SetBkColor (hDC, screen->rgbFGColour);
1229 }
1230 ExtTextOut (hDC, nHorzPos, nVertPos, (ETO_OPAQUE | ETO_CLIPPED),
1231 &rect, &screen->chars[bias + pos],
1232 run_length, NULL);
1233 #if 0
1234 if (attrib&2) /* Bolden by horizontal 1-pixel smear */
1235 ExtTextOut (hDC, nHorzPos+1, nVertPos, (ETO_CLIPPED),
1236 &rect, &screen->chars[bias + pos],
1237 run_length, NULL);
1238 #endif
1239 if (attrib&1)
1240 {
1241 SetTextColor (hDC, screen->rgbFGColour);
1242 SetBkColor (hDC, screen->rgbBGColour);
1243 }
1244 pos = nposn;
1245 }
1246 }
1247 SelectObject (hDC, hOldFont);
1248 }
1249
1250 /* VOID PaintScreen (HWND hWnd )
1251
1252 Description:
1253 Paints the rectangle determined by the paint struct of
1254 the DC.
1255
1256 Parameters:
1257 HWND hWnd
1258 handle to TTY window (as always)
1259 */
1260
1261 static VOID
PaintScreen(HWND hWnd)1262 PaintScreen (HWND hWnd)
1263 {
1264 SCREEN screen = GETSCREEN (hWnd);
1265 HDC hDC;
1266 PAINTSTRUCT ps;
1267
1268 if (NULL == screen)
1269 return;
1270
1271 hDC = BeginPaint (hWnd, &ps);
1272 if (IsIconic (hWnd)) {
1273 DefWindowProc (hWnd, WM_ICONERASEBKGND, (WPARAM) hDC, 0L);
1274 DrawIcon (hDC, 0, 0, screen->hIcon ? screen->hIcon : ghDefaultIcon);
1275 } else {
1276 Do_PaintScreen (hWnd, screen, hDC, &ps);
1277 }
1278 EndPaint (hWnd, &ps);
1279 MoveScreenCursor (screen);
1280 }
1281
1282 #if 0
1283 static VOID
1284 EraseScreen (HWND hWnd, HDC hDC)
1285 {
1286 SCREEN screen = GETSCREEN (hWnd);
1287 RECT rect;
1288
1289 if (NULL == screen)
1290 return;
1291
1292 if (! (IsIconic (hWnd))) {
1293 GetClientRect (hWnd, &rect);
1294 FillRect (hDC, &rect, screen->bkgnd_brush);
1295 }
1296 }
1297 #endif
1298
1299 static VOID _fastcall
SetCells(SCREEN screen,int row,int col,int count,char ch,SCREEN_ATTRIBUTE attr)1300 SetCells (SCREEN screen, int row, int col, int count,
1301 char ch, SCREEN_ATTRIBUTE attr)
1302 {
1303 int address1 = row * MAXCOLS + col;
1304 int address2 = address1 + count;
1305 int i;
1306 for (i = address1; i<address2; i++)
1307 {
1308 screen->chars[i] = ch;
1309 screen->attrs[i] = attr;
1310 }
1311 }
1312
1313 static VOID
ScrollScreenBufferUp(SCREEN screen,int count)1314 ScrollScreenBufferUp (SCREEN screen, int count)
1315 {
1316 /* int total_rows = MAXROWS; */
1317 int total_rows = screen->height;
1318 int rows_copied = max (total_rows - count, 0);
1319 count = min (count, total_rows);
1320
1321 _fmemmove ((LPSTR) (screen->chars),
1322 (LPSTR) (screen->chars + count * MAXCOLS),
1323 rows_copied * MAXCOLS);
1324 _fmemmove ((LPSTR) (screen->attrs),
1325 (LPSTR) (screen->attrs + count * MAXCOLS),
1326 rows_copied * MAXCOLS);
1327 _fmemset ((LPSTR)(screen->chars + rows_copied * MAXCOLS),
1328 ' ', count*MAXCOLS);
1329 _fmemset ((LPSTR)(screen->attrs + rows_copied * MAXCOLS),
1330 screen->write_attribute, count*MAXCOLS);
1331 }
1332
1333 /* BOOL SizeScreen (HWND hWnd, WORD wVertSize, WORD wHorzSize )
1334 Description:
1335 Set SCREEN size. */
1336
1337 static BOOL
SizeScreen(HWND hWnd,WORD wVertSize,WORD wHorzSize)1338 SizeScreen (HWND hWnd, WORD wVertSize, WORD wHorzSize )
1339 {
1340 SCREEN screen = GETSCREEN (hWnd);
1341 int old_width, old_height;
1342 unsigned int new_width;
1343 unsigned int new_height;
1344
1345 if (NULL == screen)
1346 return FALSE;
1347
1348 if (IsIconic(hWnd)) {
1349 /* This entire section is a crock to ensure a reasonably sized window
1350 when Scheme is started minimized.
1351
1352 Since we protect this procedure against minimizing in the WndProc, we
1353 can get here only when window is launched in a minimized state. We
1354 get here because of the SendMessage in ScreenReset. Our duty is to
1355 fake a normal position and size.
1356 Luckily none of the scrolling business happens because all the cursor
1357 etc are at zero. (Hopefully it would be clipped).
1358 */
1359 WINDOWPLACEMENT pl;
1360 int width, height, params[4] = {-1, -1, 0, 0}; /* left,top,width,height*/
1361 init_geometry ("MITSCHEME_GEOMETRY", ¶ms[0]);
1362 width = min (params[2] ? params[2] : 80*screen->xChar,
1363 GetSystemMetrics(SM_CXSCREEN));
1364 height = min (params[3] ? params[3] : 40*screen->yChar,
1365 GetSystemMetrics(SM_CYSCREEN));
1366 pl.length = (sizeof (pl));
1367 GetWindowPlacement (hWnd, &pl);
1368 AdjustedSize (screen, &width, &height);
1369 pl.rcNormalPosition.left = params[0]==-1 ? 0 : params[0];
1370 pl.rcNormalPosition.top = params[1]==-1 ? 0 : params[1];
1371 pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + height;
1372 pl.rcNormalPosition.right = pl.rcNormalPosition.left + width;
1373 SetWindowPlacement (hWnd, &pl);
1374 wVertSize = height;
1375 wHorzSize = width;
1376 }
1377
1378 /* if (GetMenu(hWnd)) wVertSize -= GetSystemMetrics(SM_CYMENU); */
1379 old_width = screen->width;
1380 old_height = screen->height;
1381
1382 new_width =
1383 max (1, min ((wHorzSize + screen->xOffset) / screen->xChar, MAXCOLS));
1384 new_height =
1385 max (1, min ((wVertSize + screen->yOffset) / screen->yChar, MAXROWS));
1386
1387 if (new_width > old_width)
1388 {
1389 /* Clear out revealed character cells */
1390 int row, rows = min (old_height, new_height);
1391 for (row = 0; row < rows; row++)
1392 SetCells (screen, row, old_width, new_width-old_width, ' ', 0);
1393 }
1394
1395 if (new_height > old_height)
1396 {
1397 /* Clear out revealed character cells */
1398 int row;
1399 for (row = old_height; row < new_height; row++)
1400 SetCells (screen, row, 0, new_width, ' ', 0);
1401 }
1402 else if (screen->row >= new_height)
1403 {
1404 ScrollScreenBufferUp (screen, ((screen->row - new_height) + 1));
1405 screen->row = (new_height - 1);
1406 }
1407
1408 screen->width = new_width;
1409 screen->height = new_height;
1410
1411 /* scroll window to fit in cursor */
1412 if (screen->column >= new_width)
1413 {
1414 screen->column = 0;
1415 screen->row += 1;
1416 }
1417 if (screen->row >= new_height)
1418 {
1419 ScrollScreenBufferUp (screen, 1);
1420 screen->row = (new_height - 1);
1421 }
1422 MoveScreenCursor (screen);
1423
1424 screen->ySize = (int) wVertSize;
1425 screen->xSize = (int) wHorzSize;
1426 screen->yScroll = 0;
1427 screen->xScroll = 0;
1428
1429 if ((screen->mode_flags & SCREEN_MODE_EDWIN) == 0)
1430 screen->scroll_lines = (COMPUTE_SCROLL_LINES (new_height));
1431 else if (screen->mode_flags & SCREEN_EVENT_TYPE_RESIZE)
1432 {
1433 /* queue RESIZE event */
1434 SCREEN_EVENT * event
1435 = (allocate_event (screen, SCREEN_EVENT_TYPE_RESIZE));
1436 if (event)
1437 {
1438 event->event.resize.rows = new_height;
1439 event->event.resize.columns = new_width;
1440 }
1441 }
1442 else
1443 {
1444 /* Queue a character based resize event */
1445 SCREEN_EVENT * event = (allocate_event (screen, SCREEN_EVENT_TYPE_KEY));
1446 if (event)
1447 {
1448 event->event.key.repeat_count = 1;
1449 event->event.key.virtual_keycode = 0;
1450 event->event.key.virtual_scancode = 0;
1451 event->event.key.ch = SCREEN_EDWIN_RESIZE_COMMAND;
1452 event->event.key.control_key_state = 0;
1453 }
1454 }
1455 /* Cause screen to be redrawn, but if we are under Edwin, don't
1456 bother as Edwin has to calculate the redisplay anyway. Well, we
1457 do bother otherwise we would have to clear the part of the
1458 screen that is not in a character box. */
1459 #if 0
1460 if ((screen->mode_flags & SCREEN_MODE_EDWIN) == 0)
1461 #endif
1462 {
1463 InvalidateRect (hWnd, NULL, TRUE);
1464 }
1465
1466 return TRUE;
1467
1468 }
1469
1470 static BOOL
handle_window_pos_changing(HWND hwnd,LPWINDOWPOS wp)1471 handle_window_pos_changing (HWND hwnd, LPWINDOWPOS wp)
1472 {
1473 BOOL result = (FORWARD_WM_WINDOWPOSCHANGING (hwnd, wp, DefWindowProc));
1474 if ((wp -> flags) & SWP_NOSIZE)
1475 return (result);
1476 {
1477 SCREEN screen = (GETSCREEN (hwnd));
1478 (wp -> cx)
1479 = (char_to_pixel_width (screen,
1480 (pixel_to_char_width (screen, (wp -> cx)))));
1481 (wp -> cy)
1482 = (char_to_pixel_height (screen,
1483 (pixel_to_char_height (screen, (wp -> cy)))));
1484 }
1485 return (0);
1486 }
1487
1488 void
screen_char_dimensions(HWND hwnd,int * xchar,int * ychar)1489 screen_char_dimensions (HWND hwnd, int * xchar, int * ychar)
1490 {
1491 SCREEN screen = (GETSCREEN (hwnd));
1492 (*xchar) = (screen -> xChar);
1493 (*ychar) = (screen -> yChar);
1494 }
1495
1496 /* BOOL ScrollScreenVert (HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
1497
1498 Description:
1499 Scrolls TTY window vertically.
1500
1501 Parameters:
1502 HWND hWnd
1503 handle to TTY window
1504
1505 WORD wScrollCmd
1506 type of scrolling we're doing
1507
1508 WORD wScrollPos
1509 scroll position
1510 */
1511
1512 static BOOL
ScrollScreenVert(HWND hWnd,WORD wScrollCmd,WORD wScrollPos)1513 ScrollScreenVert (HWND hWnd, WORD wScrollCmd, WORD wScrollPos)
1514 {
1515 int nScrollAmt;
1516 SCREEN screen = GETSCREEN (hWnd);
1517
1518 if (NULL == screen)
1519 return FALSE;
1520
1521 switch (wScrollCmd)
1522 {
1523 case SB_TOP:
1524 nScrollAmt = -screen->yOffset;
1525 break;
1526
1527 case SB_BOTTOM:
1528 nScrollAmt = screen->yScroll - screen->yOffset;
1529 break;
1530
1531 case SB_PAGEUP:
1532 nScrollAmt = -screen->ySize;
1533 break;
1534
1535 case SB_PAGEDOWN:
1536 nScrollAmt = screen->ySize;
1537 break;
1538
1539 case SB_LINEUP:
1540 nScrollAmt = -screen->yChar;
1541 break;
1542
1543 case SB_LINEDOWN:
1544 nScrollAmt = screen->yChar;
1545 break;
1546
1547 case SB_THUMBPOSITION:
1548 nScrollAmt = wScrollPos - screen->yOffset;
1549 break;
1550
1551 default:
1552 return FALSE;
1553 }
1554 if ((screen->yOffset + nScrollAmt) > screen->yScroll)
1555 nScrollAmt = screen->yScroll - screen->yOffset;
1556 if ((screen->yOffset + nScrollAmt) < 0)
1557 nScrollAmt = -screen->yOffset;
1558 ScrollWindow (hWnd, 0, -nScrollAmt, NULL, NULL);
1559 screen->yOffset = screen->yOffset + nScrollAmt;
1560 SetScrollPos (hWnd, SB_VERT, screen->yOffset, TRUE);
1561
1562 return TRUE;
1563 }
1564
1565 /* BOOL ScrollScreenHorz (HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
1566
1567 Description:
1568 Scrolls TTY window horizontally.
1569
1570 Parameters:
1571 HWND hWnd
1572 handle to TTY window
1573
1574 WORD wScrollCmd
1575 type of scrolling we're doing
1576
1577 WORD wScrollPos
1578 scroll position
1579 */
1580
1581 static BOOL
ScrollScreenHorz(HWND hWnd,WORD wScrollCmd,WORD wScrollPos)1582 ScrollScreenHorz (HWND hWnd, WORD wScrollCmd, WORD wScrollPos)
1583 {
1584 int nScrollAmt;
1585 SCREEN screen = GETSCREEN (hWnd);
1586
1587 if (NULL == screen)
1588 return FALSE;
1589
1590 switch (wScrollCmd)
1591 {
1592 case SB_TOP:
1593 nScrollAmt = -screen->xOffset;
1594 break;
1595
1596 case SB_BOTTOM:
1597 nScrollAmt = screen->xScroll - screen->xOffset;
1598 break;
1599
1600 case SB_PAGEUP:
1601 nScrollAmt = -screen->xSize;
1602 break;
1603
1604 case SB_PAGEDOWN:
1605 nScrollAmt = screen->xSize;
1606 break;
1607
1608 case SB_LINEUP:
1609 nScrollAmt = -screen->xChar;
1610 break;
1611
1612 case SB_LINEDOWN:
1613 nScrollAmt = screen->xChar;
1614 break;
1615
1616 case SB_THUMBPOSITION:
1617 nScrollAmt = wScrollPos - screen->xOffset;
1618 break;
1619
1620 default:
1621 return FALSE;
1622 }
1623 if ((screen->xOffset + nScrollAmt) > screen->xScroll)
1624 nScrollAmt = screen->xScroll - screen->xOffset;
1625 if ((screen->xOffset + nScrollAmt) < 0)
1626 nScrollAmt = -screen->xOffset;
1627 ScrollWindow (hWnd, -nScrollAmt, 0, NULL, NULL);
1628 screen->xOffset = screen->xOffset + nScrollAmt;
1629 SetScrollPos (hWnd, SB_HORZ, screen->xOffset, TRUE);
1630
1631 return TRUE;
1632 }
1633
1634 static SCREEN screen_focus = NULL;
1635
1636 HWND
ScreenCurrentFocus(void)1637 ScreenCurrentFocus (void)
1638 {
1639 SCREEN *link;
1640 HWND hWnd;
1641
1642 if (screen_focus)
1643 return screen_focus->hWnd;
1644 hWnd = GetFocus();
1645 if (NULL == hWnd)
1646 return NULL;
1647 link = head_to_registered_screen (hWnd);
1648 if (NULL == link)
1649 return NULL;
1650 screen_focus = (*link);
1651 return hWnd;
1652 }
1653
1654 /* BOOL SetScreenFocus (HWND hWnd )
1655
1656 Description:
1657 Sets the focus to the TTY window also creates caret.
1658
1659 Parameters:
1660 HWND hWnd
1661 handle to TTY window
1662 */
1663
1664 static BOOL
SetScreenFocus(HWND hWnd)1665 SetScreenFocus (HWND hWnd)
1666 {
1667 SCREEN screen = GETSCREEN (hWnd);
1668
1669 if (NULL == screen) return FALSE;
1670
1671 screen_focus = screen;
1672 CreateCaret (hWnd, NULL, screen->xChar, screen->yChar);
1673 if (screen->cursor_visible)
1674 ShowCaret (hWnd);
1675
1676 MoveScreenCursor (screen);
1677 return TRUE;
1678 }
1679
1680 /* BOOL KillScreenFocus (HWND hWnd )
1681
1682 Description:
1683 Kills TTY focus and destroys the caret.
1684
1685 Parameters:
1686 HWND hWnd
1687 handle to TTY window
1688 */
1689
1690 BOOL
KillScreenFocus(HWND hWnd)1691 KillScreenFocus (HWND hWnd )
1692 {
1693 SCREEN screen = GETSCREEN (hWnd);
1694
1695 if (NULL == screen) return FALSE;
1696
1697 screen_focus = NULL;
1698 #if 0
1699 if (screen->cursor_visible)
1700 HideCaret (hWnd);
1701 #endif
1702 DestroyCaret ();
1703 return TRUE;
1704 }
1705
1706 /* VOID MoveScreenCursor (SCREEN screen)
1707
1708 Description:
1709 Moves caret to current position.
1710 */
1711
1712 static VOID
MoveScreenCursor(SCREEN screen)1713 MoveScreenCursor (SCREEN screen)
1714 {
1715 ScreenCurrentFocus();
1716 if (screen == screen_focus)
1717 #if 0
1718 SetCaretPos (screen->column * screen->xChar - screen->xOffset
1719 /* This ensures visiblity at the far left: */
1720 + ((screen->column == screen->width) ? -2 : 0),
1721 screen->row * screen->yChar - screen->yOffset);
1722 #endif
1723 SetCaretPos (/* This ensures visiblity at the far left: */
1724 (screen->column >= screen->width)
1725 ? (screen->width * screen->xChar - screen->xOffset - 2)
1726 : (screen->column * screen->xChar - screen->xOffset),
1727 screen->row * screen->yChar - screen->yOffset);
1728 }
1729
1730 BOOL
Screen_SetPosition(SCREEN screen,int row,int column)1731 Screen_SetPosition (SCREEN screen, int row, int column)
1732 {
1733 if ((row < 0) || (row >= screen->height))
1734 return (FALSE);
1735 #if 0
1736 if ((column < 0) || (column > screen->width)) /* may be == */
1737 #endif
1738 if ((column < 0) || (column >= MAXCOLS))
1739 return (FALSE);
1740 screen->row = row;
1741 screen->column = column;
1742 MoveScreenCursor (screen);
1743 return TRUE;
1744 }
1745
1746 /* UINT ScreenPeekOrRead (SCREEN, n_to_read, SCREEN_EVENT* buffer, BOOL remove)
1747
1748 Copy events into buffer. Return number of events processed.
1749 If remove=TRUE, remove events from screen queue (i.e. Read)
1750 If remove=FALSE, leave events in queue (i.e. Peek)
1751 If buffer=NULL, process without copying.
1752 If n_to_read<0, process all events.
1753 . n_to_read=-1, buffer=NULL, remove=FALSE -> count of pending events
1754 . n_to_read=-1, buffer=NULL, remove=TRUE -> flush queue
1755 . n_to_read=n, buffer=NULL, remove=TRUE -> discard n events
1756
1757 NB: if (n_to_read < 0), buffer is ignored.
1758 */
1759
1760 UINT
ScreenPeekOrRead(SCREEN screen,int n_to_read,SCREEN_EVENT * buffer,BOOL remove)1761 ScreenPeekOrRead (SCREEN screen, int n_to_read, SCREEN_EVENT * buffer,
1762 BOOL remove)
1763 {
1764 SCREEN_EVENT * scan_buffer = ((n_to_read < 0) ? 0 : buffer);
1765 SCREEN_EVENT event;
1766 int n_read = 0;
1767
1768 if (remove)
1769 while (((n_read < n_to_read) || (n_to_read < 0))
1770 && (read_event (screen, 0, 1, (&event))))
1771 {
1772 if (scan_buffer)
1773 (*scan_buffer++) = event;
1774 n_read += 1;
1775 }
1776 else
1777 {
1778 SCREEN_EVENT_LINK * scan_queue = event_queue_head;
1779 while (((n_read < n_to_read) || (n_to_read < 0))
1780 && (scan_queue != 0))
1781 if (((scan_queue -> event) . handle) == (screen -> hWnd))
1782 {
1783 if (scan_buffer)
1784 (*scan_buffer++) = (scan_queue -> event);
1785 scan_queue = (scan_queue -> next);
1786 n_read += 1;
1787 }
1788 }
1789 return (n_read);
1790 }
1791
1792 void
flush_typeahead(SCREEN screen)1793 flush_typeahead (SCREEN screen)
1794 {
1795 while (read_event (screen, SCREEN_EVENT_TYPE_KEY, 1, 0))
1796 ;
1797 (screen -> n_chars) = 0;
1798 }
1799
1800 /* The following handling of the keyboard is taken with only minor
1801 changes from Emacs 20.5. */
1802
1803 #define LP_REPEAT(lparam) ((lparam) & 0x0000ffff)
1804 #define LP_SCAN_CODE(lparam) (((lparam) & 0x00ff0000) >> 16)
1805 #define LP_EXTENDED(lparam) (((lparam) & 0x01000000) != 0)
1806
1807 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
1808 between left and right keys as advertised. We test for this
1809 support dynamically, and set a flag when the support is absent. If
1810 absent, we keep track of the left and right control and alt keys
1811 ourselves. This is particularly necessary on keyboards that rely
1812 upon the AltGr key, which is represented as having the left control
1813 and right alt keys pressed. For these keyboards, we need to know
1814 when the left alt key has been pressed in addition to the AltGr key
1815 so that we can properly support M-AltGr-key sequences (such as M-@
1816 on Swedish keyboards). */
1817
1818 #define MOD_LCONTROL 0
1819 #define MOD_RCONTROL 1
1820 #define MOD_LMENU 2
1821 #define MOD_RMENU 3
1822
1823 static int modifiers [4] = { 0, 0, 0, 0 };
1824 static int record_modifiers_p;
1825
1826 static void
record_modifier_transition(WPARAM wparam,LPARAM lparam,int down_p)1827 record_modifier_transition (WPARAM wparam, LPARAM lparam, int down_p)
1828 {
1829 static int modifier_key_support_tested = 0;
1830 if (down_p && (!modifier_key_support_tested))
1831 {
1832 if (wparam == VK_CONTROL)
1833 {
1834 record_modifiers_p
1835 = (((GetKeyState (VK_LCONTROL) & 0x8000) == 0)
1836 && ((GetKeyState (VK_RCONTROL) & 0x8000) == 0));
1837 modifier_key_support_tested = 1;
1838 }
1839 else if (wparam == VK_MENU)
1840 {
1841 record_modifiers_p
1842 = (((GetKeyState (VK_LMENU) & 0x8000) == 0)
1843 && ((GetKeyState (VK_RMENU) & 0x8000) == 0));
1844 modifier_key_support_tested = 1;
1845 }
1846 }
1847 if (record_modifiers_p)
1848 {
1849 if (down_p)
1850 {
1851 /* Synchronize modifier state with what is reported with the
1852 current keystroke. Even if we cannot distinguish between
1853 left and right modifier keys, we know that, if no
1854 modifiers are set, then neither the left nor right
1855 modifier should be set. */
1856 if ((GetKeyState (VK_CONTROL) & 0x8000) == 0)
1857 {
1858 (modifiers[MOD_RCONTROL]) = 0;
1859 (modifiers[MOD_LCONTROL]) = 0;
1860 }
1861 if ((GetKeyState (VK_MENU) & 0x8000) == 0)
1862 {
1863 (modifiers[MOD_RMENU]) = 0;
1864 (modifiers[MOD_LMENU]) = 0;
1865 }
1866 }
1867 if (wparam == VK_CONTROL)
1868 (modifiers [(LP_EXTENDED (lparam)) ? MOD_RCONTROL : MOD_LCONTROL])
1869 = down_p;
1870 else if (wparam == VK_MENU)
1871 (modifiers [(LP_EXTENDED (lparam)) ? MOD_RMENU : MOD_LMENU]) = down_p;
1872 }
1873 }
1874
1875 /* We can lose focus while a modifier key has been pressed. When
1876 we regain focus, be conservative and clear all modifiers since
1877 we cannot reconstruct the left and right modifier state. */
1878
1879 static void
copy_current_state(unsigned int vk,BYTE * keystate)1880 copy_current_state (unsigned int vk, BYTE * keystate)
1881 {
1882 (keystate[vk]) = ((GetAsyncKeyState (vk) & 0x8000) >> 8);
1883 }
1884
1885 static void
reset_modifiers(void)1886 reset_modifiers (void)
1887 {
1888 if ((GetFocus ()) != 0)
1889 {
1890 if (((GetAsyncKeyState (VK_CONTROL)) & 0x08000) == 0)
1891 {
1892 /* Clear any recorded control modifier state. */
1893 (modifiers[MOD_RCONTROL]) = 0;
1894 (modifiers[MOD_LCONTROL]) = 0;
1895 }
1896 if (((GetAsyncKeyState (VK_MENU)) & 0x08000) == 0)
1897 {
1898 /* Clear any recorded alt modifier state. */
1899 (modifiers[MOD_RMENU]) = 0;
1900 (modifiers[MOD_LMENU]) = 0;
1901 }
1902 /* Update the state of all modifier keys, because modifiers used in
1903 hot-key combinations can get stuck on if Scheme loses focus as a
1904 result of a hot-key being pressed. */
1905 {
1906 BYTE keystate [256];
1907 GetKeyboardState (keystate);
1908 copy_current_state (VK_SHIFT, keystate);
1909 copy_current_state (VK_CONTROL, keystate);
1910 copy_current_state (VK_LCONTROL, keystate);
1911 copy_current_state (VK_RCONTROL, keystate);
1912 copy_current_state (VK_MENU, keystate);
1913 copy_current_state (VK_LMENU, keystate);
1914 copy_current_state (VK_RMENU, keystate);
1915 copy_current_state (VK_LWIN, keystate);
1916 copy_current_state (VK_RWIN, keystate);
1917 copy_current_state (VK_APPS, keystate);
1918 SetKeyboardState (keystate);
1919 }
1920 }
1921 }
1922
1923 static int
modifier_set_p(int vk)1924 modifier_set_p (int vk)
1925 {
1926 if (record_modifiers_p)
1927 switch (vk)
1928 {
1929 case VK_LCONTROL:
1930 return (modifiers[MOD_LCONTROL]);
1931 case VK_RCONTROL:
1932 return (modifiers[MOD_RCONTROL]);
1933 case VK_LMENU:
1934 return (modifiers[MOD_LMENU]);
1935 case VK_RMENU:
1936 return (modifiers[MOD_RMENU]);
1937 }
1938 /* For toggled modifiers, test the low-order bit; otherwise the
1939 high-order bit. */
1940 return
1941 (((GetKeyState (vk))
1942 & (((vk == VK_CAPITAL) || (vk == VK_NUMLOCK) || (vk == VK_SCROLL))
1943 ? 0x0001
1944 : 0x8000))
1945 != 0);
1946 }
1947
1948 static unsigned int
get_modifiers(void)1949 get_modifiers (void)
1950 {
1951 unsigned int mods = 0;
1952
1953 if (modifier_set_p (VK_SHIFT)) mods |= SCREEN_SHIFT_PRESSED;
1954 if (modifier_set_p (VK_CAPITAL)) mods |= SCREEN_CAPSLOCK_ON;
1955 if (modifier_set_p (VK_NUMLOCK)) mods |= SCREEN_NUMLOCK_ON;
1956 if (modifier_set_p (VK_SCROLL)) mods |= SCREEN_SCROLLLOCK_ON;
1957
1958 if (modifier_set_p (VK_RCONTROL))
1959 mods |= (SCREEN_RIGHT_CONTROL_PRESSED | SCREEN_CONTROL_PRESSED);
1960 if (modifier_set_p (VK_LMENU))
1961 mods |= (SCREEN_LEFT_ALT_PRESSED | SCREEN_ALT_PRESSED);
1962
1963 /* Slight complication to handle case where AltGr is pressed. */
1964 if ((modifier_set_p (VK_LCONTROL)) && (!modifier_set_p (VK_RMENU)))
1965 mods |= (SCREEN_LEFT_CONTROL_PRESSED | SCREEN_CONTROL_PRESSED);
1966 if ((modifier_set_p (VK_RMENU)) && (!modifier_set_p (VK_LCONTROL)))
1967 mods |= (SCREEN_RIGHT_ALT_PRESSED | SCREEN_ALT_PRESSED);
1968
1969 return (mods);
1970 }
1971
1972 static void
use_translate_message(HWND handle,UINT message,WPARAM wparam,LPARAM lparam)1973 use_translate_message (HWND handle, UINT message, WPARAM wparam, LPARAM lparam)
1974 {
1975 MSG msg;
1976 (msg . hwnd) = handle;
1977 (msg . message) = message;
1978 (msg . wParam) = wparam;
1979 (msg . lParam) = lparam;
1980 (msg . time) = (GetMessageTime ());
1981 (msg . pt . x) = 0;
1982 (msg . pt . y) = 0;
1983 TranslateMessage (&msg);
1984 }
1985
1986 static void
make_key_event(HWND handle,WPARAM wparam,LPARAM lparam,int ch)1987 make_key_event (HWND handle, WPARAM wparam, LPARAM lparam, int ch)
1988 {
1989 SCREEN screen = (GETSCREEN (handle));
1990 SCREEN_EVENT * event;
1991 unsigned int modifiers = (get_modifiers ());
1992
1993 /* Translate the Backspace key to the Delete character. */
1994 if ((ch == 0x08) && (wparam == VK_BACK))
1995 ch = ASCII_DEL;
1996
1997 /* If the unmodified key is bound to a command, send the command.
1998 Extra hair here is due to need to handle control characters. */
1999 if (((modifiers & SCREEN_ALT_PRESSED) == 0)
2000 && (((modifiers & SCREEN_CONTROL_PRESSED) == 0)
2001 || (('A' <= ch) && (ch <= 'Z'))
2002 || (('a' <= ch) && (ch <= 'z'))
2003 || (ch == '@') || (ch == '[') || (ch == '\\')
2004 || (ch == ']') || (ch == '^') || (ch == '_')))
2005 {
2006 int ch2 = ch;
2007 unsigned int i;
2008 if ((modifiers & SCREEN_CONTROL_PRESSED) != 0)
2009 {
2010 if (('a' <= ch) && (ch <= 'z'))
2011 ch2 -= ('a' - 'A');
2012 ch2 -= '@';
2013 }
2014 for (i = 0; (i < (screen -> n_bindings)); i += 1)
2015 if ((((screen -> bindings) [i]) . key) == ch2)
2016 {
2017 if (SendMessage
2018 (handle,
2019 WM_COMMAND,
2020 (MAKEWPARAM ((((screen -> bindings) [i]) . command), 0)),
2021 0))
2022 return;
2023 else
2024 break;
2025 }
2026 }
2027
2028 if ((ch == (-1)) && (((screen -> mode_flags) & SCREEN_MODE_VK_KEYS) == 0))
2029 return;
2030
2031 event = (allocate_event (screen, SCREEN_EVENT_TYPE_KEY));
2032 if (!event) return;
2033 ((event -> event.key) . repeat_count) = (LP_REPEAT (lparam));
2034 ((event -> event.key) . virtual_keycode) = wparam;
2035 ((event -> event.key) . virtual_scancode) = (LP_SCAN_CODE (lparam));
2036 ((event -> event.key) . ch) = ch;
2037 ((event -> event.key) . control_key_state) = modifiers;
2038
2039 if (win32_trace_level > 0)
2040 {
2041 fprintf (win32_trace_file, "make_key_event: ");
2042 fprintf
2043 (win32_trace_file,
2044 "handle=0x%x keycode=0x%x scancode=0x%x ch=0x%x modifiers=0x%x\n",
2045 handle, wparam, (LP_SCAN_CODE (lparam)), ch, modifiers);
2046 fflush (win32_trace_file);
2047 }
2048 }
2049
2050 /* Process WM_KEYDOWN and WM_SYSKEYDOWN. Return 1 to indicate that
2051 the key was handled, and that the message proc should return;
2052 return 0 to indicate that the default action should take place. */
2053
2054 static int
process_keydown(HWND handle,UINT message,WPARAM wparam,LPARAM lparam)2055 process_keydown (HWND handle, UINT message, WPARAM wparam, LPARAM lparam)
2056 {
2057 switch (wparam)
2058 {
2059 case VK_MENU:
2060 /* Prevent Windows from activating the menu bar if an Alt key is
2061 pressed and released by itself. */
2062 return (1);
2063
2064 case VK_LWIN:
2065 case VK_RWIN:
2066 case VK_APPS:
2067 case VK_NUMLOCK:
2068 case VK_SCROLL:
2069 case VK_CAPITAL:
2070 case VK_CONTROL:
2071 case VK_SHIFT:
2072 /* Let Windows handle the modifier keys. */
2073 use_translate_message (handle, message, wparam, lparam);
2074 return (0);
2075 }
2076
2077 /* Always let Windows handle AltGr key chords; for some reason,
2078 ToAscii doesn't always process AltGr chords correctly. */
2079 if ((modifier_set_p (VK_LCONTROL)) && (modifier_set_p (VK_RMENU)))
2080 {
2081 use_translate_message (handle, message, wparam, lparam);
2082 return (0);
2083 }
2084
2085 /* Edwin handles some of the special keys directly, so provide
2086 symbols for those keys rather than translating them. */
2087 if ((((GETSCREEN (handle)) -> mode_flags) & SCREEN_MODE_VK_KEYS)
2088 && ((wparam == VK_LEFT)
2089 || (wparam == VK_RIGHT)
2090 || (wparam == VK_UP)
2091 || (wparam == VK_DOWN)
2092 || (wparam == VK_HOME)
2093 || (wparam == VK_END)
2094 || (wparam == VK_PRIOR)
2095 || (wparam == VK_NEXT)
2096 || (wparam == VK_INSERT)
2097 || (wparam == VK_DELETE)
2098 || ((wparam >= VK_F1) && (wparam <= VK_F24))))
2099 {
2100 make_key_event (handle, wparam, lparam, (-1));
2101 return (1);
2102 }
2103
2104 /* Let TranslateMessage handle anything not involving Alt or Ctrl. */
2105 if (((get_modifiers ())
2106 & (SCREEN_ALT_PRESSED | SCREEN_CONTROL_PRESSED))
2107 == 0)
2108 {
2109 use_translate_message (handle, message, wparam, lparam);
2110 return (0);
2111 }
2112
2113 /* Otherwise, handle translation directly, as otherwise Windows
2114 will do the wrong thing. Translate the unmodified keystroke to
2115 the corresponding character(s), then add the modifiers back in. */
2116 {
2117 BYTE keystate [256];
2118 BYTE ansi_code [4];
2119 int n_chars;
2120 int i;
2121
2122 memset (keystate, 0, (sizeof (keystate)));
2123 (keystate[wparam]) = 0x80;
2124 if (modifier_set_p (VK_SHIFT))
2125 (keystate[VK_SHIFT]) = 0x80;
2126 if (modifier_set_p (VK_CAPITAL))
2127 (keystate[VK_CAPITAL]) = 0x01;
2128
2129 /* On NT, call ToUnicode instead and then convert to the current
2130 locale's default codepage. */
2131 if (NT_windows_type == wintype_nt)
2132 {
2133 WCHAR buffer [128];
2134 char code_page [20];
2135 int code_page_number;
2136
2137 n_chars
2138 = (ToUnicode (wparam, (LP_SCAN_CODE (lparam)), keystate,
2139 buffer, 128, 0));
2140 if (n_chars <= 0)
2141 return (1);
2142 GetLocaleInfo ((GetThreadLocale ()), LOCALE_IDEFAULTANSICODEPAGE,
2143 code_page, (sizeof (code_page)));
2144 code_page_number = (atoi (code_page));
2145 n_chars
2146 = (WideCharToMultiByte (code_page_number, 0, buffer, n_chars,
2147 ansi_code, (sizeof (ansi_code)), 0, 0));
2148 }
2149 else
2150 n_chars
2151 = (ToAscii (wparam, (LP_SCAN_CODE (lparam)), keystate,
2152 ((LPWORD) ansi_code), 0));
2153 for (i = 0; (i < n_chars); i += 1)
2154 make_key_event (handle, wparam, lparam, (ansi_code[i]));
2155 return (1);
2156 }
2157 }
2158
2159 static void
process_character(HWND handle,UINT message,WPARAM wparam,LPARAM lparam)2160 process_character (HWND handle, UINT message, WPARAM wparam, LPARAM lparam)
2161 {
2162 make_key_event
2163 (handle, (MapVirtualKey ((LP_SCAN_CODE (lparam)), 1)), lparam, wparam);
2164 }
2165
2166 static void
process_focus_message(HWND handle,int gained_p)2167 process_focus_message (HWND handle, int gained_p)
2168 {
2169 SCREEN screen = (GETSCREEN (handle));
2170 SCREEN_EVENT * event = (allocate_event (screen, SCREEN_EVENT_TYPE_FOCUS));
2171 if (event)
2172 (event->event.focus.gained_p) = gained_p;
2173 }
2174
2175 static void
process_show_message(HWND handle,int show_p)2176 process_show_message (HWND handle, int show_p)
2177 {
2178 SCREEN screen = (GETSCREEN (handle));
2179 SCREEN_EVENT * event
2180 = (allocate_event (screen, SCREEN_EVENT_TYPE_VISIBILITY));
2181 if (event)
2182 (event->event.visibility.show_p) = show_p;
2183 }
2184
2185 static VOID
ProcessCloseMessage(SCREEN screen)2186 ProcessCloseMessage (SCREEN screen)
2187 {
2188 (void) allocate_event (screen, SCREEN_EVENT_TYPE_CLOSE);
2189 }
2190
2191 static VOID
ProcessMouseButton(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL up)2192 ProcessMouseButton (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
2193 BOOL up)
2194 {
2195 SCREEN screen = GETSCREEN (hWnd);
2196 SCREEN_EVENT * event;
2197 unsigned int control = 0;
2198 unsigned int button = 0;
2199
2200 if (NULL == screen)
2201 return;
2202
2203 if (uMsg & MK_CONTROL)
2204 control |= SCREEN_CONTROL_PRESSED;
2205 if (uMsg & MK_SHIFT)
2206 control |= SCREEN_SHIFT_PRESSED;
2207
2208 switch (uMsg)
2209 {
2210 case WM_LBUTTONDOWN:
2211 case WM_LBUTTONUP:
2212 button = SCREEN_MOUSE_EVENT_LEFT_PRESSED;
2213 break;
2214
2215 case WM_MBUTTONDOWN:
2216 case WM_MBUTTONUP:
2217 button = SCREEN_MOUSE_EVENT_MIDDLE_PRESSED;
2218 break;
2219
2220 case WM_RBUTTONDOWN:
2221 case WM_RBUTTONUP:
2222 button = SCREEN_MOUSE_EVENT_RIGHT_PRESSED;
2223 break;
2224 }
2225 event = (allocate_event (screen, SCREEN_EVENT_TYPE_MOUSE));
2226 if (event)
2227 {
2228 event->event.mouse.row = ((HIWORD (lParam)) / (screen -> yChar));
2229 event->event.mouse.column = ((LOWORD (lParam)) / (screen -> xChar));
2230 event->event.mouse.control_key_state = control;
2231 event->event.mouse.button_state = button;
2232 event->event.mouse.up = up;
2233 event->event.mouse.mouse_moved = 0;
2234 event->event.mouse.double_click = 0;
2235 }
2236 }
2237
2238 /* Utilities for WriteScreenBlock */
2239
2240 static VOID _fastcall
Screen_BS(SCREEN screen)2241 Screen_BS (SCREEN screen)
2242 {
2243 if (screen->column > 0)
2244 screen->column --;
2245 else if (screen->row > 0)
2246 {
2247 screen->row--;
2248 screen->column = (screen->width - 1);
2249 }
2250 if (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE)
2251 MoveScreenCursor (screen);
2252 }
2253
2254 static VOID _fastcall
Screen_LF(SCREEN screen)2255 Screen_LF (SCREEN screen)
2256 {
2257 if ((screen->row++) >= (screen->height - 1))
2258 {
2259 ScrollScreenBufferUp (screen, screen->scroll_lines);
2260 ScrollWindow (screen->hWnd, 0,
2261 (-screen->yChar * screen->scroll_lines),
2262 NULL,
2263 NULL);
2264 #if 0
2265 InvalidateRect (hWnd, NULL, FALSE);
2266 screen->row--;
2267 #endif
2268 screen->row = (screen->height - screen->scroll_lines);
2269 }
2270 if (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE)
2271 {
2272 MoveScreenCursor (screen);
2273 UpdateWindow (screen->hWnd);
2274 }
2275 }
2276
2277 static VOID _fastcall
Screen_CR(SCREEN screen)2278 Screen_CR (SCREEN screen)
2279 {
2280 screen->column = 0;
2281 if (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE)
2282 MoveScreenCursor (screen);
2283 }
2284
2285 static VOID _fastcall
Screen_CRLF(SCREEN screen)2286 Screen_CRLF (SCREEN screen)
2287 {
2288 Screen_CR (screen);
2289 Screen_LF (screen);
2290 }
2291
2292 VOID _fastcall
clear_screen_rectangle(SCREEN screen,int lo_row,int lo_col,int hi_row,int hi_col)2293 clear_screen_rectangle (SCREEN screen,
2294 int lo_row, int lo_col,
2295 int hi_row, int hi_col)
2296 {
2297 RECT rect;
2298 int row, delta_col;
2299 char * screen_chars;
2300 SCREEN_ATTRIBUTE * screen_attrs;
2301
2302 delta_col = (hi_col - lo_col);
2303
2304 for (row = lo_row,
2305 screen_chars = &screen->chars[lo_row * MAXCOLS + lo_col],
2306 screen_attrs = &screen->attrs[lo_row * MAXCOLS + lo_col];
2307 row < hi_row;
2308 row++,
2309 screen_chars += MAXCOLS,
2310 screen_attrs += MAXCOLS)
2311 {
2312 _fmemset (screen_chars, ' ', delta_col);
2313 _fmemset (screen_attrs,
2314 screen->write_attribute,
2315 (delta_col * (sizeof (SCREEN_ATTRIBUTE))));
2316 }
2317
2318 rect.left = ((lo_col * screen->xChar) - screen->xOffset);
2319 rect.right = ((hi_col * screen->xChar) - screen->xOffset);
2320 rect.top = ((lo_row * screen->yChar) - screen->yOffset);
2321 rect.bottom = ((hi_row * screen->yChar) - screen->yOffset);
2322 InvalidateRect (screen->hWnd, &rect, FALSE);
2323 }
2324
2325 #define INIT_SCREEN_WRITE_CHAR_STATE(state) state.row = -1
2326
2327 static VOID _fastcall
Finish_ScreenWriteChar(SCREEN screen,struct screen_write_char_s * rectp)2328 Finish_ScreenWriteChar (SCREEN screen, struct screen_write_char_s * rectp)
2329 {
2330 if (rectp->row != -1)
2331 InvalidateRect (screen->hWnd, &rectp->rect, FALSE);
2332 if ((screen->column >= screen->width)
2333 && ((screen->mode_flags & SCREEN_MODE_AUTOWRAP) != 0))
2334 Screen_CRLF (screen);
2335 rectp->row = -1;
2336 }
2337
2338 VOID _fastcall
Screen_WriteCharUninterpreted(SCREEN screen,int ch,struct screen_write_char_s * rectp)2339 Screen_WriteCharUninterpreted (SCREEN screen, int ch,
2340 struct screen_write_char_s * rectp)
2341 {
2342 /* Line wrap/overwrite the last position */
2343
2344 if (screen->column >= screen->width)
2345 {
2346 if ((screen->mode_flags & SCREEN_MODE_AUTOWRAP) != 0)
2347 {
2348 if ((rectp != ((struct screen_write_char_s *) NULL))
2349 && (rectp->row != -1))
2350 {
2351 InvalidateRect (screen->hWnd, &rectp->rect, FALSE);
2352 rectp->row = -1;
2353 }
2354 Screen_CRLF (screen);
2355 }
2356 else
2357 {
2358 screen->column -= 1;
2359 if (rectp != ((struct screen_write_char_s *) NULL))
2360 {
2361 rectp->col -= 1;
2362 rectp->rect.right -= screen->xChar;
2363 }
2364 }
2365 }
2366 if (screen->row >= MAXROWS)
2367 screen->row = (MAXROWS - 1);
2368
2369 if (screen->column >= MAXCOLS)
2370 screen->column = (MAXCOLS - 1);
2371
2372 if (screen->row < 0)
2373 screen->row = 0;
2374
2375 if (screen->column < 0)
2376 screen->column = 0;
2377
2378 screen->chars[screen->row * MAXCOLS + screen->column] = ch;
2379 screen->attrs[screen->row * MAXCOLS + screen->column] =
2380 screen->write_attribute;
2381 if (rectp == ((struct screen_write_char_s *) NULL))
2382 {
2383 RECT rect;
2384
2385 rect.left = ((screen->column * screen->xChar) - screen->xOffset);
2386 rect.right = rect.left + screen->xChar;
2387 rect.top = ((screen->row * screen->yChar) - screen->yOffset);
2388 rect.bottom = rect.top + screen->yChar;
2389 InvalidateRect (screen->hWnd, &rect, FALSE);
2390 }
2391 else if ((rectp->row == screen->row) && (rectp->col == screen->column))
2392 {
2393 rectp->col += 1;
2394 rectp->rect.right += screen->xChar;
2395 }
2396 else
2397 {
2398 if (rectp->row != -1)
2399 InvalidateRect (screen->hWnd, &rectp->rect, FALSE);
2400
2401 rectp->rect.left = ((screen->column * screen->xChar) - screen->xOffset);
2402 rectp->rect.right = rectp->rect.left + screen->xChar;
2403 rectp->rect.top = ((screen->row * screen->yChar) - screen->yOffset);
2404 rectp->rect.bottom = rectp->rect.top + screen->yChar;
2405 rectp->col = (screen->column + 1);
2406 rectp->row = screen->row;
2407 }
2408 screen->column += 1;
2409 }
2410
2411 static VOID _fastcall
Screen_TAB(SCREEN screen,struct screen_write_char_s * rectp)2412 Screen_TAB (SCREEN screen, struct screen_write_char_s * rectp)
2413 {
2414 do
2415 Screen_WriteCharUninterpreted (screen, ' ', rectp);
2416 while ((screen->column % 8) != 0);
2417 }
2418
2419 static VOID _fastcall
relocate_cursor(SCREEN screen,int row,int col)2420 relocate_cursor (SCREEN screen, int row, int col)
2421 {
2422 screen->row = ((row < 0)
2423 ? 0
2424 : ((row >= screen->height)
2425 ? (screen->height - 1)
2426 : row));
2427 screen->column = ((col < 0)
2428 ? 0
2429 : ((col >= screen->width)
2430 ? (screen->width - 1)
2431 : col));
2432 if (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE)
2433 MoveScreenCursor (screen);
2434 }
2435
2436 static VOID _fastcall
cursor_right(SCREEN screen,int delta)2437 cursor_right (SCREEN screen, int delta)
2438 {
2439 int new_col = (screen->column + delta);
2440
2441 if (new_col < screen->width)
2442 screen->column = new_col;
2443 else if ((screen->mode_flags & SCREEN_MODE_AUTOWRAP) == 0)
2444 screen->column = (screen->width - 1);
2445 else
2446 {
2447 while (new_col >= screen->width)
2448 {
2449 Screen_CRLF (screen);
2450 new_col -= screen->width;
2451 }
2452 screen->column = new_col;
2453 }
2454 }
2455
2456 VOID _fastcall
scroll_screen_vertically(SCREEN screen,int lo_row_from,int lo_col,int hi_row_from,int hi_col,int lo_row_to)2457 scroll_screen_vertically (SCREEN screen,
2458 int lo_row_from, int lo_col,
2459 int hi_row_from, int hi_col,
2460 int lo_row_to)
2461 {
2462 RECT rect;
2463 int row, delta_col, hi_row_to;
2464 char * chars_from, * chars_to;
2465 SCREEN_ATTRIBUTE * attrs_from, * attrs_to;
2466
2467 if (lo_row_to < 0)
2468 lo_row_to = 0;
2469 if (lo_row_to > MAXCOLS)
2470 lo_row_to = MAXCOLS;
2471
2472 delta_col = (hi_col - lo_col);
2473 hi_row_to = (lo_row_to + (hi_row_from - lo_row_from));
2474
2475 if (lo_row_from > lo_row_to) /* Scrolling up. */
2476 for (row = lo_row_from,
2477 chars_from = &screen->chars[lo_row_from * MAXCOLS + lo_col],
2478 attrs_from = &screen->attrs[lo_row_from * MAXCOLS + lo_col],
2479 chars_to = &screen->chars[lo_row_to * MAXCOLS + lo_col],
2480 attrs_to = &screen->attrs[lo_row_to * MAXCOLS + lo_col];
2481 row < hi_row_from;
2482 row++,
2483 chars_from += MAXCOLS,
2484 attrs_from += MAXCOLS,
2485 chars_to += MAXCOLS,
2486 attrs_to += MAXCOLS)
2487 {
2488 _fmemmove (((LPSTR) chars_to), ((LPSTR) chars_from), delta_col);
2489 _fmemmove (((LPSTR) attrs_to), ((LPSTR) attrs_from), delta_col);
2490 }
2491 else /* Scrolling down. */
2492 for (row = (hi_row_from - 1),
2493 chars_from = &screen->chars[(hi_row_from - 1) * MAXCOLS + lo_col],
2494 attrs_from = &screen->attrs[(hi_row_from - 1) * MAXCOLS + lo_col],
2495 chars_to = &screen->chars[(hi_row_to - 1) * MAXCOLS + lo_col],
2496 attrs_to = &screen->attrs[(hi_row_to - 1) * MAXCOLS + lo_col];
2497 row >= lo_row_from;
2498 row--,
2499 chars_from -= MAXCOLS,
2500 attrs_from -= MAXCOLS,
2501 chars_to -= MAXCOLS,
2502 attrs_to -= MAXCOLS)
2503 {
2504 _fmemmove (((LPSTR) chars_to), ((LPSTR) chars_from), delta_col);
2505 _fmemmove (((LPSTR) attrs_to), ((LPSTR) attrs_from), delta_col);
2506 }
2507
2508 rect.left = ((lo_col * screen->xChar) - screen->xOffset);
2509 rect.right = ((hi_col * screen->xChar) - screen->xOffset);
2510 rect.top = ((lo_row_to * screen->yChar) - screen->yOffset);
2511 rect.bottom = ((hi_row_to * screen->yChar) - screen->yOffset);
2512 InvalidateRect (screen->hWnd, &rect, FALSE);
2513 }
2514
2515 static VOID _fastcall
scroll_screen_line_horizontally(SCREEN screen,int row,int lo_col_from,int hi_col_from,int lo_col_to)2516 scroll_screen_line_horizontally (SCREEN screen, int row,
2517 int lo_col_from, int hi_col_from,
2518 int lo_col_to)
2519 {
2520 RECT rect;
2521 int delta_col = (hi_col_from - lo_col_from);
2522 int hi_col_to = (lo_col_to + delta_col);
2523
2524 _fmemmove (((LPSTR) &screen->chars[(row * MAXCOLS) + lo_col_to]),
2525 ((LPSTR) &screen->chars[(row * MAXCOLS) + lo_col_from]),
2526 delta_col);
2527 _fmemmove (((LPSTR) &screen->attrs[(row * MAXCOLS) + lo_col_to]),
2528 ((LPSTR) &screen->attrs[(row * MAXCOLS) + lo_col_from]),
2529 delta_col);
2530
2531 rect.left = ((lo_col_to * screen->xChar) - screen->xOffset);
2532 rect.right = ((hi_col_to * screen->xChar) - screen->xOffset);
2533 rect.top = ((row * screen->yChar) - screen->yOffset);
2534 rect.bottom = (((row + 1) * screen->yChar) - screen->yOffset);
2535 InvalidateRect (screen->hWnd, &rect, FALSE);
2536 }
2537
2538 static int _fastcall
read_decimal(LPSTR str,int lo,int len,int * hi)2539 read_decimal (LPSTR str, int lo, int len, int * hi)
2540 {
2541 int ctr, result;
2542
2543 for (result = 0, ctr = lo;
2544 ctr < len;
2545 result = ((result * 10) + ((str[ctr]) - '0')), ctr++)
2546 if ((str[ctr] < '0') || (str[ctr] > '9'))
2547 break;
2548
2549 * hi = ctr;
2550 return (result);
2551 }
2552
2553 #ifdef PRETTY_PRINT_CHARS
2554 static VOID _fastcall
screen_write_octal(SCREEN screen,unsigned char the_char,struct screen_write_char_s * rectp)2555 screen_write_octal (SCREEN screen, unsigned char the_char,
2556 struct screen_write_char_s * rectp)
2557 {
2558 Screen_WriteCharUninterpreted (screen, '\\', rectp);
2559 Screen_WriteCharUninterpreted (screen, ((the_char / 0100) + '0'), rectp);
2560 Screen_WriteCharUninterpreted (screen, (((the_char % 0100) / 010) + '0'),
2561 rectp);
2562 Screen_WriteCharUninterpreted (screen, ((the_char % 010) + '0'), rectp);
2563 }
2564 #endif /* PRETTY_PRINT_CHARS */
2565
2566 static VOID
WriteScreenBlock_suspend(SCREEN screen,LPSTR lpBlock,int i,int nLength)2567 WriteScreenBlock_suspend (SCREEN screen, LPSTR lpBlock, int i, int nLength)
2568 {
2569 screen->n_pending = (nLength - i);
2570 screen->pending = ((LPSTR) (LocalAlloc (NONZEROLPTR, screen->n_pending)));
2571 if (screen->pending != ((LPSTR) NULL))
2572 strncpy (screen->pending, (lpBlock + i), screen->n_pending);
2573 else
2574 {
2575 screen->n_pending = 0;
2576 MessageBeep (0);
2577 }
2578 }
2579
2580 static VOID
WriteScreenBlock_continue(SCREEN screen,LPSTR lpBlock_in,int nLength_in,LPSTR * lpBlock,int * nLength)2581 WriteScreenBlock_continue (SCREEN screen,
2582 LPSTR lpBlock_in, int nLength_in,
2583 LPSTR * lpBlock, int * nLength)
2584 {
2585 (* nLength) = (screen->n_pending + nLength_in);
2586 (* lpBlock) = ((LPSTR) (LocalAlloc (NONZEROLPTR, (* nLength))));
2587 if ((* lpBlock) == ((LPSTR) NULL))
2588 {
2589 MessageBeep (0);
2590 (* nLength) = nLength_in;
2591 (* lpBlock) = lpBlock_in;
2592 }
2593 else
2594 {
2595 strncpy ((* lpBlock), screen->pending, screen->n_pending);
2596 strncpy (((* lpBlock) + screen->n_pending), lpBlock_in, nLength_in);
2597 }
2598 LocalFree (screen->pending);
2599 screen->n_pending = 0;
2600 }
2601
2602 /* BOOL WriteScreenBlock (HWND hWnd, LPSTR lpBlock_in, int nLength_in )
2603
2604 Description:
2605 Writes block of characters to TTY screen. Interprets lots of ANSI
2606 sequences.
2607 */
2608
2609 BOOL
WriteScreenBlock(HWND hWnd,LPSTR lpBlock_in,int nLength_in)2610 WriteScreenBlock (HWND hWnd, LPSTR lpBlock_in, int nLength_in)
2611 {
2612 int i;
2613 LPSTR lpBlock;
2614 int nLength;
2615 WORD saved_mode_flags;
2616 SCREEN screen = (GETSCREEN (hWnd));
2617 struct screen_write_char_s state;
2618
2619 if (NULL == screen)
2620 return (FALSE);
2621
2622 INIT_SCREEN_WRITE_CHAR_STATE (state);
2623 saved_mode_flags = (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE);
2624 screen->mode_flags &= (~ (SCREEN_MODE_EAGER_UPDATE));
2625
2626 if (screen->n_pending != 0)
2627 WriteScreenBlock_continue (screen,
2628 lpBlock_in, nLength_in,
2629 &lpBlock, &nLength);
2630 else
2631 {
2632 nLength = nLength_in;
2633 lpBlock = lpBlock_in;
2634 }
2635
2636 if ((screen->mode_flags & SCREEN_MODE_PROCESS_OUTPUT) == 0)
2637 for (i = 0; i < nLength; i++)
2638 Screen_WriteCharUninterpreted (screen, (lpBlock[i]), &state);
2639 else for (i = 0; i < nLength; i++)
2640 {
2641 unsigned char the_char = ((unsigned char) (lpBlock[i]));
2642
2643 switch (the_char)
2644 {
2645 case ASCII_BEL:
2646 MessageBeep (0);
2647 break;
2648
2649 case ASCII_BS:
2650 Screen_BS (screen);
2651 break;
2652
2653 case '\t':
2654 Screen_TAB (screen, &state);
2655 break;
2656
2657 case ASCII_LF:
2658 if (screen->mode_flags & SCREEN_MODE_NEWLINE_CRS)
2659 Screen_CR (screen);
2660 Finish_ScreenWriteChar (screen, &state);
2661 Screen_LF (screen);
2662 break;
2663
2664 case ASCII_CR:
2665 Screen_CR (screen);
2666 if (screen->mode_flags & SCREEN_MODE_CR_NEWLINES)
2667 {
2668 Finish_ScreenWriteChar (screen, &state);
2669 Screen_LF (screen);
2670 }
2671 break;
2672
2673 case ASCII_FF:
2674 Finish_ScreenWriteChar (screen, &state);
2675 Screen_Clear (screen, 0);
2676 break;
2677
2678 default:
2679 char_default:
2680 #ifdef PRETTY_PRINT_CHARS
2681 if (the_char < ' ')
2682 {
2683 Screen_WriteCharUninterpreted (screen, '^', &state);
2684 Screen_WriteCharUninterpreted (screen, (the_char + '@'), &state);
2685 }
2686 else if (the_char < ASCII_DEL)
2687 Screen_WriteCharUninterpreted (screen, the_char, &state);
2688 else if (the_char == ASCII_DEL)
2689 {
2690 Screen_WriteCharUninterpreted (screen, '^', &state);
2691 Screen_WriteCharUninterpreted (screen, '?', &state);
2692 }
2693 else
2694 screen_write_octal (screen, ((unsigned char) the_char), &state);
2695 #else /* not PRETTY_PRINT_CHARS */
2696 Screen_WriteCharUninterpreted (screen, the_char, &state);
2697 #endif /* PRETTY_PRINT_CHARS */
2698 break;
2699
2700 case ASCII_ESC:
2701 {
2702 char dispatch;
2703
2704 Finish_ScreenWriteChar (screen, &state);
2705 if ((i + 2) >= nLength)
2706 {
2707 WriteScreenBlock_suspend (screen, lpBlock, i, nLength);
2708 i = (nLength - 1); /* 1 added in for loop */
2709 break;
2710 }
2711
2712 if (lpBlock[i + 1] != '[')
2713 goto char_default;
2714
2715 dispatch = (lpBlock[i + 2]);
2716 switch (dispatch)
2717 {
2718 case 'K':
2719 /* Clear Line */
2720 clear_screen_rectangle (screen,
2721 screen->row, screen->column,
2722 (screen->row + 1), screen->width);
2723 i += 2; /* 1 added in for loop */
2724 continue;
2725
2726 case 'J':
2727 /* Clear to bottom */
2728 if (screen->column == 0)
2729 clear_screen_rectangle (screen, screen->row, 0,
2730 screen->height, screen->width);
2731 else
2732 {
2733 clear_screen_rectangle (screen,
2734 screen->row, screen->column,
2735 (screen->row + 1), screen->width);
2736 clear_screen_rectangle (screen, (screen->row + 1), 0,
2737 screen->height, screen->width);
2738 }
2739 i += 2; /* 1 added in for loop */
2740 continue;
2741
2742 case 'H':
2743 /* Cursor home */
2744 relocate_cursor (screen, 0, 0);
2745 i += 2; /* 1 added in for loop */
2746 continue;
2747
2748 case 'A':
2749 /* Cursor up */
2750 relocate_cursor (screen, (screen->row - 1), screen->column);
2751 i += 2; /* 1 added in for loop */
2752 continue;
2753
2754 case 'C':
2755 /* Cursor right */
2756 cursor_right (screen, 1);
2757 i += 2; /* 1 added in for loop */
2758 continue;
2759
2760 case 'L':
2761 /* Insert line */
2762 scroll_screen_vertically (screen,
2763 screen->row, screen->column,
2764 (screen->height - 1), screen->width,
2765 (screen->row + 1));
2766 clear_screen_rectangle (screen,
2767 screen->row, screen->column,
2768 (screen->row + 1), screen->width);
2769 i += 2; /* 1 added in for loop */
2770 continue;
2771
2772 case 'M':
2773 /* Delete line */
2774 scroll_screen_vertically (screen,
2775 (screen->row + 1), screen->column,
2776 screen->height, screen->width,
2777 screen->row);
2778 clear_screen_rectangle (screen,
2779 (screen->height - 1), screen->column,
2780 screen->height, screen->width);
2781 i += 2; /* 1 added in for loop */
2782 continue;
2783
2784 case 'P':
2785 /* Delete char */
2786 scroll_screen_line_horizontally (screen, screen->row,
2787 (screen->column + 1), screen->width,
2788 screen->column);
2789 i += 2;
2790 continue;
2791
2792 case '@':
2793 /* Insert char */
2794 scroll_screen_line_horizontally (screen, screen->row,
2795 screen->column, (screen->width - 1),
2796 (screen->column + 1));
2797 i += 2;
2798 continue;
2799
2800 default:
2801 if ((dispatch >= '0') && (dispatch <= '9'))
2802 {
2803 int j, x_value;
2804
2805 x_value = (read_decimal (&lpBlock[0], (i + 2), nLength, &j));
2806 if (j >= nLength)
2807 {
2808 WriteScreenBlock_suspend (screen, lpBlock, i, nLength);
2809 i = (j - 1); /* 1 added in for loop */
2810 continue;
2811 }
2812 else switch (lpBlock[j])
2813 {
2814 case ';':
2815 {
2816 int k, y_value;
2817
2818 y_value = (read_decimal (&lpBlock[0], (j + 1), nLength, &k));
2819 if ((k < nLength) && (lpBlock[k] == 'H'))
2820 /* Direct cursor motion */
2821 relocate_cursor (screen, (x_value - 1), (y_value - 1));
2822 else if (k < nLength)
2823 MessageBeep (0);
2824 else
2825 WriteScreenBlock_suspend (screen, lpBlock, i, nLength);
2826 i = k; /* 1 added in for loop */
2827 continue;
2828 }
2829
2830 case 'A':
2831 /* Multi cursor up */
2832 relocate_cursor (screen, (screen->row - x_value),
2833 screen->column);
2834 i = j; /* 1 added in for loop */
2835 continue;
2836
2837 case 'C':
2838 /* Multi cursor right */
2839 cursor_right (screen, x_value);
2840 i = j; /* 1 added in for loop */
2841 continue;
2842
2843 case 'L':
2844 /* Multi insert line */
2845 scroll_screen_vertically (screen,
2846 screen->row, screen->column,
2847 (screen->height - 1), screen->width,
2848 (screen->row + x_value));
2849 clear_screen_rectangle (screen,
2850 screen->row, screen->column,
2851 (screen->row + x_value), screen->width);
2852 i = j; /* 1 added in for loop */
2853 continue;
2854
2855 case 'M':
2856 /* Multi delete line */
2857 scroll_screen_vertically (screen,
2858 (screen->row + x_value),
2859 screen->column,
2860 screen->height, screen->width,
2861 screen->row);
2862 clear_screen_rectangle (screen,
2863 (screen->height - x_value),
2864 screen->column,
2865 screen->height, screen->width);
2866 i = j; /* 1 added in for loop */
2867 continue;
2868
2869 case 'P':
2870 /* Multi delete char */
2871 scroll_screen_line_horizontally (screen, screen->row,
2872 (screen->column + x_value),
2873 screen->width,
2874 screen->column);
2875 i = j; /* 1 added in for loop */
2876 continue;
2877
2878 case '@':
2879 /* Multi insert char */
2880 scroll_screen_line_horizontally (screen, screen->row,
2881 screen->column,
2882 (screen->width - x_value),
2883 (screen->column + x_value));
2884 i = j; /* 1 added in for loop */
2885 continue;
2886
2887 case 'm':
2888 if ((j == (i + 3)) && ((x_value == 0) || (x_value == 7)))
2889 {
2890 /* Enter stdout (7) or exit stdout (0) */
2891 screen->write_attribute = (x_value == 7);
2892 i = j; /* 1 added in for loop */
2893 continue;
2894 }
2895 goto use_default;
2896
2897 case 'p':
2898 /* Not a real ANSI escape. Modelled after aaa. */
2899 if ((j == (i + 3)) && (x_value < 2))
2900 {
2901 /* Enter edwin/emacs (1) mode or exit edwin/emacs (0) mode. */
2902 if (x_value == 1)
2903 {
2904 screen->mode_flags |= SCREEN_MODE_EDWIN;
2905 screen->mode_flags &= (~ SCREEN_MODE_NEWLINE_CRS);
2906 screen->scroll_lines = 1;
2907 SetWindowText (screen->hWnd, "Edwin");
2908 }
2909 else
2910 {
2911 screen->mode_flags &= (~ SCREEN_MODE_EDWIN);
2912 screen->mode_flags |= SCREEN_MODE_NEWLINE_CRS;
2913 screen->scroll_lines
2914 = (COMPUTE_SCROLL_LINES (screen->height));
2915 SetWindowText (screen->hWnd, "MIT/GNU Scheme");
2916 }
2917 i = j; /* 1 added in for loop */
2918 continue;
2919 }
2920 goto use_default;
2921
2922 default:
2923 use_default:
2924 MessageBeep (0);
2925 i = j; /* 1 added in for loop */
2926 continue;
2927 }
2928 }
2929 break;
2930 }
2931 }
2932 }
2933 }
2934
2935 if (lpBlock != lpBlock_in)
2936 LocalFree (lpBlock);
2937
2938 Finish_ScreenWriteChar (screen, &state);
2939 if (saved_mode_flags != 0)
2940 {
2941 UpdateWindow (screen->hWnd);
2942 MoveScreenCursor (screen);
2943 screen->mode_flags |= saved_mode_flags;
2944 }
2945 return TRUE;
2946 }
2947
2948 /* A fast raw write to the screen memory. */
2949 /* Client is responsible for invalidating the correct region */
2950
2951 VOID
WriteScreenBlock_NoInvalidRect(SCREEN screen,int row,int column,LPSTR lpBlock,int nLength)2952 WriteScreenBlock_NoInvalidRect (SCREEN screen, int row, int column,
2953 LPSTR lpBlock, int nLength)
2954 {
2955 int i, limit, start;
2956
2957 if (row < 0 || row >= MAXROWS)
2958 return;
2959
2960 if (column < 0) {
2961 lpBlock += (- column);
2962 nLength += column;
2963 column = 0;
2964 }
2965
2966 if (column + nLength >= MAXCOLS)
2967 limit = MAXCOLS - column;
2968 else
2969 limit = nLength;
2970
2971 start = row * MAXCOLS + column;
2972 for (i = 0; i < limit; i++) {
2973 int place = start + i;
2974 screen->chars[place] = lpBlock[i];
2975 screen->attrs[place] = screen->write_attribute;
2976 }
2977 }
2978
2979 /* Utilities for line-buffered input. */
2980
2981 static VOID
key_buffer_insert_self(SCREEN screen,int ch)2982 key_buffer_insert_self (SCREEN screen, int ch)
2983 {
2984 if (screen->n_chars < MAX_LINEINPUT)
2985 {
2986 screen->line_buffer[screen->n_chars++] = ch;
2987 if (screen->mode_flags & SCREEN_MODE_ECHO)
2988 {
2989 if (ch == '\n')
2990 Screen_CRLF (screen);
2991 else
2992 {
2993 char c = ((char) ch);
2994 #if 0
2995 Screen_WriteCharUninterpreted (screen, ch, NULL);
2996 #endif
2997 WriteScreenBlock (screen->hWnd, &c, 1);
2998 }
2999 }
3000 }
3001 }
3002
3003 static VOID
key_buffer_erase_character(SCREEN screen)3004 key_buffer_erase_character (SCREEN screen)
3005 {
3006 if (screen->n_chars > 0)
3007 {
3008 screen->n_chars -= 1;
3009 if (screen->mode_flags & SCREEN_MODE_ECHO)
3010 {
3011 Screen_BS (screen);
3012 Screen_WriteCharUninterpreted (screen, ' ', NULL);
3013 Screen_BS (screen);
3014 }
3015 }
3016 }
3017
3018 static VOID
buffered_key_command(SCREEN screen,int ch)3019 buffered_key_command (SCREEN screen, int ch)
3020 {
3021 switch (ch)
3022 {
3023 case '\n':
3024 case '\r':
3025 key_buffer_insert_self (screen, '\n');
3026 break;
3027
3028 case '\b':
3029 case ASCII_DEL:
3030 key_buffer_erase_character (screen);
3031 break;
3032
3033 default:
3034 key_buffer_insert_self (screen, ch);
3035 break;
3036 }
3037 if (screen->mode_flags & SCREEN_MODE_EAGER_UPDATE)
3038 UpdateWindow (screen->hWnd);
3039 }
3040
3041 /* Line-buffered input. */
3042
3043 static int
ReadScreen_line_input(SCREEN screen,LPSTR buffer,int buflen)3044 ReadScreen_line_input (SCREEN screen, LPSTR buffer, int buflen)
3045 {
3046 SCREEN_EVENT event;
3047 int result = (-1); /* No EOL seen yet. */
3048
3049 while (read_event (screen, SCREEN_EVENT_TYPE_KEY, 1, (&event)))
3050 {
3051 int ch = event.event.key.ch;
3052 if ((event.event.key.control_key_state & SCREEN_ANY_ALT_KEY_MASK) != 0)
3053 ch |= 0200;
3054
3055 if (ch != 0)
3056 buffered_key_command (screen, ch);
3057
3058 if ((ch == '\n') || (ch == '\r'))
3059 {
3060 int i, count = (min (screen->n_chars, buflen));
3061
3062 for (i = 0; i < count; i++)
3063 buffer[i] = screen->line_buffer[i];
3064 screen->n_chars -= count;
3065 if (screen->n_chars > 0)
3066 _fmemmove (&screen->line_buffer[0],
3067 &screen->line_buffer[count],
3068 screen->n_chars);
3069 result = (count);
3070 break;
3071 }
3072 }
3073 return (result);
3074 }
3075
3076 /* Untranslated/unbuffered input */
3077
3078 static int
ReadScreen_raw(SCREEN screen,LPSTR buffer,int buflen)3079 ReadScreen_raw (SCREEN screen, LPSTR buffer, int buflen)
3080 {
3081 SCREEN_EVENT event;
3082 int position = 0;
3083
3084 while ((position < buflen)
3085 && (read_event (screen, SCREEN_EVENT_TYPE_KEY, 1, (&event))))
3086 {
3087 int ch = event.event.key.ch;
3088 if ((event.event.key.control_key_state & SCREEN_ANY_ALT_KEY_MASK) != 0)
3089 ch |= 0200;
3090
3091 /* Store the character */
3092 buffer[position++] = ch;
3093 if (screen->mode_flags & SCREEN_MODE_ECHO)
3094 {
3095 char c = ((char) ch);
3096 WriteScreenBlock (screen->hWnd, &c, 1);
3097 }
3098 }
3099 return ((position == 0) ? -1 : position);
3100 }
3101
3102 /* int ReadScreen (SCREEN screen, LPSTR buffer, int buflen)
3103
3104 Read characters into buffer.
3105 If in line mode, collect characters into the line buffer.
3106 Return the number of characters read.
3107 In raw mode, return -1 if there are no characters.
3108 If in line mode and not yet at end of line, return -1 (i.e. this
3109 is a non-blocking read
3110 */
3111
3112 static int
ReadScreen(SCREEN screen,LPSTR buffer,int buflen)3113 ReadScreen (SCREEN screen, LPSTR buffer, int buflen)
3114 {
3115 if (screen->mode_flags & SCREEN_MODE_LINE_INPUT)
3116 return (ReadScreen_line_input (screen, buffer, buflen));
3117 else
3118 return (ReadScreen_raw (screen, buffer, buflen));
3119 }
3120
3121 VOID
Screen_Clear(SCREEN screen,int kind)3122 Screen_Clear (SCREEN screen, int kind)
3123 {
3124 if (kind == 0)
3125 {
3126 /* clear whole screen */
3127 ClearScreen_internal(screen);
3128 InvalidateRect (screen->hWnd, NULL, TRUE);
3129 return;
3130 }
3131 if (kind == 1)
3132 /* clear to eol */
3133 return;
3134 }
3135
3136 /* VOID GetMinMaxSizes (HWND hWnd, LPPOINT min_size, LPPOINT max_size)
3137
3138 Description:
3139 determine the minimum and maxinum sizes for a screen window.
3140 */
3141
3142 static VOID
GetMinMaxSizes(HWND hWnd,LPPOINT min_size,LPPOINT max_size)3143 GetMinMaxSizes (HWND hWnd, LPPOINT min_size, LPPOINT max_size)
3144 {
3145 SCREEN screen = GETSCREEN (hWnd);
3146 int extra_width, extra_height;
3147
3148 if (screen==0) return;
3149 extra_width = 2*GetSystemMetrics(SM_CXFRAME);
3150 extra_height = 2*GetSystemMetrics(SM_CYFRAME)
3151 + GetSystemMetrics(SM_CYCAPTION)
3152 + (GetMenu(hWnd) ? GetSystemMetrics(SM_CYMENU) : 0);
3153 /* The min size sould be configurable so Edwin can configure it */
3154 /* to prevent the window being shrunk so far that the displayed */
3155 /* buffers wont fit. */
3156 min_size->x = screen->xChar * 5 + extra_width;
3157 min_size->y = screen->yChar * 3 + extra_height;
3158 max_size->x = screen->xChar * MAXCOLS + extra_width;
3159 max_size->y = screen->yChar * MAXROWS + extra_height;
3160 }
3161
3162 static BOOL
SelectScreenFont(SCREEN screen,HWND owner)3163 SelectScreenFont (SCREEN screen, HWND owner)
3164 {
3165 CHOOSEFONT cfTTYFont;
3166
3167 if (NULL == screen) return FALSE;
3168
3169 cfTTYFont.lStructSize = sizeof (CHOOSEFONT);
3170 cfTTYFont.hwndOwner = owner;
3171 cfTTYFont.hDC = NULL;
3172 cfTTYFont.rgbColors = screen->rgbFGColour;
3173 cfTTYFont.lpLogFont = &screen->lfFont;
3174 cfTTYFont.Flags = (CF_FIXEDPITCHONLY
3175 | CF_SCREENFONTS
3176 | CF_EFFECTS
3177 | CF_INITTOLOGFONTSTRUCT
3178 );
3179 cfTTYFont.lCustData = 0;
3180 cfTTYFont.lpfnHook = NULL;
3181 cfTTYFont.lpTemplateName = NULL;
3182 cfTTYFont.hInstance = (HINSTANCE) GetWindowLong(owner, GWL_HINSTANCE);
3183
3184 if (ChooseFont (&cfTTYFont))
3185 {
3186 screen->rgbFGColour = cfTTYFont.rgbColors;
3187 ResetScreen (screen);
3188 }
3189 return TRUE;
3190 }
3191
3192 /* BOOL SelectScreenBackColor (SCREEN screen, HWND owner)
3193
3194 Description:
3195 Selects the background color for the TTY screen.
3196 Uses the Common Dialog ChooseColor() API.
3197 */
3198
3199 static BOOL
SelectScreenBackColor(SCREEN screen,HWND owner)3200 SelectScreenBackColor (SCREEN screen, HWND owner)
3201 {
3202 static DWORD custcolors[16] = {
3203 RGB(0x00,0x00,0x00)
3204 ,RGB(0x80,0x00,0x00)
3205 ,RGB(0x00,0x80,0x00)
3206 ,RGB(0x80,0x80,0x00)
3207 ,RGB(0x00,0x00,0x80)
3208 ,RGB(0x80,0x00,0x80)
3209 ,RGB(0x00,0x80,0x80)
3210 ,RGB(0xC0,0xC0,0xC0)
3211 ,RGB(0xC0,0xDC,0xC0)
3212 ,RGB(0xA6,0xCA,0xF0)
3213 ,RGB(0xFF,0xFB,0xF0)
3214 ,RGB(0xA0,0xA0,0xA4)
3215 ,RGB(0x80,0x80,0x80)
3216 /* ,RGB(0xFF,0x00,0x00) */
3217 ,RGB(0x00,0xFF,0x00)
3218 ,RGB(0xFF,0xFF,0x00)
3219 /* ,RGB(0x00,0x00,0xFF) */
3220 /* ,RGB(0xFF,0x00,0xFF) */
3221 /* ,RGB(0x00,0xFF,0xFF) */
3222 ,RGB(0xFF,0xFF,0xFF)
3223 };
3224
3225 CHOOSECOLOR backcolor;
3226
3227 if (NULL == screen)
3228 return FALSE;
3229
3230 backcolor.lStructSize = sizeof (CHOOSECOLOR);
3231 backcolor.hwndOwner = owner;
3232 backcolor.hInstance = (HINSTANCE) GetWindowLong(owner, GWL_HINSTANCE);
3233
3234 backcolor.rgbResult = screen->rgbBGColour;
3235 backcolor.lpCustColors = &custcolors[0];
3236 backcolor.Flags = (CC_RGBINIT);
3237
3238 backcolor.lCustData = 0;
3239 backcolor.lpfnHook = NULL;
3240 backcolor.lpTemplateName = NULL;
3241
3242 if (ChooseColor (&backcolor))
3243 {
3244 HDC hdc = GetDC (owner);
3245
3246 /* Use GetNearestColor to ensure consistency with the background */
3247 /* text color. */
3248 screen->rgbBGColour = GetNearestColor (hdc, (backcolor.rgbResult));
3249 if (screen->bkgnd_brush != NULL)
3250 DeleteObject (screen->bkgnd_brush);
3251 screen->bkgnd_brush = CreateSolidBrush (screen->rgbBGColour);
3252 InvalidateRect (owner, NULL, TRUE);
3253 ReleaseDC (owner, hdc);
3254 }
3255 return TRUE;
3256 }
3257
3258 /* Event Queue */
3259
3260 static SCREEN_EVENT *
allocate_event(SCREEN screen,SCREEN_EVENT_TYPE type)3261 allocate_event (SCREEN screen, SCREEN_EVENT_TYPE type)
3262 {
3263 SCREEN_EVENT_LINK * new_event;
3264 if (((screen -> mode_flags) & type) == 0)
3265 return (0);
3266 if (free_events == 0)
3267 new_event = (xmalloc (sizeof (SCREEN_EVENT_LINK)));
3268 else
3269 {
3270 new_event = free_events;
3271 free_events = (free_events -> next);
3272 n_free_events -= 1;
3273 }
3274 (new_event -> next) = 0;
3275 if (event_queue_tail == 0)
3276 event_queue_head = new_event;
3277 else
3278 (event_queue_tail -> next) = new_event;
3279 event_queue_tail = new_event;
3280 ((new_event -> event) . handle) = (screen -> hWnd);
3281 ((new_event -> event) . type) = type;
3282 return (& (new_event -> event));
3283 }
3284
3285 /* read_event (screen, type, delete_p, event)
3286 Reads the next matching event out of the queue.
3287 Returns non-zero iff a matching event is found.
3288 If screen is non-zero, only events for that screen are considered.
3289 If type is non-zero, only events of that type are considered.
3290 If delete_p is non-zero, the event is deleted from the queue. */
3291
3292 static int
read_event(SCREEN screen,SCREEN_EVENT_TYPE type,int delete_p,SCREEN_EVENT * event)3293 read_event (SCREEN screen, SCREEN_EVENT_TYPE type, int delete_p,
3294 SCREEN_EVENT * event)
3295 {
3296 SCREEN_EVENT_LINK * scan_queue = event_queue_head;
3297 SCREEN_EVENT_LINK * prev_queue = 0;
3298 while (scan_queue != 0)
3299 {
3300 if (((screen == 0)
3301 || (((scan_queue -> event) . handle) == (screen -> hWnd)))
3302 && ((type == 0) || (((scan_queue -> event) . type) == type)))
3303 {
3304 if (event != 0)
3305 (*event) = (scan_queue -> event);
3306 if (delete_p)
3307 {
3308 if (prev_queue == 0)
3309 {
3310 event_queue_head = (event_queue_head -> next);
3311 if (event_queue_head == 0)
3312 event_queue_tail = 0;
3313 }
3314 else
3315 {
3316 (prev_queue -> next) = (scan_queue -> next);
3317 if (event_queue_tail == scan_queue)
3318 event_queue_tail = prev_queue;
3319 }
3320 ((scan_queue -> event) . handle) = INVALID_HANDLE_VALUE;
3321 if (n_free_events < MAX_FREE_EVENTS)
3322 {
3323 (scan_queue -> next) = free_events;
3324 free_events = scan_queue;
3325 n_free_events += 1;
3326 }
3327 else
3328 free (scan_queue);
3329 }
3330 return (1);
3331 }
3332 else
3333 {
3334 prev_queue = scan_queue;
3335 scan_queue = (scan_queue -> next);
3336 }
3337 }
3338 return (0);
3339 }
3340
3341 int
Screen_read_event(SCREEN_EVENT * event)3342 Screen_read_event (SCREEN_EVENT * event)
3343 {
3344 int result = (read_event (0, 0, 1, event));
3345 if (win32_trace_level > 1)
3346 {
3347 fprintf (win32_trace_file, "Screen_read_event: result=%d\n", result);
3348 fflush (win32_trace_file);
3349 }
3350 return (result);
3351 }
3352
3353 int
Screen_pending_events_p(void)3354 Screen_pending_events_p (void)
3355 {
3356 return (read_event (0, 0, 0, 0));
3357 }
3358
3359 VOID
Screen_SetAttribute(HANDLE screen,SCREEN_ATTRIBUTE sa)3360 Screen_SetAttribute (HANDLE screen, SCREEN_ATTRIBUTE sa)
3361 {
3362 SendMessage (screen, SCREEN_SETATTRIBUTE, (WPARAM)sa, 0);
3363 }
3364
3365 VOID _fastcall
Screen_SetAttributeDirect(SCREEN screen,SCREEN_ATTRIBUTE sa)3366 Screen_SetAttributeDirect (SCREEN screen, SCREEN_ATTRIBUTE sa)
3367 {
3368 screen->write_attribute = sa;
3369 }
3370
3371 VOID
Screen_WriteChar(HANDLE screen,char ch)3372 Screen_WriteChar (HANDLE screen, char ch)
3373 {
3374 SendMessage (screen, SCREEN_WRITE, 1, (LPARAM)(LPSTR) &ch);
3375 }
3376
3377 VOID
Screen_WriteText(HANDLE screen,char * string)3378 Screen_WriteText (HANDLE screen, char *string)
3379 {
3380 SendMessage (screen, SCREEN_WRITE, strlen(string), (LPARAM)(LPSTR)string);
3381 }
3382
3383 VOID
Screen_SetCursorPosition(HANDLE screen,int line,int column)3384 Screen_SetCursorPosition (HANDLE screen, int line, int column)
3385 {
3386 SendMessage (screen, SCREEN_SETPOSITION, 0, MAKELPARAM(column,line));
3387 }
3388
3389 VOID
Screen_SetMode(HANDLE screen,int mode)3390 Screen_SetMode (HANDLE screen, int mode)
3391 {
3392 SendMessage (screen, SCREEN_SETMODES, ((WPARAM) mode), 0);
3393 }
3394
3395 int
Screen_GetMode(HANDLE screen)3396 Screen_GetMode (HANDLE screen)
3397 {
3398 return SendMessage (screen, SCREEN_GETMODES, 0, 0);
3399 }
3400
3401 #define SCREEN_MODE_COOKED (SCREEN_MODE_LINE_INPUT | SCREEN_MODE_ECHO)
3402
3403 int
Screen_Read(HANDLE hWnd,BOOL buffered_p,char * buffer,int buflen)3404 Screen_Read (HANDLE hWnd, BOOL buffered_p, char * buffer, int buflen)
3405 {
3406 int result;
3407 WORD input_flags;
3408 SCREEN screen = (GETSCREEN (hWnd));
3409
3410 if (screen != NULL)
3411 {
3412 input_flags = (screen->mode_flags & SCREEN_MODE_COOKED);
3413 screen->mode_flags &= (~ SCREEN_MODE_COOKED);
3414 if (buffered_p)
3415 screen->mode_flags |= SCREEN_MODE_COOKED;
3416 }
3417
3418 result = (SendMessage (hWnd, SCREEN_READ,
3419 ((WPARAM) buflen), ((LPARAM) buffer)));
3420
3421 if (screen != NULL)
3422 {
3423 screen->mode_flags &= (~ SCREEN_MODE_COOKED);
3424 screen->mode_flags |= input_flags;
3425 }
3426
3427 return result;
3428 }
3429
3430 VOID
Screen_GetSize(HWND hWnd,int * rows,int * columns)3431 Screen_GetSize (HWND hWnd, int *rows, int *columns)
3432 {
3433 SCREEN screen = GETSCREEN (hWnd);
3434 if (screen == 0)
3435 return;
3436 *rows = screen->height;
3437 *columns = screen->width;
3438 }
3439
3440 VOID
Screen_CR_to_RECT(RECT * rect,SCREEN screen,int lo_row,int lo_col,int hi_row,int hi_col)3441 Screen_CR_to_RECT (RECT * rect, SCREEN screen,
3442 int lo_row, int lo_col,
3443 int hi_row, int hi_col)
3444 {
3445 rect->left = ((lo_col * screen->xChar) - screen->xOffset);
3446 rect->right = ((hi_col * screen->xChar) - screen->xOffset);
3447 rect->top = ((lo_row * screen->yChar) - screen->yOffset);
3448 rect->bottom = ((hi_row * screen->yChar) - screen->yOffset);
3449 }
3450
3451 VOID
Enable_Cursor(SCREEN screen,BOOL show)3452 Enable_Cursor (SCREEN screen, BOOL show)
3453 {
3454 ScreenCurrentFocus();
3455 if (show) {
3456 if (!screen->cursor_visible) {
3457 screen->cursor_visible = TRUE;
3458 if (screen && screen == screen_focus)
3459 ShowCaret (screen->hWnd);
3460 }
3461 } else {
3462 if (screen->cursor_visible) {
3463 screen->cursor_visible = FALSE;
3464 if (screen && screen == screen_focus)
3465 HideCaret (screen->hWnd);
3466 }
3467 }
3468 }
3469
3470 HICON
ScreenSetIcon(SCREEN screen,HICON hIcon)3471 ScreenSetIcon(SCREEN screen, HICON hIcon)
3472 {
3473 HICON result = screen->hIcon;
3474 screen->hIcon = hIcon;
3475 return result;
3476 }
3477
3478 BOOL
ScreenSetDefaultFont(char * description)3479 ScreenSetDefaultFont (char *description)
3480 {
3481 LOGFONT lf;
3482 HFONT hfont;
3483
3484 /* modify default name & size, but undo characteristics */
3485 lf = lfDefaultLogFont;
3486 (lf . lfWeight) = FW_NORMAL;
3487 (lf . lfItalic) = FALSE;
3488 (lf . lfUnderline) = FALSE;
3489 (lf . lfStrikeOut) = FALSE;
3490 hfont = (set_font_1 (description, (&lf)));
3491 if (hfont == NULL)
3492 return (FALSE);
3493 else
3494 {
3495 DeleteObject (hfont);
3496 lfDefaultLogFont = lf;
3497 return (TRUE);
3498 }
3499 }
3500
3501 BOOL
ScreenSetFont(SCREEN screen,char * description)3502 ScreenSetFont (SCREEN screen, char *description)
3503 {
3504 LOGFONT lf;
3505 HFONT hfont;
3506
3507 init_LOGFONT (&lf);
3508 hfont = (set_font_1 (description, (&lf)));
3509 if (hfont == NULL)
3510 return (FALSE);
3511 else
3512 {
3513 (screen -> hFont) = hfont;
3514 (screen -> lfFont) = lf;
3515 ResetScreen (screen);
3516 return (TRUE);
3517 }
3518 }
3519
3520 static HFONT
set_font_1(char * description,LOGFONT * lf)3521 set_font_1 (char * description, LOGFONT * lf)
3522 {
3523 HFONT hfont = NULL;
3524 if (parse_logfont (description, lf))
3525 {
3526 (void) search_for_font (lf);
3527 hfont = (CreateFontIndirect (lf));
3528 }
3529 return (hfont);
3530 }
3531
3532 static BOOL
parse_logfont(char * name,LOGFONT * lf)3533 parse_logfont (char * name, LOGFONT * lf)
3534 {
3535 int i = 0;
3536 int name_ended = 0;
3537 int number_p;
3538 int len;
3539 char * start = name;
3540 char * end = name;
3541 char * scan;
3542
3543 while (1)
3544 {
3545 while ((*start) == ' ')
3546 start += 1;
3547 if ((*start) == '\0')
3548 return (TRUE);
3549 end = start;
3550 while (((*end) != ' ') && ((*end) != '\0'))
3551 end += 1;
3552 len = (end - start);
3553 scan = start;
3554 number_p = 0;
3555 if (scan < end)
3556 while (1)
3557 {
3558 if (scan == end)
3559 {
3560 number_p = 1;
3561 break;
3562 }
3563 if (! (((*scan) >= '0') && ((*scan) <= '9')))
3564 {
3565 number_p = 0;
3566 break;
3567 }
3568 scan += 1;
3569 }
3570 if (number_p)
3571 {
3572 long points = (atol (start));
3573 (lf -> lfHeight) = (- (points_to_logical_units (points)));
3574 name_ended = 1;
3575 }
3576 else if ((len == 4) && ((_strnicmp (start, "bold", len)) == 0))
3577 {
3578 (lf -> lfWeight) = FW_BOLD;
3579 name_ended = 1;
3580 }
3581 else if ((len == 6) && ((_strnicmp (start, "italic", len)) == 0))
3582 {
3583 (lf -> lfItalic) = TRUE;
3584 name_ended = 1;
3585 }
3586 else if ((len == 7) && ((_strnicmp (start, "regular", len)) == 0))
3587 {
3588 (lf -> lfWeight) = FW_NORMAL;
3589 (lf -> lfItalic) = FALSE;
3590 name_ended = 1;
3591 }
3592 else if ((len == 9) && ((_strnicmp (start, "underline", len)) == 0))
3593 {
3594 (lf -> lfUnderline) = TRUE;
3595 name_ended = 1;
3596 }
3597 else if ((len == 9) && ((_strnicmp (start, "strikeout", len)) == 0))
3598 {
3599 (lf -> lfStrikeOut) = TRUE;
3600 name_ended = 1;
3601 }
3602 else if ((len < (LF_FACESIZE - i)) && (!name_ended))
3603 {
3604 if (i > 0)
3605 ((lf -> lfFaceName) [i++]) = ' ';
3606 while (start < end)
3607 ((lf -> lfFaceName) [i++]) = (*start++);
3608 ((lf -> lfFaceName) [i]) = '\0';
3609 }
3610 else
3611 return (FALSE);
3612 start = end;
3613 }
3614 }
3615
3616 static long
points_to_logical_units(long points)3617 points_to_logical_units (long points)
3618 {
3619 HDC hdc = (CreateDC ("DISPLAY", NULL, NULL, NULL));
3620 float pixels_per_inch_y = ((float) (GetDeviceCaps (hdc, LOGPIXELSY)));
3621 float pixels = ((((float) points) / 72.0) * pixels_per_inch_y);
3622 POINT pt;
3623 (pt . x) = 0;
3624 (pt . y) = ((int) (pixels * 10.0));
3625 DPtoLP (hdc, (&pt), 1);
3626 DeleteDC (hdc);
3627 return ((pt . y) / 10);
3628 }
3629
3630 struct enum_font_args
3631 {
3632 LOGFONT * lf;
3633 ENUMLOGFONT elf;
3634 BOOL foundp;
3635 };
3636
3637 static BOOL
search_for_font(LOGFONT * lf)3638 search_for_font (LOGFONT * lf)
3639 {
3640 HDC hdc = (CreateDC ("DISPLAY", NULL, NULL, NULL));
3641 struct enum_font_args args;
3642 (args . lf) = lf;
3643 (args . foundp) = FALSE;
3644 (void) EnumFontFamilies (hdc,
3645 (lf -> lfFaceName),
3646 ((void *) search_for_font_proc),
3647 ((LPARAM) (&args)));
3648 if (args . foundp)
3649 (*lf) = (args . elf . elfLogFont);
3650 DeleteDC (hdc);
3651 return (args . foundp);
3652 }
3653
3654 static int CALLBACK
search_for_font_proc(ENUMLOGFONT * elf,NEWTEXTMETRIC * ntm,int type,LPARAM a)3655 search_for_font_proc (ENUMLOGFONT * elf, NEWTEXTMETRIC * ntm, int type,
3656 LPARAM a)
3657 {
3658 struct enum_font_args * args = ((struct enum_font_args *) a);
3659 if ((((elf -> elfLogFont) . lfHeight) == (- (args -> lf -> lfHeight)))
3660 && (((elf -> elfLogFont) . lfWeight) == (args -> lf -> lfWeight))
3661 && (((elf -> elfLogFont) . lfItalic) == (args -> lf -> lfItalic))
3662 && (((elf -> elfLogFont) . lfUnderline) == (args -> lf -> lfUnderline))
3663 && (((elf -> elfLogFont) . lfStrikeOut) == (args -> lf -> lfStrikeOut)))
3664 {
3665 (args -> elf) = (*elf);
3666 (args -> foundp) = TRUE;
3667 return (0);
3668 }
3669 else
3670 return (1);
3671 }
3672
3673 static BOOL
change_colour(SCREEN screen,DWORD requested_colour,DWORD * colour_slot)3674 change_colour (SCREEN screen, DWORD requested_colour, DWORD *colour_slot)
3675 {
3676 HWND hWnd = screen->hWnd;
3677 HDC hdc = GetDC (hWnd);
3678 COLORREF actual_colour = GetNearestColor (hdc, requested_colour);
3679 if (actual_colour == CLR_INVALID) {
3680 ReleaseDC (hWnd, hdc);
3681 return FALSE;
3682 }
3683 *colour_slot = actual_colour;
3684
3685 /* Redraw screen with new colours */
3686 if (screen->bkgnd_brush != NULL)
3687 DeleteObject (screen->bkgnd_brush);
3688 screen->bkgnd_brush = CreateSolidBrush (screen->rgbBGColour);
3689 InvalidateRect (hWnd, NULL, TRUE);
3690 ReleaseDC (hWnd, hdc);
3691
3692 return TRUE;
3693 }
3694
3695 BOOL
ScreenSetForegroundColour(SCREEN screen,DWORD colour)3696 ScreenSetForegroundColour (SCREEN screen, DWORD colour)
3697 {
3698 return change_colour (screen, colour, &screen->rgbFGColour);
3699 }
3700
3701 BOOL
ScreenSetBackgroundColour(SCREEN screen,DWORD colour)3702 ScreenSetBackgroundColour (SCREEN screen, DWORD colour)
3703 {
3704 return change_colour (screen, colour, &screen->rgbBGColour);
3705 }
3706
3707 static const char *
translate_message_code(UINT uMsg)3708 translate_message_code (UINT uMsg)
3709 {
3710 switch (uMsg)
3711 {
3712 case WM_NULL: return ("WM_NULL");
3713 case WM_CREATE: return ("WM_CREATE");
3714 case WM_DESTROY: return ("WM_DESTROY");
3715 case WM_MOVE: return ("WM_MOVE");
3716 case WM_SIZE: return ("WM_SIZE");
3717 case WM_ACTIVATE: return ("WM_ACTIVATE");
3718 case WM_SETFOCUS: return ("WM_SETFOCUS");
3719 case WM_KILLFOCUS: return ("WM_KILLFOCUS");
3720 case WM_ENABLE: return ("WM_ENABLE");
3721 case WM_SETREDRAW: return ("WM_SETREDRAW");
3722 case WM_SETTEXT: return ("WM_SETTEXT");
3723 case WM_GETTEXT: return ("WM_GETTEXT");
3724 case WM_GETTEXTLENGTH: return ("WM_GETTEXTLENGTH");
3725 case WM_PAINT: return ("WM_PAINT");
3726 case WM_CLOSE: return ("WM_CLOSE");
3727 case WM_QUERYENDSESSION: return ("WM_QUERYENDSESSION");
3728 case WM_QUIT: return ("WM_QUIT");
3729 case WM_QUERYOPEN: return ("WM_QUERYOPEN");
3730 case WM_ERASEBKGND: return ("WM_ERASEBKGND");
3731 case WM_SYSCOLORCHANGE: return ("WM_SYSCOLORCHANGE");
3732 case WM_ENDSESSION: return ("WM_ENDSESSION");
3733 case WM_SHOWWINDOW: return ("WM_SHOWWINDOW");
3734 case WM_WININICHANGE: return ("WM_WININICHANGE");
3735 case WM_DEVMODECHANGE: return ("WM_DEVMODECHANGE");
3736 case WM_ACTIVATEAPP: return ("WM_ACTIVATEAPP");
3737 case WM_FONTCHANGE: return ("WM_FONTCHANGE");
3738 case WM_TIMECHANGE: return ("WM_TIMECHANGE");
3739 case WM_CANCELMODE: return ("WM_CANCELMODE");
3740 case WM_SETCURSOR: return ("WM_SETCURSOR");
3741 case WM_MOUSEACTIVATE: return ("WM_MOUSEACTIVATE");
3742 case WM_CHILDACTIVATE: return ("WM_CHILDACTIVATE");
3743 case WM_QUEUESYNC: return ("WM_QUEUESYNC");
3744 case WM_GETMINMAXINFO: return ("WM_GETMINMAXINFO");
3745 case WM_PAINTICON: return ("WM_PAINTICON");
3746 case WM_ICONERASEBKGND: return ("WM_ICONERASEBKGND");
3747 case WM_NEXTDLGCTL: return ("WM_NEXTDLGCTL");
3748 case WM_SPOOLERSTATUS: return ("WM_SPOOLERSTATUS");
3749 case WM_DRAWITEM: return ("WM_DRAWITEM");
3750 case WM_MEASUREITEM: return ("WM_MEASUREITEM");
3751 case WM_DELETEITEM: return ("WM_DELETEITEM");
3752 case WM_VKEYTOITEM: return ("WM_VKEYTOITEM");
3753 case WM_CHARTOITEM: return ("WM_CHARTOITEM");
3754 case WM_SETFONT: return ("WM_SETFONT");
3755 case WM_GETFONT: return ("WM_GETFONT");
3756 case WM_SETHOTKEY: return ("WM_SETHOTKEY");
3757 case WM_GETHOTKEY: return ("WM_GETHOTKEY");
3758 case WM_QUERYDRAGICON: return ("WM_QUERYDRAGICON");
3759 case WM_COMPAREITEM: return ("WM_COMPAREITEM");
3760 case WM_COMPACTING: return ("WM_COMPACTING");
3761 case WM_COMMNOTIFY: return ("WM_COMMNOTIFY");
3762 case WM_WINDOWPOSCHANGING: return ("WM_WINDOWPOSCHANGING");
3763 case WM_WINDOWPOSCHANGED: return ("WM_WINDOWPOSCHANGED");
3764 case WM_POWER: return ("WM_POWER");
3765 case WM_COPYDATA: return ("WM_COPYDATA");
3766 case WM_CANCELJOURNAL: return ("WM_CANCELJOURNAL");
3767 case WM_NCCREATE: return ("WM_NCCREATE");
3768 case WM_NCDESTROY: return ("WM_NCDESTROY");
3769 case WM_NCCALCSIZE: return ("WM_NCCALCSIZE");
3770 case WM_NCHITTEST: return ("WM_NCHITTEST");
3771 case WM_NCPAINT: return ("WM_NCPAINT");
3772 case WM_NCACTIVATE: return ("WM_NCACTIVATE");
3773 case WM_GETDLGCODE: return ("WM_GETDLGCODE");
3774 case WM_NCMOUSEMOVE: return ("WM_NCMOUSEMOVE");
3775 case WM_NCLBUTTONDOWN: return ("WM_NCLBUTTONDOWN");
3776 case WM_NCLBUTTONUP: return ("WM_NCLBUTTONUP");
3777 case WM_NCLBUTTONDBLCLK: return ("WM_NCLBUTTONDBLCLK");
3778 case WM_NCRBUTTONDOWN: return ("WM_NCRBUTTONDOWN");
3779 case WM_NCRBUTTONUP: return ("WM_NCRBUTTONUP");
3780 case WM_NCRBUTTONDBLCLK: return ("WM_NCRBUTTONDBLCLK");
3781 case WM_NCMBUTTONDOWN: return ("WM_NCMBUTTONDOWN");
3782 case WM_NCMBUTTONUP: return ("WM_NCMBUTTONUP");
3783 case WM_NCMBUTTONDBLCLK: return ("WM_NCMBUTTONDBLCLK");
3784 case WM_KEYDOWN: return ("WM_KEYDOWN");
3785 case WM_KEYUP: return ("WM_KEYUP");
3786 case WM_CHAR: return ("WM_CHAR");
3787 case WM_DEADCHAR: return ("WM_DEADCHAR");
3788 case WM_SYSKEYDOWN: return ("WM_SYSKEYDOWN");
3789 case WM_SYSKEYUP: return ("WM_SYSKEYUP");
3790 case WM_SYSCHAR: return ("WM_SYSCHAR");
3791 case WM_SYSDEADCHAR: return ("WM_SYSDEADCHAR");
3792 case WM_KEYLAST: return ("WM_KEYLAST");
3793 case WM_INITDIALOG: return ("WM_INITDIALOG");
3794 case WM_COMMAND: return ("WM_COMMAND");
3795 case WM_SYSCOMMAND: return ("WM_SYSCOMMAND");
3796 case WM_TIMER: return ("WM_TIMER");
3797 case WM_HSCROLL: return ("WM_HSCROLL");
3798 case WM_VSCROLL: return ("WM_VSCROLL");
3799 case WM_INITMENU: return ("WM_INITMENU");
3800 case WM_INITMENUPOPUP: return ("WM_INITMENUPOPUP");
3801 case WM_MENUSELECT: return ("WM_MENUSELECT");
3802 case WM_MENUCHAR: return ("WM_MENUCHAR");
3803 case WM_ENTERIDLE: return ("WM_ENTERIDLE");
3804 case WM_CTLCOLORMSGBOX: return ("WM_CTLCOLORMSGBOX");
3805 case WM_CTLCOLOREDIT: return ("WM_CTLCOLOREDIT");
3806 case WM_CTLCOLORLISTBOX: return ("WM_CTLCOLORLISTBOX");
3807 case WM_CTLCOLORBTN: return ("WM_CTLCOLORBTN");
3808 case WM_CTLCOLORDLG: return ("WM_CTLCOLORDLG");
3809 case WM_CTLCOLORSCROLLBAR: return ("WM_CTLCOLORSCROLLBAR");
3810 case WM_CTLCOLORSTATIC: return ("WM_CTLCOLORSTATIC");
3811 case WM_MOUSEMOVE: return ("WM_MOUSEMOVE");
3812 case WM_LBUTTONDOWN: return ("WM_LBUTTONDOWN");
3813 case WM_LBUTTONUP: return ("WM_LBUTTONUP");
3814 case WM_LBUTTONDBLCLK: return ("WM_LBUTTONDBLCLK");
3815 case WM_RBUTTONDOWN: return ("WM_RBUTTONDOWN");
3816 case WM_RBUTTONUP: return ("WM_RBUTTONUP");
3817 case WM_RBUTTONDBLCLK: return ("WM_RBUTTONDBLCLK");
3818 case WM_MBUTTONDOWN: return ("WM_MBUTTONDOWN");
3819 case WM_MBUTTONUP: return ("WM_MBUTTONUP");
3820 case WM_MBUTTONDBLCLK: return ("WM_MBUTTONDBLCLK");
3821 case WM_PARENTNOTIFY: return ("WM_PARENTNOTIFY");
3822 case WM_ENTERMENULOOP: return ("WM_ENTERMENULOOP");
3823 case WM_EXITMENULOOP: return ("WM_EXITMENULOOP");
3824 case WM_MDICREATE: return ("WM_MDICREATE");
3825 case WM_MDIDESTROY: return ("WM_MDIDESTROY");
3826 case WM_MDIACTIVATE: return ("WM_MDIACTIVATE");
3827 case WM_MDIRESTORE: return ("WM_MDIRESTORE");
3828 case WM_MDINEXT: return ("WM_MDINEXT");
3829 case WM_MDIMAXIMIZE: return ("WM_MDIMAXIMIZE");
3830 case WM_MDITILE: return ("WM_MDITILE");
3831 case WM_MDICASCADE: return ("WM_MDICASCADE");
3832 case WM_MDIICONARRANGE: return ("WM_MDIICONARRANGE");
3833 case WM_MDIGETACTIVE: return ("WM_MDIGETACTIVE");
3834 case WM_MDISETMENU: return ("WM_MDISETMENU");
3835 case WM_ENTERSIZEMOVE: return ("WM_ENTERSIZEMOVE");
3836 case WM_EXITSIZEMOVE: return ("WM_EXITSIZEMOVE");
3837 case WM_DROPFILES: return ("WM_DROPFILES");
3838 case WM_MDIREFRESHMENU: return ("WM_MDIREFRESHMENU");
3839 case WM_CUT: return ("WM_CUT");
3840 case WM_COPY: return ("WM_COPY");
3841 case WM_PASTE: return ("WM_PASTE");
3842 case WM_CLEAR: return ("WM_CLEAR");
3843 case WM_UNDO: return ("WM_UNDO");
3844 case WM_RENDERFORMAT: return ("WM_RENDERFORMAT");
3845 case WM_RENDERALLFORMATS: return ("WM_RENDERALLFORMATS");
3846 case WM_DESTROYCLIPBOARD: return ("WM_DESTROYCLIPBOARD");
3847 case WM_DRAWCLIPBOARD: return ("WM_DRAWCLIPBOARD");
3848 case WM_PAINTCLIPBOARD: return ("WM_PAINTCLIPBOARD");
3849 case WM_VSCROLLCLIPBOARD: return ("WM_VSCROLLCLIPBOARD");
3850 case WM_SIZECLIPBOARD: return ("WM_SIZECLIPBOARD");
3851 case WM_ASKCBFORMATNAME: return ("WM_ASKCBFORMATNAME");
3852 case WM_CHANGECBCHAIN: return ("WM_CHANGECBCHAIN");
3853 case WM_HSCROLLCLIPBOARD: return ("WM_HSCROLLCLIPBOARD");
3854 case WM_QUERYNEWPALETTE: return ("WM_QUERYNEWPALETTE");
3855 case WM_PALETTEISCHANGING: return ("WM_PALETTEISCHANGING");
3856 case WM_PALETTECHANGED: return ("WM_PALETTECHANGED");
3857 case WM_HOTKEY: return ("WM_HOTKEY");
3858 case WM_PENWINFIRST: return ("WM_PENWINFIRST");
3859 case WM_PENWINLAST: return ("WM_PENWINLAST");
3860
3861 #if(WINVER >= 0x0400)
3862 case WM_NOTIFY: return ("WM_NOTIFY");
3863 case WM_INPUTLANGCHANGEREQUEST: return ("WM_INPUTLANGCHANGEREQUEST");
3864 case WM_INPUTLANGCHANGE: return ("WM_INPUTLANGCHANGE");
3865 case WM_TCARD: return ("WM_TCARD");
3866 case WM_HELP: return ("WM_HELP");
3867 case WM_USERCHANGED: return ("WM_USERCHANGED");
3868 case WM_NOTIFYFORMAT: return ("WM_NOTIFYFORMAT");
3869 case WM_CONTEXTMENU: return ("WM_CONTEXTMENU");
3870 case WM_STYLECHANGING: return ("WM_STYLECHANGING");
3871 case WM_STYLECHANGED: return ("WM_STYLECHANGED");
3872 case WM_DISPLAYCHANGE: return ("WM_DISPLAYCHANGE");
3873 case WM_GETICON: return ("WM_GETICON");
3874 case WM_SETICON: return ("WM_SETICON");
3875 case WM_IME_STARTCOMPOSITION: return ("WM_IME_STARTCOMPOSITION");
3876 case WM_IME_ENDCOMPOSITION: return ("WM_IME_ENDCOMPOSITION");
3877 case WM_IME_COMPOSITION: return ("WM_IME_COMPOSITION");
3878 case WM_NEXTMENU: return ("WM_NEXTMENU");
3879 case WM_SIZING: return ("WM_SIZING");
3880 case WM_CAPTURECHANGED: return ("WM_CAPTURECHANGED");
3881 case WM_MOVING: return ("WM_MOVING");
3882 case WM_POWERBROADCAST: return ("WM_POWERBROADCAST");
3883 case WM_DEVICECHANGE: return ("WM_DEVICECHANGE");
3884 case WM_IME_SETCONTEXT: return ("WM_IME_SETCONTEXT");
3885 case WM_IME_NOTIFY: return ("WM_IME_NOTIFY");
3886 case WM_IME_CONTROL: return ("WM_IME_CONTROL");
3887 case WM_IME_COMPOSITIONFULL: return ("WM_IME_COMPOSITIONFULL");
3888 case WM_IME_SELECT: return ("WM_IME_SELECT");
3889 case WM_IME_CHAR: return ("WM_IME_CHAR");
3890 case WM_IME_KEYDOWN: return ("WM_IME_KEYDOWN");
3891 case WM_IME_KEYUP: return ("WM_IME_KEYUP");
3892 case WM_PRINT: return ("WM_PRINT");
3893 case WM_PRINTCLIENT: return ("WM_PRINTCLIENT");
3894 case WM_HANDHELDFIRST: return ("WM_HANDHELDFIRST");
3895 case WM_HANDHELDLAST: return ("WM_HANDHELDLAST");
3896 case WM_AFXFIRST: return ("WM_AFXFIRST");
3897 case WM_AFXLAST: return ("WM_AFXLAST");
3898 case WM_APP: return ("WM_APP");
3899 #endif /* WINVER >= 0x0400 */
3900 case SCREEN_WRITE: return ("SCREEN_WRITE");
3901 case SCREEN_SETPOSITION: return ("SCREEN_SETPOSITION");
3902 case SCREEN_GETPOSITION: return ("SCREEN_GETPOSITION");
3903 case SCREEN_SETATTRIBUTE: return ("SCREEN_SETATTRIBUTE");
3904 case SCREEN_GETATTRIBUTE: return ("SCREEN_GETATTRIBUTE");
3905 case SCREEN_PEEKEVENT: return ("SCREEN_PEEKEVENT");
3906 case SCREEN_READEVENT: return ("SCREEN_READEVENT");
3907 case SCREEN_SETMODES: return ("SCREEN_SETMODES");
3908 case SCREEN_GETMODES: return ("SCREEN_GETMODES");
3909 case SCREEN_SETCOMMAND: return ("SCREEN_SETCOMMAND");
3910 case SCREEN_GETCOMMAND: return ("SCREEN_GETCOMMAND");
3911 case SCREEN_SETBINDING: return ("SCREEN_SETBINDING");
3912 case SCREEN_GETBINDING: return ("SCREEN_GETBINDING");
3913 case SCREEN_SETMENU: return ("SCREEN_SETMENU");
3914 case SCREEN_READ: return ("SCREEN_READ");
3915 case SCREEN_CLEAR: return ("SCREEN_CLEAR");
3916 case WM_CATATONIC: return ("WM_CATATONIC");
3917 case WM_SCHEME_INTERRUPT: return ("WM_SCHEME_INTERRUPT");
3918 default: return (0);
3919 }
3920 }
3921