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