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