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