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