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