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