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