Turn off text cursor when dropping down menus.
[bpt/emacs.git] / src / w32console.c
1 /* Terminal hooks for GNU Emacs on the Microsoft Windows API.
2 Copyright (C) 1992, 1999, 2001-2013 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19 /*
20 Tim Fleehart (apollo@online.com) 1-17-92
21 Geoff Voelker (voelker@cs.washington.edu) 9-12-93
22 */
23
24
25 #include <config.h>
26
27 #include <stdio.h>
28 #include <windows.h>
29
30 #include "lisp.h"
31 #include "character.h"
32 #include "coding.h"
33 #include "disptab.h"
34 #include "frame.h"
35 #include "window.h"
36 #include "termhooks.h"
37 #include "termchar.h"
38 #include "dispextern.h"
39 #include "w32term.h"
40 #include "w32common.h" /* for os_subtype */
41 #include "w32inevt.h"
42
43 /* from window.c */
44 extern Lisp_Object Frecenter (Lisp_Object);
45
46 static void w32con_move_cursor (struct frame *f, int row, int col);
47 static void w32con_clear_to_end (struct frame *f);
48 static void w32con_clear_frame (struct frame *f);
49 static void w32con_clear_end_of_line (struct frame *f, int);
50 static void w32con_ins_del_lines (struct frame *f, int vpos, int n);
51 static void w32con_insert_glyphs (struct frame *f, struct glyph *start, int len);
52 static void w32con_write_glyphs (struct frame *f, struct glyph *string, int len);
53 static void w32con_delete_glyphs (struct frame *f, int n);
54 static void w32con_reset_terminal_modes (struct terminal *t);
55 static void w32con_set_terminal_modes (struct terminal *t);
56 static void w32con_update_begin (struct frame * f);
57 static void w32con_update_end (struct frame * f);
58 static WORD w32_face_attributes (struct frame *f, int face_id);
59
60 static COORD cursor_coords;
61 static HANDLE prev_screen, cur_screen;
62 static WORD char_attr_normal;
63 static DWORD prev_console_mode;
64
65 static CONSOLE_CURSOR_INFO console_cursor_info;
66 #ifndef USE_SEPARATE_SCREEN
67 static CONSOLE_CURSOR_INFO prev_console_cursor;
68 #endif
69
70 HANDLE keyboard_handle;
71 int w32_console_unicode_input;
72
73
74 /* Setting this as the ctrl handler prevents emacs from being killed when
75 someone hits ^C in a 'suspended' session (child shell).
76 Also ignore Ctrl-Break signals. */
77
78 BOOL
79 ctrl_c_handler (unsigned long type)
80 {
81 /* Only ignore "interrupt" events when running interactively. */
82 return (!noninteractive
83 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
84 }
85
86
87 /* Move the cursor to (ROW, COL) on FRAME. */
88 static void
89 w32con_move_cursor (struct frame *f, int row, int col)
90 {
91 cursor_coords.X = col;
92 cursor_coords.Y = row;
93
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);
97 }
98
99 void
100 w32con_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
107 void
108 w32con_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
115 /* Clear from cursor to end of screen. */
116 static void
117 w32con_clear_to_end (struct frame *f)
118 {
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);
121 }
122
123 /* Clear the frame. */
124 static void
125 w32con_clear_frame (struct frame *f)
126 {
127 COORD dest;
128 int n;
129 DWORD r;
130 CONSOLE_SCREEN_BUFFER_INFO info;
131
132 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
133
134 /* Remember that the screen buffer might be wider than the window. */
135 n = FRAME_LINES (f) * info.dwSize.X;
136 dest.X = dest.Y = 0;
137
138 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
139 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
140
141 w32con_move_cursor (f, 0, 0);
142 }
143
144
145 static struct glyph glyph_base[256];
146 static BOOL ceol_initialized = FALSE;
147
148 /* Clear from Cursor to end (what's "standout marker"?). */
149 static void
150 w32con_clear_end_of_line (struct frame *f, int end)
151 {
152 if (!ceol_initialized)
153 {
154 int i;
155 for (i = 0; i < 256; i++)
156 {
157 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
158 }
159 ceol_initialized = TRUE;
160 }
161 w32con_write_glyphs (f, glyph_base, end - cursor_coords.X); /* fencepost ? */
162 }
163
164 /* Insert n lines at vpos. if n is negative delete -n lines. */
165 static void
166 w32con_ins_del_lines (struct frame *f, int vpos, int n)
167 {
168 int i, nb;
169 SMALL_RECT scroll;
170 SMALL_RECT clip;
171 COORD dest;
172 CHAR_INFO fill;
173
174 if (n < 0)
175 {
176 scroll.Top = vpos - n;
177 scroll.Bottom = FRAME_LINES (f);
178 dest.Y = vpos;
179 }
180 else
181 {
182 scroll.Top = vpos;
183 scroll.Bottom = FRAME_LINES (f) - n;
184 dest.Y = vpos + n;
185 }
186 clip.Top = clip.Left = scroll.Left = 0;
187 clip.Right = scroll.Right = FRAME_COLS (f);
188 clip.Bottom = FRAME_LINES (f);
189
190 dest.X = 0;
191
192 fill.Char.AsciiChar = 0x20;
193 fill.Attributes = char_attr_normal;
194
195 ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
196
197 /* Here we have to deal with a w32 console flake: If the scroll
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 {
210 w32con_move_cursor (f, i, 0);
211 w32con_clear_end_of_line (f, FRAME_COLS (f));
212 }
213 }
214 }
215 else
216 {
217 nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
218
219 if (nb < scroll.Top)
220 {
221 for (i = nb; i < scroll.Top; i++)
222 {
223 w32con_move_cursor (f, i, 0);
224 w32con_clear_end_of_line (f, FRAME_COLS (f));
225 }
226 }
227 }
228
229 cursor_coords.X = 0;
230 cursor_coords.Y = vpos;
231 }
232
233 #undef LEFT
234 #undef RIGHT
235 #define LEFT 1
236 #define RIGHT 0
237
238 static void
239 scroll_line (struct frame *f, int dist, int direction)
240 {
241 /* The idea here is to implement a horizontal scroll in one line to
242 implement delete and half of insert. */
243 SMALL_RECT scroll, clip;
244 COORD dest;
245 CHAR_INFO fill;
246
247 clip.Top = scroll.Top = clip.Bottom = scroll.Bottom = cursor_coords.Y;
248 clip.Left = 0;
249 clip.Right = FRAME_COLS (f);
250
251 if (direction == LEFT)
252 {
253 scroll.Left = cursor_coords.X + dist;
254 scroll.Right = FRAME_COLS (f) - 1;
255 }
256 else
257 {
258 scroll.Left = cursor_coords.X;
259 scroll.Right = FRAME_COLS (f) - dist - 1;
260 }
261
262 dest.X = cursor_coords.X;
263 dest.Y = cursor_coords.Y;
264
265 fill.Char.AsciiChar = 0x20;
266 fill.Attributes = char_attr_normal;
267
268 ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
269 }
270
271
272 /* If start is zero insert blanks instead of a string at start ?. */
273 static void
274 w32con_insert_glyphs (struct frame *f, register struct glyph *start,
275 register int len)
276 {
277 scroll_line (f, len, RIGHT);
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. */
284
285 w32con_write_glyphs (f, start, len);
286 }
287 else
288 {
289 w32con_clear_end_of_line (f, cursor_coords.X + len);
290 }
291 }
292
293 static void
294 w32con_write_glyphs (struct frame *f, register struct glyph *string,
295 register int len)
296 {
297 DWORD r;
298 WORD char_attr;
299 unsigned char *conversion_buffer;
300 struct coding_system *coding;
301
302 if (len <= 0)
303 return;
304
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. */
308 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
309 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
310 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
311 the tail. */
312 coding->mode &= ~CODING_MODE_LAST_BLOCK;
313
314 while (len > 0)
315 {
316 /* Identify a run of glyphs with the same face. */
317 int face_id = string->face_id;
318 int n;
319
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. */
325 char_attr = w32_face_attributes (f, face_id);
326
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))
337 {
338 printf ("Failed writing console attributes: %d\n",
339 GetLastError ());
340 fflush (stdout);
341 }
342
343 /* Write the characters. */
344 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
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;
354 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
355 }
356 len -= n;
357 string += n;
358 }
359 }
360
361 /* Used for mouse highlight. */
362 static void
363 w32con_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. */
409 void
410 tty_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 }
439
440 static void
441 w32con_delete_glyphs (struct frame *f, int n)
442 {
443 /* delete chars means scroll chars from cursor_coords.X + n to
444 cursor_coords.X, anything beyond the edge of the screen should
445 come out empty... */
446
447 scroll_line (f, n, LEFT);
448 }
449
450
451 static void
452 w32con_reset_terminal_modes (struct terminal *t)
453 {
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);
472
473 #ifdef USE_SEPARATE_SCREEN
474 SetConsoleActiveScreenBuffer (prev_screen);
475 #else
476 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
477 #endif
478
479 SetConsoleMode (keyboard_handle, prev_console_mode);
480 }
481
482 static void
483 w32con_set_terminal_modes (struct terminal *t)
484 {
485 CONSOLE_CURSOR_INFO cci;
486
487 /* make cursor big and visible (100 on Windows 95 makes it disappear) */
488 cci.dwSize = 99;
489 cci.bVisible = TRUE;
490 (void) SetConsoleCursorInfo (cur_screen, &cci);
491
492 SetConsoleActiveScreenBuffer (cur_screen);
493
494 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
495
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);
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...
503
504 we'll start with not moving the cursor while an update is in progress. */
505 static void
506 w32con_update_begin (struct frame * f)
507 {
508 }
509
510 static void
511 w32con_update_end (struct frame * f)
512 {
513 SetConsoleCursorPosition (cur_screen, cursor_coords);
514 }
515
516 /***********************************************************************
517 stubs from termcap.c
518 ***********************************************************************/
519
520 void
521 sys_tputs (char *str, int nlines, int (*outfun) (int))
522 {
523 }
524
525 char *
526 sys_tgetstr (char *cap, char **area)
527 {
528 return NULL;
529 }
530
531
532 /***********************************************************************
533 stubs from cm.c
534 ***********************************************************************/
535
536 struct tty_display_info *current_tty = NULL;
537 int cost = 0;
538
539 int
540 evalcost (int c)
541 {
542 return c;
543 }
544
545 int
546 cmputc (int c)
547 {
548 return c;
549 }
550
551 void
552 cmcheckmagic (struct tty_display_info *tty)
553 {
554 }
555
556 void
557 cmcostinit (struct tty_display_info *tty)
558 {
559 }
560
561 void
562 cmgoto (struct tty_display_info *tty, int row, int col)
563 {
564 }
565
566 void
567 Wcm_clear (struct tty_display_info *tty)
568 {
569 }
570
571
572 /* Report the current cursor position. The following two functions
573 are used in term.c's tty menu code, so they are not really
574 "stubs". */
575 int
576 cursorX (struct tty_display_info *tty)
577 {
578 return cursor_coords.X;
579 }
580
581 int
582 cursorY (struct tty_display_info *tty)
583 {
584 return cursor_coords.Y;
585 }
586
587 /***********************************************************************
588 Faces
589 ***********************************************************************/
590
591
592 /* Turn appearances of face FACE_ID on tty frame F on. */
593
594 static WORD
595 w32_face_attributes (struct frame *f, int face_id)
596 {
597 WORD char_attr;
598 struct face *face = FACE_FROM_ID (f, face_id);
599
600 eassert (face != NULL);
601
602 char_attr = char_attr_normal;
603
604 /* Reverse the default color if requested. If background and
605 foreground are specified, then they have been reversed already. */
606 if (face->tty_reverse_p)
607 char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
608 + ((char_attr & 0x00f0) >> 4);
609
610 /* Before the terminal is properly initialized, all colors map to 0.
611 Don't try to resolve them. */
612 if (NILP (Vtty_defined_color_alist))
613 return char_attr;
614
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)
621 char_attr = (char_attr & 0xfff0) + face->foreground;
622
623 if (face->background >= 0 && face->background < 16)
624 char_attr = (char_attr & 0xff0f) + (face->background << 4);
625
626 return char_attr;
627 }
628
629 void
630 initialize_w32_display (struct terminal *term, int *width, int *height)
631 {
632 CONSOLE_SCREEN_BUFFER_INFO info;
633 Mouse_HLInfo *hlinfo;
634
635 term->rif = 0; /* No window based redisplay on the console. */
636 term->cursor_to_hook = w32con_move_cursor;
637 term->raw_cursor_to_hook = w32con_move_cursor;
638 term->clear_to_end_hook = w32con_clear_to_end;
639 term->clear_frame_hook = w32con_clear_frame;
640 term->clear_end_of_line_hook = w32con_clear_end_of_line;
641 term->ins_del_lines_hook = w32con_ins_del_lines;
642 term->insert_glyphs_hook = w32con_insert_glyphs;
643 term->write_glyphs_hook = w32con_write_glyphs;
644 term->delete_glyphs_hook = w32con_delete_glyphs;
645 term->ring_bell_hook = w32_sys_ring_bell;
646 term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
647 term->set_terminal_modes_hook = w32con_set_terminal_modes;
648 term->set_terminal_window_hook = NULL;
649 term->update_begin_hook = w32con_update_begin;
650 term->update_end_hook = w32con_update_end;
651
652 term->read_socket_hook = w32_console_read_socket;
653 term->mouse_position_hook = w32_console_mouse_position;
654
655 /* The following are not used on the console. */
656 term->frame_rehighlight_hook = 0;
657 term->frame_raise_lower_hook = 0;
658 term->set_vertical_scroll_bar_hook = 0;
659 term->condemn_scroll_bars_hook = 0;
660 term->redeem_scroll_bar_hook = 0;
661 term->judge_scroll_bars_hook = 0;
662 term->frame_up_to_date_hook = 0;
663
664 /* Initialize the mouse-highlight data. */
665 reset_mouse_highlight (&term->display_info.tty->mouse_highlight);
666
667 /* Initialize interrupt_handle. */
668 init_crit ();
669
670 /* Remember original console settings. */
671 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
672 GetConsoleMode (keyboard_handle, &prev_console_mode);
673
674 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
675
676 #ifdef USE_SEPARATE_SCREEN
677 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
678 0, NULL,
679 CONSOLE_TEXTMODE_BUFFER,
680 NULL);
681
682 if (cur_screen == INVALID_HANDLE_VALUE)
683 {
684 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
685 printf ("LastError = 0x%lx\n", GetLastError ());
686 fflush (stdout);
687 exit (0);
688 }
689 #else
690 cur_screen = prev_screen;
691 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
692 #endif
693
694 /* Respect setting of LINES and COLUMNS environment variables. */
695 {
696 char * lines = getenv ("LINES");
697 char * columns = getenv ("COLUMNS");
698
699 if (lines != NULL && columns != NULL)
700 {
701 SMALL_RECT new_win_dims;
702 COORD new_size;
703
704 new_size.X = atoi (columns);
705 new_size.Y = atoi (lines);
706
707 GetConsoleScreenBufferInfo (cur_screen, &info);
708
709 /* Shrink the window first, so the buffer dimensions can be
710 reduced if necessary. */
711 new_win_dims.Top = 0;
712 new_win_dims.Left = 0;
713 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
714 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
715 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
716
717 SetConsoleScreenBufferSize (cur_screen, new_size);
718
719 /* Set the window size to match the buffer dimension. */
720 new_win_dims.Top = 0;
721 new_win_dims.Left = 0;
722 new_win_dims.Bottom = new_size.Y - 1;
723 new_win_dims.Right = new_size.X - 1;
724 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
725 }
726 }
727
728 GetConsoleScreenBufferInfo (cur_screen, &info);
729
730 char_attr_normal = info.wAttributes;
731
732 /* Determine if the info returned by GetConsoleScreenBufferInfo
733 is realistic. Old MS Telnet servers used to only fill out
734 the dwSize portion, even modern one fill the whole struct with
735 garbage when using non-MS telnet clients. */
736 if ((w32_use_full_screen_buffer
737 && (info.dwSize.Y < 20 || info.dwSize.Y > 100
738 || info.dwSize.X < 40 || info.dwSize.X > 200))
739 || (!w32_use_full_screen_buffer
740 && (info.srWindow.Bottom - info.srWindow.Top < 20
741 || info.srWindow.Bottom - info.srWindow.Top > 100
742 || info.srWindow.Right - info.srWindow.Left < 40
743 || info.srWindow.Right - info.srWindow.Left > 100)))
744 {
745 *height = 25;
746 *width = 80;
747 }
748
749 else if (w32_use_full_screen_buffer)
750 {
751 *height = info.dwSize.Y; /* lines per page */
752 *width = info.dwSize.X; /* characters per line */
753 }
754 else
755 {
756 /* Lines per page. Use buffer coords instead of buffer size. */
757 *height = 1 + info.srWindow.Bottom - info.srWindow.Top;
758 /* Characters per line. Use buffer coords instead of buffer size. */
759 *width = 1 + info.srWindow.Right - info.srWindow.Left;
760 }
761
762 if (os_subtype == OS_NT)
763 w32_console_unicode_input = 1;
764 else
765 w32_console_unicode_input = 0;
766
767 /* This is needed by w32notify.c:send_notifications. */
768 dwMainThreadId = GetCurrentThreadId ();
769
770 /* Setup w32_display_info structure for this frame. */
771
772 w32_initialize_display_info (build_string ("Console"));
773
774 }
775
776
777 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
778 doc: /* Set screen foreground and background colors.
779
780 Arguments should be indices between 0 and 15, see w32console.el. */)
781 (Lisp_Object foreground, Lisp_Object background)
782 {
783 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
784
785 Frecenter (Qnil);
786 return Qt;
787 }
788
789 DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 0, 0,
790 doc: /* Get color indices of the current screen foreground and background.
791
792 The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND).
793 See w32console.el and `tty-defined-color-alist' for mapping of indices
794 to colors. */)
795 (void)
796 {
797 return Fcons (make_number (char_attr_normal & 0x000f),
798 Fcons (make_number ((char_attr_normal >> 4) & 0x000f), Qnil));
799 }
800
801 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
802 doc: /* Set cursor size. */)
803 (Lisp_Object size)
804 {
805 CONSOLE_CURSOR_INFO cci;
806 cci.dwSize = XFASTINT (size);
807 cci.bVisible = TRUE;
808 (void) SetConsoleCursorInfo (cur_screen, &cci);
809
810 return Qt;
811 }
812
813 void
814 syms_of_ntterm (void)
815 {
816 DEFVAR_BOOL ("w32-use-full-screen-buffer",
817 w32_use_full_screen_buffer,
818 doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
819 This is desirable when running Emacs over telnet.
820 A value of nil means use the current console window dimensions; this
821 may be preferable when working directly at the console with a large
822 scroll-back buffer. */);
823 w32_use_full_screen_buffer = 0;
824
825 defsubr (&Sset_screen_color);
826 defsubr (&Sget_screen_color);
827 defsubr (&Sset_cursor_size);
828 }