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