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