* server.el (server-start, server-unload-hook): Undo previous
[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"
b93b26cb 38/* Disable features in frame.h that require a Window System. */
65fb143c
JR
39#undef HAVE_WINDOW_SYSTEM
40#include "frame.h"
1c30a66f
JR
41#include "termhooks.h"
42#include "termchar.h"
43#include "dispextern.h"
489f9371 44#include "w32inevt.h"
6cdfb6e6 45
0534d577 46/* from window.c */
6cdfb6e6
RS
47extern Lisp_Object Frecenter ();
48
49/* from keyboard.c */
50extern int detect_input_pending ();
51
52/* from sysdep.c */
53extern int read_input_pending ();
54
1c30a66f
JR
55static void w32con_move_cursor (struct frame *f, int row, int col);
56static void w32con_clear_to_end (struct frame *f);
57static void w32con_clear_frame (struct frame *f);
58static void w32con_clear_end_of_line (struct frame *f, int);
59static void w32con_ins_del_lines (struct frame *f, int vpos, int n);
60static void w32con_insert_glyphs (struct frame *f, struct glyph *start, int len);
61static void w32con_write_glyphs (struct frame *f, struct glyph *string, int len);
62static void w32con_delete_glyphs (struct frame *f, int n);
63static void w32con_reset_terminal_modes (struct terminal *t);
64static void w32con_set_terminal_modes (struct terminal *t);
65static void w32con_set_terminal_window (struct frame *f, int size);
7cb010ed
JR
66static void w32con_update_begin (struct frame * f);
67static void w32con_update_end (struct frame * f);
338b1bb2 68static WORD w32_face_attributes (struct frame *f, int face_id);
6cdfb6e6 69
338b1bb2
JR
70static COORD cursor_coords;
71static HANDLE prev_screen, cur_screen;
72static WORD char_attr_normal;
73static DWORD prev_console_mode;
6cdfb6e6 74
3e671d90 75#ifndef USE_SEPARATE_SCREEN
338b1bb2 76static CONSOLE_CURSOR_INFO prev_console_cursor;
3e671d90
GV
77#endif
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
AI
293 int produced, consumed;
294 DWORD r;
338b1bb2 295 WORD char_attr;
853895f6
KH
296 unsigned char *conversion_buffer;
297 struct coding_system *coding;
338b1bb2
JR
298
299 if (len <= 0)
300 return;
b47278e1 301
853895f6
KH
302 /* If terminal_coding does any conversion, use it, otherwise use
303 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
304 because it always return 1 if the member src_multibyte is 1. */
1c30a66f
JR
305 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
306 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
8c2ac482
JR
307 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
308 the tail. */
1c30a66f 309 coding->mode &= ~CODING_MODE_LAST_BLOCK;
6cdfb6e6 310
8c2ac482 311 while (len > 0)
6cdfb6e6 312 {
8c2ac482
JR
313 /* Identify a run of glyphs with the same face. */
314 int face_id = string->face_id;
315 int n;
177c0ea7 316
8c2ac482
JR
317 for (n = 1; n < len; ++n)
318 if (string[n].face_id != face_id)
319 break;
320
321 /* Turn appearance modes of the face of the run on. */
338b1bb2 322 char_attr = w32_face_attributes (f, face_id);
8c2ac482 323
853895f6
KH
324 if (n == len)
325 /* This is the last run. */
326 coding->mode |= CODING_MODE_LAST_BLOCK;
327 conversion_buffer = encode_terminal_code (string, n, coding);
328 if (coding->produced > 0)
329 {
330 /* Set the attribute for these characters. */
331 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
332 coding->produced, cursor_coords,
333 &r))
8c2ac482 334 {
853895f6
KH
335 printf ("Failed writing console attributes: %d\n",
336 GetLastError ());
337 fflush (stdout);
338 }
339
340 /* Write the characters. */
341 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
342 coding->produced, cursor_coords,
343 &r))
344 {
345 printf ("Failed writing console characters: %d\n",
346 GetLastError ());
347 fflush (stdout);
348 }
349
350 cursor_coords.X += coding->produced;
1c30a66f 351 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
853895f6
KH
352 }
353 len -= n;
354 string += n;
6cdfb6e6 355 }
6cdfb6e6
RS
356}
357
8c2ac482 358
7cb010ed 359static void
1c30a66f 360w32con_delete_glyphs (struct frame *f, int n)
6cdfb6e6 361{
177c0ea7
JB
362 /* delete chars means scroll chars from cursor_coords.X + n to
363 cursor_coords.X, anything beyond the edge of the screen should
6cdfb6e6
RS
364 come out empty... */
365
1c30a66f 366 scroll_line (f, n, LEFT);
6cdfb6e6
RS
367}
368
0534d577 369static unsigned int sound_type = 0xFFFFFFFF;
78859b80 370#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
0534d577 371
6cdfb6e6 372void
1c30a66f 373w32_sys_ring_bell (struct frame *f)
6cdfb6e6 374{
177c0ea7 375 if (sound_type == 0xFFFFFFFF)
78859b80 376 {
0534d577 377 Beep (666, 100);
78859b80
GV
378 }
379 else if (sound_type == MB_EMACS_SILENT)
380 {
381 /* Do nothing. */
382 }
0534d577 383 else
78859b80 384 MessageBeep (sound_type);
6cdfb6e6
RS
385}
386
0534d577 387DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
33f09670
JR
388 doc: /* Set the sound generated when the bell is rung.
389SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
390to use the corresponding system sound for the bell. The 'silent sound
391prevents Emacs from making any sound at all.
392SOUND is nil to use the normal beep. */)
0534d577
KH
393 (sound)
394 Lisp_Object sound;
6cdfb6e6 395{
b7826503 396 CHECK_SYMBOL (sound);
0534d577 397
177c0ea7 398 if (NILP (sound))
0534d577
KH
399 sound_type = 0xFFFFFFFF;
400 else if (EQ (sound, intern ("asterisk")))
401 sound_type = MB_ICONASTERISK;
177c0ea7 402 else if (EQ (sound, intern ("exclamation")))
0534d577 403 sound_type = MB_ICONEXCLAMATION;
177c0ea7 404 else if (EQ (sound, intern ("hand")))
0534d577 405 sound_type = MB_ICONHAND;
177c0ea7 406 else if (EQ (sound, intern ("question")))
0534d577 407 sound_type = MB_ICONQUESTION;
177c0ea7 408 else if (EQ (sound, intern ("ok")))
0534d577 409 sound_type = MB_OK;
78859b80
GV
410 else if (EQ (sound, intern ("silent")))
411 sound_type = MB_EMACS_SILENT;
0534d577
KH
412 else
413 sound_type = 0xFFFFFFFF;
414
415 return sound;
6cdfb6e6 416}
177c0ea7 417
7cb010ed 418static void
1c30a66f 419w32con_reset_terminal_modes (struct terminal *t)
6cdfb6e6 420{
3e671d90 421#ifdef USE_SEPARATE_SCREEN
6cdfb6e6 422 SetConsoleActiveScreenBuffer (prev_screen);
3e671d90
GV
423#else
424 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
425#endif
426 SetConsoleMode (keyboard_handle, prev_console_mode);
6cdfb6e6
RS
427}
428
7cb010ed 429static void
1c30a66f 430w32con_set_terminal_modes (struct terminal *t)
6cdfb6e6
RS
431{
432 CONSOLE_CURSOR_INFO cci;
433
3e671d90
GV
434 /* make cursor big and visible (100 on Win95 makes it disappear) */
435 cci.dwSize = 99;
436 cci.bVisible = TRUE;
437 (void) SetConsoleCursorInfo (cur_screen, &cci);
6cdfb6e6 438
3e671d90 439 SetConsoleActiveScreenBuffer (cur_screen);
6cdfb6e6 440
3e671d90 441 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
6cdfb6e6 442
3e671d90
GV
443 /* Initialize input mode: interrupt_input off, no flow control, allow
444 8 bit character input, standard quit char. */
445 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6cdfb6e6
RS
446}
447
448/* hmmm... perhaps these let us bracket screen changes so that we can flush
449 clumps rather than one-character-at-a-time...
177c0ea7 450
6cdfb6e6 451 we'll start with not moving the cursor while an update is in progress. */
7cb010ed
JR
452static void
453w32con_update_begin (struct frame * f)
6cdfb6e6
RS
454{
455}
456
7cb010ed
JR
457static void
458w32con_update_end (struct frame * f)
6cdfb6e6
RS
459{
460 SetConsoleCursorPosition (cur_screen, cursor_coords);
461}
462
7cb010ed 463static void
1c30a66f 464w32con_set_terminal_window (struct frame *f, int size)
6cdfb6e6
RS
465{
466}
467
8c2ac482
JR
468/***********************************************************************
469 Faces
470 ***********************************************************************/
471
472
473/* Turn appearances of face FACE_ID on tty frame F on. */
474
338b1bb2
JR
475static WORD
476w32_face_attributes (f, face_id)
8c2ac482
JR
477 struct frame *f;
478 int face_id;
479{
338b1bb2 480 WORD char_attr;
8c2ac482
JR
481 struct face *face = FACE_FROM_ID (f, face_id);
482
483 xassert (face != NULL);
484
485 char_attr = char_attr_normal;
486
338b1bb2
JR
487 if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
488 && face->foreground != FACE_TTY_DEFAULT_COLOR)
489 char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
490
491 if (face->background != FACE_TTY_DEFAULT_BG_COLOR
492 && face->background != FACE_TTY_DEFAULT_COLOR)
177c0ea7 493 char_attr = (char_attr & 0xff0f) + ((face->background % 16) << 4);
338b1bb2 494
8c2ac482 495
b93b26cb
JR
496 /* NTEMACS_TODO: Faces defined during startup get both foreground
497 and background of 0. Need a better way around this - for now detect
498 the problem and invert one of the faces to make the text readable. */
338b1bb2
JR
499 if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
500 char_attr ^= 0x0007;
8c2ac482 501
e850a615 502 if (face->tty_reverse_p)
338b1bb2
JR
503 char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
504 + ((char_attr & 0x00f0) >> 4);
8c2ac482 505
338b1bb2 506 return char_attr;
8c2ac482
JR
507}
508
509
338b1bb2 510/* Emulation of some X window features from xfns.c and xfaces.c. */
8c2ac482 511
338b1bb2
JR
512extern char unspecified_fg[], unspecified_bg[];
513
514
515/* Given a color index, return its standard name. */
516Lisp_Object
517vga_stdcolor_name (int idx)
8c2ac482 518{
338b1bb2
JR
519 /* Standard VGA colors, in the order of their standard numbering
520 in the default VGA palette. */
521 static char *vga_colors[16] = {
522 "black", "blue", "green", "cyan", "red", "magenta", "brown",
523 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
524 "lightred", "lightmagenta", "yellow", "white"
525 };
526
527 extern Lisp_Object Qunspecified;
528
529 if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
530 return build_string (vga_colors[idx]);
531 else
532 return Qunspecified; /* meaning the default */
8c2ac482 533}
338b1bb2 534
6cdfb6e6
RS
535typedef int (*term_hook) ();
536
537void
79af260e 538initialize_w32_display (struct terminal *term)
6cdfb6e6
RS
539{
540 CONSOLE_SCREEN_BUFFER_INFO info;
1c30a66f
JR
541
542 term->cursor_to_hook = w32con_move_cursor;
543 term->raw_cursor_to_hook = w32con_move_cursor;
544 term->clear_to_end_hook = w32con_clear_to_end;
545 term->clear_frame_hook = w32con_clear_frame;
546 term->clear_end_of_line_hook = w32con_clear_end_of_line;
547 term->ins_del_lines_hook = w32con_ins_del_lines;
548 term->insert_glyphs_hook = w32con_insert_glyphs;
549 term->write_glyphs_hook = w32con_write_glyphs;
550 term->delete_glyphs_hook = w32con_delete_glyphs;
551 term->ring_bell_hook = w32_sys_ring_bell;
552 term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
553 term->set_terminal_modes_hook = w32con_set_terminal_modes;
554 term->set_terminal_window_hook = w32con_set_terminal_window;
555 term->update_begin_hook = w32con_update_begin;
556 term->update_end_hook = w32con_update_end;
557
558 term->read_socket_hook = w32_console_read_socket;
559 term->mouse_position_hook = w32_console_mouse_position;
3e671d90 560
c1e06681
AI
561 /* Initialize interrupt_handle. */
562 init_crit ();
563
3e671d90
GV
564 /* Remember original console settings. */
565 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
566 GetConsoleMode (keyboard_handle, &prev_console_mode);
567
6cdfb6e6 568 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
177c0ea7 569
3e671d90
GV
570#ifdef USE_SEPARATE_SCREEN
571 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
572 0, NULL,
573 CONSOLE_TEXTMODE_BUFFER,
574 NULL);
575
576 if (cur_screen == INVALID_HANDLE_VALUE)
577 {
578 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
579 printf ("LastError = 0x%lx\n", GetLastError ());
580 fflush (stdout);
581 exit (0);
582 }
583#else
584 cur_screen = prev_screen;
585 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
586#endif
587
191100f2
AI
588 /* Respect setting of LINES and COLUMNS environment variables. */
589 {
590 char * lines = getenv("LINES");
591 char * columns = getenv("COLUMNS");
592
593 if (lines != NULL && columns != NULL)
594 {
595 SMALL_RECT new_win_dims;
596 COORD new_size;
597
598 new_size.X = atoi (columns);
599 new_size.Y = atoi (lines);
600
601 GetConsoleScreenBufferInfo (cur_screen, &info);
602
603 /* Shrink the window first, so the buffer dimensions can be
604 reduced if necessary. */
605 new_win_dims.Top = 0;
606 new_win_dims.Left = 0;
607 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
608 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
609 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
610
611 SetConsoleScreenBufferSize (cur_screen, new_size);
612
613 /* Set the window size to match the buffer dimension. */
614 new_win_dims.Top = 0;
615 new_win_dims.Left = 0;
616 new_win_dims.Bottom = new_size.Y - 1;
617 new_win_dims.Right = new_size.X - 1;
618 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
619 }
620 }
621
6cdfb6e6 622 GetConsoleScreenBufferInfo (cur_screen, &info);
177c0ea7 623
338b1bb2 624 char_attr_normal = info.wAttributes;
938469f2 625
3fb1d72b
JR
626 /* Determine if the info returned by GetConsoleScreenBufferInfo
627 is realistic. Old MS Telnet servers used to only fill out
628 the dwSize portion, even modern one fill the whole struct with
629 garbage when using non-MS telnet clients. */
630 if ((w32_use_full_screen_buffer
631 && (info.dwSize.Y < 20 || info.dwSize.Y > 100
632 || info.dwSize.X < 40 || info.dwSize.X > 200))
633 || (!w32_use_full_screen_buffer
634 && (info.srWindow.Bottom - info.srWindow.Top < 20
635 || info.srWindow.Bottom - info.srWindow.Top > 100
636 || info.srWindow.Right - info.srWindow.Left < 40
637 || info.srWindow.Right - info.srWindow.Left > 100)))
638 {
639 FRAME_LINES (SELECTED_FRAME ()) = 25;
640 SET_FRAME_COLS (SELECTED_FRAME (), 80);
641 }
642
643 else if (w32_use_full_screen_buffer)
191100f2 644 {
90022f5a
KS
645 FRAME_LINES (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
646 SET_FRAME_COLS (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
191100f2
AI
647 }
648 else
649 {
650 /* Lines per page. Use buffer coords instead of buffer size. */
90022f5a 651 FRAME_LINES (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
177c0ea7 652 info.srWindow.Top;
191100f2 653 /* Characters per line. Use buffer coords instead of buffer size. */
90022f5a 654 SET_FRAME_COLS (SELECTED_FRAME (), 1 + info.srWindow.Right -
191100f2
AI
655 info.srWindow.Left);
656 }
65fb143c
JR
657
658 /* Setup w32_display_info structure for this frame. */
659
660 w32_initialize_display_info (build_string ("Console"));
661
6cdfb6e6
RS
662}
663
1c30a66f
JR
664/* Initialize the tty-dependent part of frame F. The frame must
665 already have its device initialized. */
666void
667create_w32cons_output(struct frame *f)
668{
669 struct tty_output *tty;
670
671 if (! FRAME_TERMCAP_P (f))
672 abort ();
673
674 tty = xmalloc (sizeof (struct tty_output));
675 bzero (tty, sizeof (struct tty_output));
676
677 tty->display_info = FRAME_TERMINAL (f)->display_info.tty;
678 tty->display_info->meta_key = 1;
679
680 f->output_data.tty = tty;
681}
682
6cdfb6e6 683DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
33f09670 684 doc: /* Set screen colors. */)
6cdfb6e6
RS
685 (foreground, background)
686 Lisp_Object foreground;
687 Lisp_Object background;
688{
689 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
6cdfb6e6
RS
690
691 Frecenter (Qnil);
692 return Qt;
693}
694
695DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
33f09670 696 doc: /* Set cursor size. */)
6cdfb6e6
RS
697 (size)
698 Lisp_Object size;
699{
700 CONSOLE_CURSOR_INFO cci;
701 cci.dwSize = XFASTINT (size);
702 cci.bVisible = TRUE;
703 (void) SetConsoleCursorInfo (cur_screen, &cci);
177c0ea7 704
6cdfb6e6
RS
705 return Qt;
706}
707
0534d577 708void
6cdfb6e6
RS
709syms_of_ntterm ()
710{
191100f2
AI
711 DEFVAR_BOOL ("w32-use-full-screen-buffer",
712 &w32_use_full_screen_buffer,
33f09670 713 doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
639804b3 714This is desirable when running Emacs over telnet.
33f09670
JR
715A value of nil means use the current console window dimensions; this
716may be preferrable when working directly at the console with a large
717scroll-back buffer. */);
3fb1d72b 718 w32_use_full_screen_buffer = 0;
191100f2 719
6cdfb6e6
RS
720 defsubr (&Sset_screen_color);
721 defsubr (&Sset_cursor_size);
0534d577 722 defsubr (&Sset_message_beep);
6cdfb6e6 723}
ab5796a9
MB
724
725/* arch-tag: a390a07f-f661-42bc-aeb4-e6d8bf860337
726 (do not change this comment) */