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