*** empty log message ***
[bpt/emacs.git] / src / w32console.c
CommitLineData
e6b20d65 1/* Terminal hooks for GNU Emacs on the Microsoft W32 API.
8c2ac482 2 Copyright (C) 1992, 1999 Free Software Foundation, Inc.
6cdfb6e6 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
6cdfb6e6
RS
20
21 Tim Fleehart (apollo@online.com) 1-17-92
22 Geoff Voelker (voelker@cs.washington.edu) 9-12-93
23*/
24
25
6816efce
GV
26#include <config.h>
27
6cdfb6e6
RS
28#include <stdlib.h>
29#include <stdio.h>
6cdfb6e6 30#include <windows.h>
338b1bb2 31#include <string.h>
6cdfb6e6
RS
32
33#include "lisp.h"
2091aeb2 34#include "charset.h"
8c2ac482 35#include "coding.h"
6cdfb6e6
RS
36#include "disptab.h"
37#include "termhooks.h"
65fb143c
JR
38/* Disable features in dispextern.h that require a Window System. */
39#undef HAVE_WINDOW_SYSTEM
40#include "frame.h"
489f9371 41#include "w32inevt.h"
8c2ac482 42#include "dispextern.h"
6cdfb6e6 43
84f5bd81
AI
44#define min(a, b) ((a) < (b) ? (a) : (b))
45
0534d577 46/* from window.c */
6cdfb6e6
RS
47extern Lisp_Object Frecenter ();
48
49/* from keyboard.c */
50extern int detect_input_pending ();
51
52/* from sysdep.c */
53extern int read_input_pending ();
54
8c2ac482 55extern struct frame * updating_frame;
6cdfb6e6
RS
56extern int meta_key;
57
58static void move_cursor (int row, int col);
59static void clear_to_end (void);
60static void clear_frame (void);
61static void clear_end_of_line (int);
62static void ins_del_lines (int vpos, int n);
8c2ac482 63static void change_line_highlight (int, int, int, int);
6cdfb6e6 64static void reassert_line_highlight (int, int);
8c2ac482
JR
65static void insert_glyphs (struct glyph *start, int len);
66static void write_glyphs (struct glyph *string, int len);
6cdfb6e6 67static void delete_glyphs (int n);
fbd6baed 68void w32_sys_ring_bell (void);
6cdfb6e6
RS
69static void reset_terminal_modes (void);
70static void set_terminal_modes (void);
71static void set_terminal_window (int size);
8c2ac482
JR
72static void update_begin (struct frame * f);
73static void update_end (struct frame * f);
338b1bb2
JR
74static WORD w32_face_attributes (struct frame *f, int face_id);
75static int hl_mode (int new_highlight);
6cdfb6e6 76
338b1bb2
JR
77static COORD cursor_coords;
78static HANDLE prev_screen, cur_screen;
79static WORD char_attr_normal;
80static DWORD prev_console_mode;
6cdfb6e6 81
3e671d90 82#ifndef USE_SEPARATE_SCREEN
338b1bb2 83static CONSOLE_CURSOR_INFO prev_console_cursor;
3e671d90
GV
84#endif
85
191100f2
AI
86/* Determine whether to make frame dimensions match the screen buffer,
87 or the current window size. The former is desirable when running
88 over telnet, while the latter is more useful when working directly at
89 the console with a large scroll-back buffer. */
90int w32_use_full_screen_buffer;
338b1bb2 91HANDLE keyboard_handle;
191100f2 92
6cdfb6e6
RS
93
94/* Setting this as the ctrl handler prevents emacs from being killed when
40d578c9
RS
95 someone hits ^C in a 'suspended' session (child shell).
96 Also ignore Ctrl-Break signals. */
97
6cdfb6e6
RS
98BOOL
99ctrl_c_handler (unsigned long type)
100{
3e671d90
GV
101 /* Only ignore "interrupt" events when running interactively. */
102 return (!noninteractive
103 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
6cdfb6e6
RS
104}
105
106/* If we're updating a frame, use it as the current frame
107 Otherwise, use the selected frame. */
8c2ac482 108#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
6cdfb6e6
RS
109
110/* Move the cursor to (row, col). */
111void
112move_cursor (int row, int col)
113{
114 cursor_coords.X = col;
115 cursor_coords.Y = row;
116
8c2ac482 117 if (updating_frame == (struct frame *) NULL)
6cdfb6e6
RS
118 {
119 SetConsoleCursorPosition (cur_screen, cursor_coords);
120 }
121}
122
123/* Clear from cursor to end of screen. */
124void
125clear_to_end (void)
126{
8c2ac482 127 struct frame * f = PICK_FRAME ();
6cdfb6e6
RS
128
129 clear_end_of_line (FRAME_WIDTH (f) - 1);
130 ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
131}
132
133/* Clear the frame. */
134void
135clear_frame (void)
136{
8c2ac482 137 struct frame * f = PICK_FRAME ();
b47278e1 138 COORD dest;
84f5bd81
AI
139 int n;
140 DWORD r;
a5404e3a
AI
141 CONSOLE_SCREEN_BUFFER_INFO info;
142
143 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
b47278e1 144
6cdfb6e6 145 hl_mode (0);
338b1bb2 146
a5404e3a
AI
147 /* Remember that the screen buffer might be wider than the window. */
148 n = FRAME_HEIGHT (f) * info.dwSize.X;
b47278e1
GV
149 dest.X = dest.Y = 0;
150
338b1bb2 151 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
b47278e1
GV
152 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
153
6cdfb6e6
RS
154 move_cursor (0, 0);
155}
156
157
8c2ac482 158static struct glyph glyph_base[256];
6cdfb6e6
RS
159static BOOL ceol_initialized = FALSE;
160
161/* Clear from Cursor to end (what's "standout marker"?). */
162void
163clear_end_of_line (int end)
164{
165 if (!ceol_initialized)
166 {
167 int i;
168 for (i = 0; i < 256; i++)
169 {
8c2ac482 170 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
6cdfb6e6
RS
171 }
172 ceol_initialized = TRUE;
173 }
174 write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
175}
176
177/* Insert n lines at vpos. if n is negative delete -n lines. */
178void
179ins_del_lines (int vpos, int n)
180{
181 int i, nb, save_highlight;
182 SMALL_RECT scroll;
183 COORD dest;
184 CHAR_INFO fill;
8c2ac482 185 struct frame * f = PICK_FRAME ();
6cdfb6e6
RS
186
187 if (n < 0)
188 {
189 scroll.Top = vpos - n;
190 scroll.Bottom = FRAME_HEIGHT (f);
191 dest.Y = vpos;
192 }
193 else
194 {
195 scroll.Top = vpos;
196 scroll.Bottom = FRAME_HEIGHT (f) - n;
197 dest.Y = vpos + n;
198 }
199 scroll.Left = 0;
200 scroll.Right = FRAME_WIDTH (f);
201
202 dest.X = 0;
203
204 save_highlight = hl_mode (0);
205
206 fill.Char.AsciiChar = 0x20;
338b1bb2 207 fill.Attributes = char_attr_normal;
6cdfb6e6
RS
208
209 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
210
fbd6baed 211 /* Here we have to deal with a w32 console flake: If the scroll
6cdfb6e6
RS
212 region looks like abc and we scroll c to a and fill with d we get
213 cbd... if we scroll block c one line at a time to a, we get cdd...
214 Emacs expects cdd consistently... So we have to deal with that
215 here... (this also occurs scrolling the same way in the other
216 direction. */
217
218 if (n > 0)
219 {
220 if (scroll.Bottom < dest.Y)
221 {
222 for (i = scroll.Bottom; i < dest.Y; i++)
223 {
224 move_cursor (i, 0);
225 clear_end_of_line (FRAME_WIDTH (f));
226 }
227 }
228 }
229 else
230 {
231 nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
232
233 if (nb < scroll.Top)
234 {
235 for (i = nb; i < scroll.Top; i++)
236 {
237 move_cursor (i, 0);
238 clear_end_of_line (FRAME_WIDTH (f));
239 }
240 }
241 }
242
243 cursor_coords.X = 0;
244 cursor_coords.Y = vpos;
245
246 hl_mode (save_highlight);
247}
248
249/* Changes attribute to use when drawing characters to control. */
250static int
251hl_mode (int new_highlight)
252{
253 static int highlight = 0;
254 int old_highlight;
255
256 old_highlight = highlight;
257 highlight = (new_highlight != 0);
338b1bb2 258
6cdfb6e6
RS
259 return old_highlight;
260}
261
262/* Call this when about to modify line at position VPOS and change whether it
263 is highlighted. */
264void
8c2ac482
JR
265change_line_highlight (int new_highlight, int vpos, int y,
266 int first_unused_hpos)
6cdfb6e6
RS
267{
268 hl_mode (new_highlight);
269 move_cursor (vpos, 0);
270 clear_end_of_line (first_unused_hpos);
271}
272
273/* External interface to control of standout mode. Call this when about to
274 * modify line at position VPOS and not change whether it is highlighted. */
275void
276reassert_line_highlight (int highlight, int vpos)
277{
278 hl_mode (highlight);
279 vpos; /* pedantic compiler silencer */
280}
281
282#undef LEFT
283#undef RIGHT
284#define LEFT 1
285#define RIGHT 0
286
287void
288scroll_line (int dist, int direction)
289{
290 /* The idea here is to implement a horizontal scroll in one line to
291 implement delete and half of insert. */
292 SMALL_RECT scroll;
293 COORD dest;
294 CHAR_INFO fill;
8c2ac482 295 struct frame * f = PICK_FRAME ();
6cdfb6e6
RS
296
297 scroll.Top = cursor_coords.Y;
298 scroll.Bottom = cursor_coords.Y;
299
300 if (direction == LEFT)
301 {
302 scroll.Left = cursor_coords.X + dist;
303 scroll.Right = FRAME_WIDTH (f) - 1;
304 }
305 else
306 {
307 scroll.Left = cursor_coords.X;
308 scroll.Right = FRAME_WIDTH (f) - dist - 1;
309 }
310
311 dest.X = cursor_coords.X;
312 dest.Y = cursor_coords.Y;
313
314 fill.Char.AsciiChar = 0x20;
338b1bb2
JR
315 fill.Attributes = char_attr_normal;
316
6cdfb6e6
RS
317 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
318}
319
320
321/* If start is zero insert blanks instead of a string at start ?. */
322void
8c2ac482 323insert_glyphs (register struct glyph *start, register int len)
6cdfb6e6
RS
324{
325 scroll_line (len, RIGHT);
326
327 /* Move len chars to the right starting at cursor_coords, fill with blanks */
328 if (start)
329 {
330 /* Print the first len characters of start, cursor_coords.X adjusted
331 by write_glyphs. */
332
333 write_glyphs (start, len);
334 }
335 else
336 {
337 clear_end_of_line (cursor_coords.X + len);
338 }
339}
340
341void
8c2ac482 342write_glyphs (register struct glyph *string, register int len)
6cdfb6e6 343{
84f5bd81
AI
344 int produced, consumed;
345 DWORD r;
8c2ac482 346 struct frame * f = PICK_FRAME ();
338b1bb2 347 WORD char_attr;
4d5d6aab
KH
348 unsigned char conversion_buffer[1024];
349 int conversion_buffer_size = sizeof conversion_buffer;
338b1bb2
JR
350
351 if (len <= 0)
352 return;
b47278e1 353
8c2ac482
JR
354 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
355 the tail. */
356 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
6cdfb6e6 357
8c2ac482 358 while (len > 0)
6cdfb6e6 359 {
8c2ac482
JR
360 /* Identify a run of glyphs with the same face. */
361 int face_id = string->face_id;
362 int n;
363
364 for (n = 1; n < len; ++n)
365 if (string[n].face_id != face_id)
366 break;
367
368 /* Turn appearance modes of the face of the run on. */
338b1bb2 369 char_attr = w32_face_attributes (f, face_id);
8c2ac482
JR
370
371 while (n > 0)
372 {
4d5d6aab
KH
373 /* We use a fixed size (1024 bytes) of conversion buffer.
374 Usually it is sufficient, but if not, we just repeat the
375 loop. */
8c2ac482
JR
376 produced = encode_terminal_code (string, conversion_buffer,
377 n, conversion_buffer_size,
378 &consumed);
379 if (produced > 0)
380 {
381 /* Set the attribute for these characters. */
382 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
84f5bd81 383 produced, cursor_coords, &r))
8c2ac482
JR
384 {
385 printf ("Failed writing console attributes: %d\n",
386 GetLastError ());
387 fflush (stdout);
388 }
389
390 /* Write the characters. */
391 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
84f5bd81 392 produced, cursor_coords, &r))
8c2ac482
JR
393 {
394 printf ("Failed writing console characters: %d\n",
395 GetLastError ());
396 fflush (stdout);
397 }
398
399 cursor_coords.X += produced;
400 move_cursor (cursor_coords.Y, cursor_coords.X);
401 }
402 len -= consumed;
403 n -= consumed;
404 string += consumed;
405 }
6cdfb6e6
RS
406 }
407
8c2ac482
JR
408 /* We may have to output some codes to terminate the writing. */
409 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
6cdfb6e6 410 {
8c2ac482
JR
411 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
412 encode_coding (&terminal_coding, "", conversion_buffer,
413 0, conversion_buffer_size);
414 if (terminal_coding.produced > 0)
415 {
338b1bb2 416 if (!FillConsoleOutputAttribute (cur_screen, char_attr_normal,
8c2ac482 417 terminal_coding.produced,
84f5bd81 418 cursor_coords, &r))
8c2ac482
JR
419 {
420 printf ("Failed writing console attributes: %d\n",
421 GetLastError ());
422 fflush (stdout);
423 }
424
425 /* Write the characters. */
426 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
84f5bd81 427 produced, cursor_coords, &r))
8c2ac482
JR
428 {
429 printf ("Failed writing console characters: %d\n",
430 GetLastError ());
431 fflush (stdout);
432 }
433 }
6cdfb6e6 434 }
6cdfb6e6
RS
435}
436
8c2ac482 437
6cdfb6e6
RS
438void
439delete_glyphs (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 (n, LEFT);
446}
447
0534d577 448static unsigned int sound_type = 0xFFFFFFFF;
78859b80 449#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
0534d577 450
6cdfb6e6 451void
fbd6baed 452w32_sys_ring_bell (void)
6cdfb6e6 453{
0534d577 454 if (sound_type == 0xFFFFFFFF)
78859b80 455 {
0534d577 456 Beep (666, 100);
78859b80
GV
457 }
458 else if (sound_type == MB_EMACS_SILENT)
459 {
460 /* Do nothing. */
461 }
0534d577 462 else
78859b80 463 MessageBeep (sound_type);
6cdfb6e6
RS
464}
465
0534d577
KH
466DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
467 "Set the sound generated when the bell is rung.\n\
78859b80
GV
468SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent\n\
469to use the corresponding system sound for the bell. The 'silent sound\n\
470prevents Emacs from making any sound at all.\n\
0534d577
KH
471SOUND is nil to use the normal beep.")
472 (sound)
473 Lisp_Object sound;
6cdfb6e6 474{
0534d577
KH
475 CHECK_SYMBOL (sound, 0);
476
477 if (NILP (sound))
478 sound_type = 0xFFFFFFFF;
479 else if (EQ (sound, intern ("asterisk")))
480 sound_type = MB_ICONASTERISK;
481 else if (EQ (sound, intern ("exclamation")))
482 sound_type = MB_ICONEXCLAMATION;
483 else if (EQ (sound, intern ("hand")))
484 sound_type = MB_ICONHAND;
485 else if (EQ (sound, intern ("question")))
486 sound_type = MB_ICONQUESTION;
487 else if (EQ (sound, intern ("ok")))
488 sound_type = MB_OK;
78859b80
GV
489 else if (EQ (sound, intern ("silent")))
490 sound_type = MB_EMACS_SILENT;
0534d577
KH
491 else
492 sound_type = 0xFFFFFFFF;
493
494 return sound;
6cdfb6e6 495}
6cdfb6e6
RS
496
497void
498reset_terminal_modes (void)
499{
338b1bb2
JR
500 hl_mode (0);
501
3e671d90 502#ifdef USE_SEPARATE_SCREEN
6cdfb6e6 503 SetConsoleActiveScreenBuffer (prev_screen);
3e671d90
GV
504#else
505 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
506#endif
507 SetConsoleMode (keyboard_handle, prev_console_mode);
6cdfb6e6
RS
508}
509
510void
511set_terminal_modes (void)
512{
513 CONSOLE_CURSOR_INFO cci;
514
338b1bb2
JR
515 hl_mode (0);
516
3e671d90
GV
517 /* make cursor big and visible (100 on Win95 makes it disappear) */
518 cci.dwSize = 99;
519 cci.bVisible = TRUE;
520 (void) SetConsoleCursorInfo (cur_screen, &cci);
6cdfb6e6 521
3e671d90 522 SetConsoleActiveScreenBuffer (cur_screen);
6cdfb6e6 523
3e671d90 524 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
6cdfb6e6 525
3e671d90
GV
526 /* Initialize input mode: interrupt_input off, no flow control, allow
527 8 bit character input, standard quit char. */
528 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6cdfb6e6
RS
529}
530
531/* hmmm... perhaps these let us bracket screen changes so that we can flush
532 clumps rather than one-character-at-a-time...
533
534 we'll start with not moving the cursor while an update is in progress. */
535void
8c2ac482 536update_begin (struct frame * f)
6cdfb6e6 537{
338b1bb2 538 hl_mode (0);
6cdfb6e6
RS
539}
540
541void
8c2ac482 542update_end (struct frame * f)
6cdfb6e6 543{
338b1bb2 544 hl_mode (0);
6cdfb6e6
RS
545 SetConsoleCursorPosition (cur_screen, cursor_coords);
546}
547
548void
549set_terminal_window (int size)
550{
551}
552
8c2ac482
JR
553/***********************************************************************
554 Faces
555 ***********************************************************************/
556
557
558/* Turn appearances of face FACE_ID on tty frame F on. */
559
338b1bb2
JR
560static WORD
561w32_face_attributes (f, face_id)
8c2ac482
JR
562 struct frame *f;
563 int face_id;
564{
338b1bb2
JR
565 WORD char_attr;
566 int highlight_on_p;
8c2ac482
JR
567 struct face *face = FACE_FROM_ID (f, face_id);
568
338b1bb2
JR
569 highlight_on_p = hl_mode (0);
570 hl_mode (highlight_on_p);
571
8c2ac482
JR
572 xassert (face != NULL);
573
574 char_attr = char_attr_normal;
575
338b1bb2
JR
576 if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
577 && face->foreground != FACE_TTY_DEFAULT_COLOR)
578 char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
579
580 if (face->background != FACE_TTY_DEFAULT_BG_COLOR
581 && face->background != FACE_TTY_DEFAULT_COLOR)
582 char_attr = (char_attr & 0xff0f) + ((face->background % 16) * 16);
583
8c2ac482 584
338b1bb2
JR
585 /* Ensure readability (temporary measure until this all works) */
586 if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
587 char_attr ^= 0x0007;
8c2ac482 588
338b1bb2
JR
589 if (face->tty_reverse_p || highlight_on_p)
590 char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
591 + ((char_attr & 0x00f0) >> 4);
8c2ac482 592
338b1bb2 593 return char_attr;
8c2ac482
JR
594}
595
596
338b1bb2 597/* Emulation of some X window features from xfns.c and xfaces.c. */
8c2ac482 598
338b1bb2
JR
599extern char unspecified_fg[], unspecified_bg[];
600
601
602/* Given a color index, return its standard name. */
603Lisp_Object
604vga_stdcolor_name (int idx)
8c2ac482 605{
338b1bb2
JR
606 /* Standard VGA colors, in the order of their standard numbering
607 in the default VGA palette. */
608 static char *vga_colors[16] = {
609 "black", "blue", "green", "cyan", "red", "magenta", "brown",
610 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
611 "lightred", "lightmagenta", "yellow", "white"
612 };
613
614 extern Lisp_Object Qunspecified;
615
616 if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
617 return build_string (vga_colors[idx]);
618 else
619 return Qunspecified; /* meaning the default */
8c2ac482 620}
338b1bb2 621
6cdfb6e6
RS
622typedef int (*term_hook) ();
623
624void
e6b20d65 625initialize_w32_display (void)
6cdfb6e6
RS
626{
627 CONSOLE_SCREEN_BUFFER_INFO info;
628
f3d268f9
GV
629 cursor_to_hook = move_cursor;
630 raw_cursor_to_hook = move_cursor;
631 clear_to_end_hook = clear_to_end;
632 clear_frame_hook = clear_frame;
633 clear_end_of_line_hook = clear_end_of_line;
634 ins_del_lines_hook = ins_del_lines;
635 change_line_highlight_hook = change_line_highlight;
636 reassert_line_highlight_hook = reassert_line_highlight;
637 insert_glyphs_hook = insert_glyphs;
638 write_glyphs_hook = write_glyphs;
639 delete_glyphs_hook = delete_glyphs;
640 ring_bell_hook = w32_sys_ring_bell;
641 reset_terminal_modes_hook = reset_terminal_modes;
642 set_terminal_modes_hook = set_terminal_modes;
643 set_terminal_window_hook = set_terminal_window;
644 update_begin_hook = update_begin;
645 update_end_hook = update_end;
6cdfb6e6 646
fbd6baed 647 read_socket_hook = w32_console_read_socket;
f3d268f9 648 mouse_position_hook = w32_console_mouse_position;
8c2ac482 649 estimate_mode_line_height_hook = 0;
3e671d90 650
c1e06681
AI
651 /* Initialize interrupt_handle. */
652 init_crit ();
653
3e671d90
GV
654 /* Remember original console settings. */
655 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
656 GetConsoleMode (keyboard_handle, &prev_console_mode);
657
6cdfb6e6
RS
658 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
659
3e671d90
GV
660#ifdef USE_SEPARATE_SCREEN
661 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
662 0, NULL,
663 CONSOLE_TEXTMODE_BUFFER,
664 NULL);
665
666 if (cur_screen == INVALID_HANDLE_VALUE)
667 {
668 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
669 printf ("LastError = 0x%lx\n", GetLastError ());
670 fflush (stdout);
671 exit (0);
672 }
673#else
674 cur_screen = prev_screen;
675 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
676#endif
677
191100f2
AI
678 /* Respect setting of LINES and COLUMNS environment variables. */
679 {
680 char * lines = getenv("LINES");
681 char * columns = getenv("COLUMNS");
682
683 if (lines != NULL && columns != NULL)
684 {
685 SMALL_RECT new_win_dims;
686 COORD new_size;
687
688 new_size.X = atoi (columns);
689 new_size.Y = atoi (lines);
690
691 GetConsoleScreenBufferInfo (cur_screen, &info);
692
693 /* Shrink the window first, so the buffer dimensions can be
694 reduced if necessary. */
695 new_win_dims.Top = 0;
696 new_win_dims.Left = 0;
697 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
698 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
699 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
700
701 SetConsoleScreenBufferSize (cur_screen, new_size);
702
703 /* Set the window size to match the buffer dimension. */
704 new_win_dims.Top = 0;
705 new_win_dims.Left = 0;
706 new_win_dims.Bottom = new_size.Y - 1;
707 new_win_dims.Right = new_size.X - 1;
708 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
709 }
710 }
711
6cdfb6e6
RS
712 GetConsoleScreenBufferInfo (cur_screen, &info);
713
714 meta_key = 1;
338b1bb2
JR
715 char_attr_normal = info.wAttributes;
716 hl_mode (0);
938469f2 717
191100f2
AI
718 if (w32_use_full_screen_buffer)
719 {
8c2ac482
JR
720 FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
721 SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
191100f2
AI
722 }
723 else
724 {
725 /* Lines per page. Use buffer coords instead of buffer size. */
8c2ac482 726 FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
191100f2
AI
727 info.srWindow.Top;
728 /* Characters per line. Use buffer coords instead of buffer size. */
8c2ac482 729 SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right -
191100f2
AI
730 info.srWindow.Left);
731 }
65fb143c
JR
732
733 /* Setup w32_display_info structure for this frame. */
734
735 w32_initialize_display_info (build_string ("Console"));
736
6cdfb6e6
RS
737}
738
739DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
740 "Set screen colors.")
741 (foreground, background)
742 Lisp_Object foreground;
743 Lisp_Object background;
744{
745 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
6cdfb6e6
RS
746
747 Frecenter (Qnil);
748 return Qt;
749}
750
751DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
752 "Set cursor size.")
753 (size)
754 Lisp_Object size;
755{
756 CONSOLE_CURSOR_INFO cci;
757 cci.dwSize = XFASTINT (size);
758 cci.bVisible = TRUE;
759 (void) SetConsoleCursorInfo (cur_screen, &cci);
760
761 return Qt;
762}
763
6e72ba86 764#ifndef HAVE_NTGUI
6cdfb6e6 765void
8c2ac482 766pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
6cdfb6e6
RS
767 void *bounds, int noclip)
768{
769 *x = pix_x;
770 *y = pix_y;
771}
772
773void
5101dbdf 774glyph_to_pixel_coords (struct window * f, int x, int y, int *pix_x, int *pix_y)
6cdfb6e6
RS
775{
776 *pix_x = x;
777 *pix_y = y;
778}
6e72ba86 779#endif /* !HAVE_NTGUI */
6cdfb6e6 780
0534d577 781void
6cdfb6e6
RS
782syms_of_ntterm ()
783{
191100f2
AI
784 DEFVAR_BOOL ("w32-use-full-screen-buffer",
785 &w32_use_full_screen_buffer,
786 "Non-nil means make terminal frames use the full screen buffer dimensions.\n\
787This is desirable when running Emacs over telnet, and is the default.\n\
788A value of nil means use the current console window dimensions; this\n\
789may be preferrable when working directly at the console with a large\n\
790scroll-back buffer.");
791 w32_use_full_screen_buffer = 1;
792
6cdfb6e6
RS
793 defsubr (&Sset_screen_color);
794 defsubr (&Sset_cursor_size);
0534d577 795 defsubr (&Sset_message_beep);
6cdfb6e6 796}