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