]> code.delx.au - gnu-emacs/blob - src/w32console.c
*** empty log message ***
[gnu-emacs] / src / w32console.c
1 /* Terminal hooks for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1992, 1999, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Tim Fleehart (apollo@online.com) 1-17-92
23 Geoff Voelker (voelker@cs.washington.edu) 9-12-93
24 */
25
26
27 #include <config.h>
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <windows.h>
32 #include <string.h>
33
34 #include "lisp.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "disptab.h"
38 #include "termhooks.h"
39 #include "dispextern.h"
40 /* Disable features in frame.h that require a Window System. */
41 #undef HAVE_WINDOW_SYSTEM
42 #include "frame.h"
43 #include "w32inevt.h"
44
45 /* from window.c */
46 extern Lisp_Object Frecenter ();
47
48 /* from keyboard.c */
49 extern int detect_input_pending ();
50
51 /* from sysdep.c */
52 extern int read_input_pending ();
53
54 extern struct frame * updating_frame;
55 extern int meta_key;
56
57 static void w32con_move_cursor (int row, int col);
58 static void w32con_clear_to_end (void);
59 static void w32con_clear_frame (void);
60 static void w32con_clear_end_of_line (int);
61 static void w32con_ins_del_lines (int vpos, int n);
62 static void w32con_insert_glyphs (struct glyph *start, int len);
63 static void w32con_write_glyphs (struct glyph *string, int len);
64 static void w32con_delete_glyphs (int n);
65 void w32_sys_ring_bell (void);
66 static void w32con_reset_terminal_modes (void);
67 static void w32con_set_terminal_modes (void);
68 static void w32con_set_terminal_window (int size);
69 static void w32con_update_begin (struct frame * f);
70 static void w32con_update_end (struct frame * f);
71 static WORD w32_face_attributes (struct frame *f, int face_id);
72
73 static COORD cursor_coords;
74 static HANDLE prev_screen, cur_screen;
75 static WORD char_attr_normal;
76 static DWORD prev_console_mode;
77
78 #ifndef USE_SEPARATE_SCREEN
79 static CONSOLE_CURSOR_INFO prev_console_cursor;
80 #endif
81
82 /* Determine whether to make frame dimensions match the screen buffer,
83 or the current window size. The former is desirable when running
84 over telnet, while the latter is more useful when working directly at
85 the console with a large scroll-back buffer. */
86 int w32_use_full_screen_buffer;
87 HANDLE keyboard_handle;
88
89
90 /* Setting this as the ctrl handler prevents emacs from being killed when
91 someone hits ^C in a 'suspended' session (child shell).
92 Also ignore Ctrl-Break signals. */
93
94 BOOL
95 ctrl_c_handler (unsigned long type)
96 {
97 /* Only ignore "interrupt" events when running interactively. */
98 return (!noninteractive
99 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
100 }
101
102 /* If we're updating a frame, use it as the current frame
103 Otherwise, use the selected frame. */
104 #define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
105
106 /* Move the cursor to (row, col). */
107 static void
108 w32con_move_cursor (int row, int col)
109 {
110 cursor_coords.X = col;
111 cursor_coords.Y = row;
112
113 if (updating_frame == (struct frame *) NULL)
114 {
115 SetConsoleCursorPosition (cur_screen, cursor_coords);
116 }
117 }
118
119 /* Clear from cursor to end of screen. */
120 static void
121 w32con_clear_to_end (void)
122 {
123 struct frame * f = PICK_FRAME ();
124
125 w32con_clear_end_of_line (FRAME_COLS (f) - 1);
126 w32con_ins_del_lines (cursor_coords.Y, FRAME_LINES (f) - cursor_coords.Y - 1);
127 }
128
129 /* Clear the frame. */
130 static void
131 w32con_clear_frame (void)
132 {
133 struct frame * f = PICK_FRAME ();
134 COORD dest;
135 int n;
136 DWORD r;
137 CONSOLE_SCREEN_BUFFER_INFO info;
138
139 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
140
141 /* Remember that the screen buffer might be wider than the window. */
142 n = FRAME_LINES (f) * info.dwSize.X;
143 dest.X = dest.Y = 0;
144
145 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
146 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
147
148 w32con_move_cursor (0, 0);
149 }
150
151
152 static struct glyph glyph_base[256];
153 static BOOL ceol_initialized = FALSE;
154
155 /* Clear from Cursor to end (what's "standout marker"?). */
156 static void
157 w32con_clear_end_of_line (int end)
158 {
159 if (!ceol_initialized)
160 {
161 int i;
162 for (i = 0; i < 256; i++)
163 {
164 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
165 }
166 ceol_initialized = TRUE;
167 }
168 w32con_write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
169 }
170
171 /* Insert n lines at vpos. if n is negative delete -n lines. */
172 static void
173 w32con_ins_del_lines (int vpos, int n)
174 {
175 int i, nb;
176 SMALL_RECT scroll;
177 COORD dest;
178 CHAR_INFO fill;
179 struct frame * f = PICK_FRAME ();
180
181 if (n < 0)
182 {
183 scroll.Top = vpos - n;
184 scroll.Bottom = FRAME_LINES (f);
185 dest.Y = vpos;
186 }
187 else
188 {
189 scroll.Top = vpos;
190 scroll.Bottom = FRAME_LINES (f) - n;
191 dest.Y = vpos + n;
192 }
193 scroll.Left = 0;
194 scroll.Right = FRAME_COLS (f);
195
196 dest.X = 0;
197
198 fill.Char.AsciiChar = 0x20;
199 fill.Attributes = char_attr_normal;
200
201 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
202
203 /* Here we have to deal with a w32 console flake: If the scroll
204 region looks like abc and we scroll c to a and fill with d we get
205 cbd... if we scroll block c one line at a time to a, we get cdd...
206 Emacs expects cdd consistently... So we have to deal with that
207 here... (this also occurs scrolling the same way in the other
208 direction. */
209
210 if (n > 0)
211 {
212 if (scroll.Bottom < dest.Y)
213 {
214 for (i = scroll.Bottom; i < dest.Y; i++)
215 {
216 w32con_move_cursor (i, 0);
217 w32con_clear_end_of_line (FRAME_COLS (f));
218 }
219 }
220 }
221 else
222 {
223 nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
224
225 if (nb < scroll.Top)
226 {
227 for (i = nb; i < scroll.Top; i++)
228 {
229 w32con_move_cursor (i, 0);
230 w32con_clear_end_of_line (FRAME_COLS (f));
231 }
232 }
233 }
234
235 cursor_coords.X = 0;
236 cursor_coords.Y = vpos;
237 }
238
239 #undef LEFT
240 #undef RIGHT
241 #define LEFT 1
242 #define RIGHT 0
243
244 static void
245 scroll_line (int dist, int direction)
246 {
247 /* The idea here is to implement a horizontal scroll in one line to
248 implement delete and half of insert. */
249 SMALL_RECT scroll;
250 COORD dest;
251 CHAR_INFO fill;
252 struct frame * f = PICK_FRAME ();
253
254 scroll.Top = cursor_coords.Y;
255 scroll.Bottom = cursor_coords.Y;
256
257 if (direction == LEFT)
258 {
259 scroll.Left = cursor_coords.X + dist;
260 scroll.Right = FRAME_COLS (f) - 1;
261 }
262 else
263 {
264 scroll.Left = cursor_coords.X;
265 scroll.Right = FRAME_COLS (f) - dist - 1;
266 }
267
268 dest.X = cursor_coords.X;
269 dest.Y = cursor_coords.Y;
270
271 fill.Char.AsciiChar = 0x20;
272 fill.Attributes = char_attr_normal;
273
274 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
275 }
276
277
278 /* If start is zero insert blanks instead of a string at start ?. */
279 static void
280 w32con_insert_glyphs (register struct glyph *start, register int len)
281 {
282 scroll_line (len, RIGHT);
283
284 /* Move len chars to the right starting at cursor_coords, fill with blanks */
285 if (start)
286 {
287 /* Print the first len characters of start, cursor_coords.X adjusted
288 by write_glyphs. */
289
290 w32con_write_glyphs (start, len);
291 }
292 else
293 {
294 w32con_clear_end_of_line (cursor_coords.X + len);
295 }
296 }
297
298 extern unsigned char *encode_terminal_code P_ ((struct glyph *, int,
299 struct coding_system *));
300
301 static void
302 w32con_write_glyphs (register struct glyph *string, register int len)
303 {
304 int produced, consumed;
305 DWORD r;
306 struct frame * f = PICK_FRAME ();
307 WORD char_attr;
308 unsigned char *conversion_buffer;
309 struct coding_system *coding;
310
311 if (len <= 0)
312 return;
313
314 /* If terminal_coding does any conversion, use it, otherwise use
315 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
316 because it always return 1 if the member src_multibyte is 1. */
317 coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
318 ? &terminal_coding : &safe_terminal_coding);
319 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
320 the tail. */
321 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
322
323 while (len > 0)
324 {
325 /* Identify a run of glyphs with the same face. */
326 int face_id = string->face_id;
327 int n;
328
329 for (n = 1; n < len; ++n)
330 if (string[n].face_id != face_id)
331 break;
332
333 /* Turn appearance modes of the face of the run on. */
334 char_attr = w32_face_attributes (f, face_id);
335
336 if (n == len)
337 /* This is the last run. */
338 coding->mode |= CODING_MODE_LAST_BLOCK;
339 conversion_buffer = encode_terminal_code (string, n, coding);
340 if (coding->produced > 0)
341 {
342 /* Set the attribute for these characters. */
343 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
344 coding->produced, cursor_coords,
345 &r))
346 {
347 printf ("Failed writing console attributes: %d\n",
348 GetLastError ());
349 fflush (stdout);
350 }
351
352 /* Write the characters. */
353 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
354 coding->produced, cursor_coords,
355 &r))
356 {
357 printf ("Failed writing console characters: %d\n",
358 GetLastError ());
359 fflush (stdout);
360 }
361
362 cursor_coords.X += coding->produced;
363 w32con_move_cursor (cursor_coords.Y, cursor_coords.X);
364 }
365 len -= n;
366 string += n;
367 }
368 }
369
370
371 static void
372 w32con_delete_glyphs (int n)
373 {
374 /* delete chars means scroll chars from cursor_coords.X + n to
375 cursor_coords.X, anything beyond the edge of the screen should
376 come out empty... */
377
378 scroll_line (n, LEFT);
379 }
380
381 static unsigned int sound_type = 0xFFFFFFFF;
382 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
383
384 void
385 w32_sys_ring_bell (void)
386 {
387 if (sound_type == 0xFFFFFFFF)
388 {
389 Beep (666, 100);
390 }
391 else if (sound_type == MB_EMACS_SILENT)
392 {
393 /* Do nothing. */
394 }
395 else
396 MessageBeep (sound_type);
397 }
398
399 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
400 doc: /* Set the sound generated when the bell is rung.
401 SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
402 to use the corresponding system sound for the bell. The 'silent sound
403 prevents Emacs from making any sound at all.
404 SOUND is nil to use the normal beep. */)
405 (sound)
406 Lisp_Object sound;
407 {
408 CHECK_SYMBOL (sound);
409
410 if (NILP (sound))
411 sound_type = 0xFFFFFFFF;
412 else if (EQ (sound, intern ("asterisk")))
413 sound_type = MB_ICONASTERISK;
414 else if (EQ (sound, intern ("exclamation")))
415 sound_type = MB_ICONEXCLAMATION;
416 else if (EQ (sound, intern ("hand")))
417 sound_type = MB_ICONHAND;
418 else if (EQ (sound, intern ("question")))
419 sound_type = MB_ICONQUESTION;
420 else if (EQ (sound, intern ("ok")))
421 sound_type = MB_OK;
422 else if (EQ (sound, intern ("silent")))
423 sound_type = MB_EMACS_SILENT;
424 else
425 sound_type = 0xFFFFFFFF;
426
427 return sound;
428 }
429
430 static void
431 w32con_reset_terminal_modes (void)
432 {
433 #ifdef USE_SEPARATE_SCREEN
434 SetConsoleActiveScreenBuffer (prev_screen);
435 #else
436 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
437 #endif
438 SetConsoleMode (keyboard_handle, prev_console_mode);
439 }
440
441 static void
442 w32con_set_terminal_modes (void)
443 {
444 CONSOLE_CURSOR_INFO cci;
445
446 /* make cursor big and visible (100 on Win95 makes it disappear) */
447 cci.dwSize = 99;
448 cci.bVisible = TRUE;
449 (void) SetConsoleCursorInfo (cur_screen, &cci);
450
451 SetConsoleActiveScreenBuffer (cur_screen);
452
453 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
454
455 /* Initialize input mode: interrupt_input off, no flow control, allow
456 8 bit character input, standard quit char. */
457 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
458 }
459
460 /* hmmm... perhaps these let us bracket screen changes so that we can flush
461 clumps rather than one-character-at-a-time...
462
463 we'll start with not moving the cursor while an update is in progress. */
464 static void
465 w32con_update_begin (struct frame * f)
466 {
467 }
468
469 static void
470 w32con_update_end (struct frame * f)
471 {
472 SetConsoleCursorPosition (cur_screen, cursor_coords);
473 }
474
475 static void
476 w32con_set_terminal_window (int size)
477 {
478 }
479
480 /***********************************************************************
481 Faces
482 ***********************************************************************/
483
484
485 /* Turn appearances of face FACE_ID on tty frame F on. */
486
487 static WORD
488 w32_face_attributes (f, face_id)
489 struct frame *f;
490 int face_id;
491 {
492 WORD char_attr;
493 struct face *face = FACE_FROM_ID (f, face_id);
494
495 xassert (face != NULL);
496
497 char_attr = char_attr_normal;
498
499 if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
500 && face->foreground != FACE_TTY_DEFAULT_COLOR)
501 char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
502
503 if (face->background != FACE_TTY_DEFAULT_BG_COLOR
504 && face->background != FACE_TTY_DEFAULT_COLOR)
505 char_attr = (char_attr & 0xff0f) + ((face->background % 16) << 4);
506
507
508 /* NTEMACS_TODO: Faces defined during startup get both foreground
509 and background of 0. Need a better way around this - for now detect
510 the problem and invert one of the faces to make the text readable. */
511 if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
512 char_attr ^= 0x0007;
513
514 if (face->tty_reverse_p)
515 char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
516 + ((char_attr & 0x00f0) >> 4);
517
518 return char_attr;
519 }
520
521
522 /* Emulation of some X window features from xfns.c and xfaces.c. */
523
524 extern char unspecified_fg[], unspecified_bg[];
525
526
527 /* Given a color index, return its standard name. */
528 Lisp_Object
529 vga_stdcolor_name (int idx)
530 {
531 /* Standard VGA colors, in the order of their standard numbering
532 in the default VGA palette. */
533 static char *vga_colors[16] = {
534 "black", "blue", "green", "cyan", "red", "magenta", "brown",
535 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
536 "lightred", "lightmagenta", "yellow", "white"
537 };
538
539 extern Lisp_Object Qunspecified;
540
541 if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
542 return build_string (vga_colors[idx]);
543 else
544 return Qunspecified; /* meaning the default */
545 }
546
547 typedef int (*term_hook) ();
548
549 void
550 initialize_w32_display (void)
551 {
552 CONSOLE_SCREEN_BUFFER_INFO info;
553
554 cursor_to_hook = w32con_move_cursor;
555 raw_cursor_to_hook = w32con_move_cursor;
556 clear_to_end_hook = w32con_clear_to_end;
557 clear_frame_hook = w32con_clear_frame;
558 clear_end_of_line_hook = w32con_clear_end_of_line;
559 ins_del_lines_hook = w32con_ins_del_lines;
560 insert_glyphs_hook = w32con_insert_glyphs;
561 write_glyphs_hook = w32con_write_glyphs;
562 delete_glyphs_hook = w32con_delete_glyphs;
563 ring_bell_hook = w32_sys_ring_bell;
564 reset_terminal_modes_hook = w32con_reset_terminal_modes;
565 set_terminal_modes_hook = w32con_set_terminal_modes;
566 set_terminal_window_hook = w32con_set_terminal_window;
567 update_begin_hook = w32con_update_begin;
568 update_end_hook = w32con_update_end;
569
570 read_socket_hook = w32_console_read_socket;
571 mouse_position_hook = w32_console_mouse_position;
572
573 /* Initialize interrupt_handle. */
574 init_crit ();
575
576 /* Remember original console settings. */
577 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
578 GetConsoleMode (keyboard_handle, &prev_console_mode);
579
580 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
581
582 #ifdef USE_SEPARATE_SCREEN
583 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
584 0, NULL,
585 CONSOLE_TEXTMODE_BUFFER,
586 NULL);
587
588 if (cur_screen == INVALID_HANDLE_VALUE)
589 {
590 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
591 printf ("LastError = 0x%lx\n", GetLastError ());
592 fflush (stdout);
593 exit (0);
594 }
595 #else
596 cur_screen = prev_screen;
597 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
598 #endif
599
600 /* Respect setting of LINES and COLUMNS environment variables. */
601 {
602 char * lines = getenv("LINES");
603 char * columns = getenv("COLUMNS");
604
605 if (lines != NULL && columns != NULL)
606 {
607 SMALL_RECT new_win_dims;
608 COORD new_size;
609
610 new_size.X = atoi (columns);
611 new_size.Y = atoi (lines);
612
613 GetConsoleScreenBufferInfo (cur_screen, &info);
614
615 /* Shrink the window first, so the buffer dimensions can be
616 reduced if necessary. */
617 new_win_dims.Top = 0;
618 new_win_dims.Left = 0;
619 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
620 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
621 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
622
623 SetConsoleScreenBufferSize (cur_screen, new_size);
624
625 /* Set the window size to match the buffer dimension. */
626 new_win_dims.Top = 0;
627 new_win_dims.Left = 0;
628 new_win_dims.Bottom = new_size.Y - 1;
629 new_win_dims.Right = new_size.X - 1;
630 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
631 }
632 }
633
634 GetConsoleScreenBufferInfo (cur_screen, &info);
635
636 meta_key = 1;
637 char_attr_normal = info.wAttributes;
638
639 /* Determine if the info returned by GetConsoleScreenBufferInfo
640 is realistic. Old MS Telnet servers used to only fill out
641 the dwSize portion, even modern one fill the whole struct with
642 garbage when using non-MS telnet clients. */
643 if ((w32_use_full_screen_buffer
644 && (info.dwSize.Y < 20 || info.dwSize.Y > 100
645 || info.dwSize.X < 40 || info.dwSize.X > 200))
646 || (!w32_use_full_screen_buffer
647 && (info.srWindow.Bottom - info.srWindow.Top < 20
648 || info.srWindow.Bottom - info.srWindow.Top > 100
649 || info.srWindow.Right - info.srWindow.Left < 40
650 || info.srWindow.Right - info.srWindow.Left > 100)))
651 {
652 FRAME_LINES (SELECTED_FRAME ()) = 25;
653 SET_FRAME_COLS (SELECTED_FRAME (), 80);
654 }
655
656 else if (w32_use_full_screen_buffer)
657 {
658 FRAME_LINES (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
659 SET_FRAME_COLS (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
660 }
661 else
662 {
663 /* Lines per page. Use buffer coords instead of buffer size. */
664 FRAME_LINES (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
665 info.srWindow.Top;
666 /* Characters per line. Use buffer coords instead of buffer size. */
667 SET_FRAME_COLS (SELECTED_FRAME (), 1 + info.srWindow.Right -
668 info.srWindow.Left);
669 }
670
671 /* Setup w32_display_info structure for this frame. */
672
673 w32_initialize_display_info (build_string ("Console"));
674
675 }
676
677 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
678 doc: /* Set screen colors. */)
679 (foreground, background)
680 Lisp_Object foreground;
681 Lisp_Object background;
682 {
683 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
684
685 Frecenter (Qnil);
686 return Qt;
687 }
688
689 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
690 doc: /* Set cursor size. */)
691 (size)
692 Lisp_Object size;
693 {
694 CONSOLE_CURSOR_INFO cci;
695 cci.dwSize = XFASTINT (size);
696 cci.bVisible = TRUE;
697 (void) SetConsoleCursorInfo (cur_screen, &cci);
698
699 return Qt;
700 }
701
702 void
703 syms_of_ntterm ()
704 {
705 DEFVAR_BOOL ("w32-use-full-screen-buffer",
706 &w32_use_full_screen_buffer,
707 doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
708 This is desirable when running Emacs over telnet, and is the default.
709 A value of nil means use the current console window dimensions; this
710 may be preferrable when working directly at the console with a large
711 scroll-back buffer. */);
712 w32_use_full_screen_buffer = 0;
713
714 defsubr (&Sset_screen_color);
715 defsubr (&Sset_cursor_size);
716 defsubr (&Sset_message_beep);
717 }
718
719 /* arch-tag: a390a07f-f661-42bc-aeb4-e6d8bf860337
720 (do not change this comment) */