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