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