]> code.delx.au - gnu-emacs/blob - src/w32console.c
285abb310fe8b541004940490037839d9b35448e
[gnu-emacs] / 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
634 term->rif = 0; /* No window based redisplay on the console. */
635 term->cursor_to_hook = w32con_move_cursor;
636 term->raw_cursor_to_hook = w32con_move_cursor;
637 term->clear_to_end_hook = w32con_clear_to_end;
638 term->clear_frame_hook = w32con_clear_frame;
639 term->clear_end_of_line_hook = w32con_clear_end_of_line;
640 term->ins_del_lines_hook = w32con_ins_del_lines;
641 term->insert_glyphs_hook = w32con_insert_glyphs;
642 term->write_glyphs_hook = w32con_write_glyphs;
643 term->delete_glyphs_hook = w32con_delete_glyphs;
644 term->ring_bell_hook = w32_sys_ring_bell;
645 term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
646 term->set_terminal_modes_hook = w32con_set_terminal_modes;
647 term->set_terminal_window_hook = NULL;
648 term->update_begin_hook = w32con_update_begin;
649 term->update_end_hook = w32con_update_end;
650
651 term->read_socket_hook = w32_console_read_socket;
652 term->mouse_position_hook = w32_console_mouse_position;
653
654 /* The following are not used on the console. */
655 term->frame_rehighlight_hook = 0;
656 term->frame_raise_lower_hook = 0;
657 term->set_vertical_scroll_bar_hook = 0;
658 term->condemn_scroll_bars_hook = 0;
659 term->redeem_scroll_bar_hook = 0;
660 term->judge_scroll_bars_hook = 0;
661 term->frame_up_to_date_hook = 0;
662
663 /* Initialize the mouse-highlight data. */
664 reset_mouse_highlight (&term->display_info.tty->mouse_highlight);
665
666 /* Initialize interrupt_handle. */
667 init_crit ();
668
669 /* Remember original console settings. */
670 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
671 GetConsoleMode (keyboard_handle, &prev_console_mode);
672
673 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
674
675 #ifdef USE_SEPARATE_SCREEN
676 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
677 0, NULL,
678 CONSOLE_TEXTMODE_BUFFER,
679 NULL);
680
681 if (cur_screen == INVALID_HANDLE_VALUE)
682 {
683 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
684 printf ("LastError = 0x%lx\n", GetLastError ());
685 fflush (stdout);
686 exit (0);
687 }
688 #else
689 cur_screen = prev_screen;
690 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
691 #endif
692
693 /* Respect setting of LINES and COLUMNS environment variables. */
694 {
695 char * lines = getenv ("LINES");
696 char * columns = getenv ("COLUMNS");
697
698 if (lines != NULL && columns != NULL)
699 {
700 SMALL_RECT new_win_dims;
701 COORD new_size;
702
703 new_size.X = atoi (columns);
704 new_size.Y = atoi (lines);
705
706 GetConsoleScreenBufferInfo (cur_screen, &info);
707
708 /* Shrink the window first, so the buffer dimensions can be
709 reduced if necessary. */
710 new_win_dims.Top = 0;
711 new_win_dims.Left = 0;
712 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
713 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
714 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
715
716 SetConsoleScreenBufferSize (cur_screen, new_size);
717
718 /* Set the window size to match the buffer dimension. */
719 new_win_dims.Top = 0;
720 new_win_dims.Left = 0;
721 new_win_dims.Bottom = new_size.Y - 1;
722 new_win_dims.Right = new_size.X - 1;
723 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
724 }
725 }
726
727 GetConsoleScreenBufferInfo (cur_screen, &info);
728
729 char_attr_normal = info.wAttributes;
730
731 /* Determine if the info returned by GetConsoleScreenBufferInfo
732 is realistic. Old MS Telnet servers used to only fill out
733 the dwSize portion, even modern one fill the whole struct with
734 garbage when using non-MS telnet clients. */
735 if ((w32_use_full_screen_buffer
736 && (info.dwSize.Y < 20 || info.dwSize.Y > 100
737 || info.dwSize.X < 40 || info.dwSize.X > 200))
738 || (!w32_use_full_screen_buffer
739 && (info.srWindow.Bottom - info.srWindow.Top < 20
740 || info.srWindow.Bottom - info.srWindow.Top > 100
741 || info.srWindow.Right - info.srWindow.Left < 40
742 || info.srWindow.Right - info.srWindow.Left > 100)))
743 {
744 *height = 25;
745 *width = 80;
746 }
747
748 else if (w32_use_full_screen_buffer)
749 {
750 *height = info.dwSize.Y; /* lines per page */
751 *width = info.dwSize.X; /* characters per line */
752 }
753 else
754 {
755 /* Lines per page. Use buffer coords instead of buffer size. */
756 *height = 1 + info.srWindow.Bottom - info.srWindow.Top;
757 /* Characters per line. Use buffer coords instead of buffer size. */
758 *width = 1 + info.srWindow.Right - info.srWindow.Left;
759 }
760
761 if (os_subtype == OS_NT)
762 w32_console_unicode_input = 1;
763 else
764 w32_console_unicode_input = 0;
765
766 /* This is needed by w32notify.c:send_notifications. */
767 dwMainThreadId = GetCurrentThreadId ();
768
769 /* Setup w32_display_info structure for this frame. */
770
771 w32_initialize_display_info (build_string ("Console"));
772
773 }
774
775
776 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
777 doc: /* Set screen foreground and background colors.
778
779 Arguments should be indices between 0 and 15, see w32console.el. */)
780 (Lisp_Object foreground, Lisp_Object background)
781 {
782 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
783
784 Frecenter (Qnil);
785 return Qt;
786 }
787
788 DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 0, 0,
789 doc: /* Get color indices of the current screen foreground and background.
790
791 The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND).
792 See w32console.el and `tty-defined-color-alist' for mapping of indices
793 to colors. */)
794 (void)
795 {
796 return Fcons (make_number (char_attr_normal & 0x000f),
797 Fcons (make_number ((char_attr_normal >> 4) & 0x000f), Qnil));
798 }
799
800 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
801 doc: /* Set cursor size. */)
802 (Lisp_Object size)
803 {
804 CONSOLE_CURSOR_INFO cci;
805 cci.dwSize = XFASTINT (size);
806 cci.bVisible = TRUE;
807 (void) SetConsoleCursorInfo (cur_screen, &cci);
808
809 return Qt;
810 }
811
812 void
813 syms_of_ntterm (void)
814 {
815 DEFVAR_BOOL ("w32-use-full-screen-buffer",
816 w32_use_full_screen_buffer,
817 doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
818 This is desirable when running Emacs over telnet.
819 A value of nil means use the current console window dimensions; this
820 may be preferable when working directly at the console with a large
821 scroll-back buffer. */);
822 w32_use_full_screen_buffer = 0;
823
824 defsubr (&Sset_screen_color);
825 defsubr (&Sget_screen_color);
826 defsubr (&Sset_cursor_size);
827 }