Put doc strings in comments.
[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 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 136 COORD dest;
84f5bd81
AI
137 int n;
138 DWORD r;
a5404e3a
AI
139 CONSOLE_SCREEN_BUFFER_INFO info;
140
141 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
b47278e1 142
6cdfb6e6 143 hl_mode (0);
338b1bb2 144
a5404e3a
AI
145 /* Remember that the screen buffer might be wider than the window. */
146 n = FRAME_HEIGHT (f) * info.dwSize.X;
b47278e1
GV
147 dest.X = dest.Y = 0;
148
338b1bb2 149 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
b47278e1
GV
150 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
151
6cdfb6e6
RS
152 move_cursor (0, 0);
153}
154
155
8c2ac482 156static struct glyph glyph_base[256];
6cdfb6e6
RS
157static BOOL ceol_initialized = FALSE;
158
159/* Clear from Cursor to end (what's "standout marker"?). */
160void
161clear_end_of_line (int end)
162{
163 if (!ceol_initialized)
164 {
165 int i;
166 for (i = 0; i < 256; i++)
167 {
8c2ac482 168 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
6cdfb6e6
RS
169 }
170 ceol_initialized = TRUE;
171 }
172 write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
173}
174
175/* Insert n lines at vpos. if n is negative delete -n lines. */
176void
177ins_del_lines (int vpos, int n)
178{
179 int i, nb, save_highlight;
180 SMALL_RECT scroll;
181 COORD dest;
182 CHAR_INFO fill;
8c2ac482 183 struct frame * f = PICK_FRAME ();
6cdfb6e6
RS
184
185 if (n < 0)
186 {
187 scroll.Top = vpos - n;
188 scroll.Bottom = FRAME_HEIGHT (f);
189 dest.Y = vpos;
190 }
191 else
192 {
193 scroll.Top = vpos;
194 scroll.Bottom = FRAME_HEIGHT (f) - n;
195 dest.Y = vpos + n;
196 }
197 scroll.Left = 0;
198 scroll.Right = FRAME_WIDTH (f);
199
200 dest.X = 0;
201
202 save_highlight = hl_mode (0);
203
204 fill.Char.AsciiChar = 0x20;
338b1bb2 205 fill.Attributes = char_attr_normal;
6cdfb6e6
RS
206
207 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
208
fbd6baed 209 /* Here we have to deal with a w32 console flake: If the scroll
6cdfb6e6
RS
210 region looks like abc and we scroll c to a and fill with d we get
211 cbd... if we scroll block c one line at a time to a, we get cdd...
212 Emacs expects cdd consistently... So we have to deal with that
213 here... (this also occurs scrolling the same way in the other
214 direction. */
215
216 if (n > 0)
217 {
218 if (scroll.Bottom < dest.Y)
219 {
220 for (i = scroll.Bottom; i < dest.Y; i++)
221 {
222 move_cursor (i, 0);
223 clear_end_of_line (FRAME_WIDTH (f));
224 }
225 }
226 }
227 else
228 {
229 nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
230
231 if (nb < scroll.Top)
232 {
233 for (i = nb; i < scroll.Top; i++)
234 {
235 move_cursor (i, 0);
236 clear_end_of_line (FRAME_WIDTH (f));
237 }
238 }
239 }
240
241 cursor_coords.X = 0;
242 cursor_coords.Y = vpos;
243
244 hl_mode (save_highlight);
245}
246
247/* Changes attribute to use when drawing characters to control. */
248static int
249hl_mode (int new_highlight)
250{
251 static int highlight = 0;
252 int old_highlight;
253
254 old_highlight = highlight;
255 highlight = (new_highlight != 0);
338b1bb2 256
6cdfb6e6
RS
257 return old_highlight;
258}
259
260/* Call this when about to modify line at position VPOS and change whether it
261 is highlighted. */
262void
8c2ac482
JR
263change_line_highlight (int new_highlight, int vpos, int y,
264 int first_unused_hpos)
6cdfb6e6
RS
265{
266 hl_mode (new_highlight);
267 move_cursor (vpos, 0);
268 clear_end_of_line (first_unused_hpos);
269}
270
271/* External interface to control of standout mode. Call this when about to
272 * modify line at position VPOS and not change whether it is highlighted. */
273void
274reassert_line_highlight (int highlight, int vpos)
275{
276 hl_mode (highlight);
277 vpos; /* pedantic compiler silencer */
278}
279
280#undef LEFT
281#undef RIGHT
282#define LEFT 1
283#define RIGHT 0
284
285void
286scroll_line (int dist, int direction)
287{
288 /* The idea here is to implement a horizontal scroll in one line to
289 implement delete and half of insert. */
290 SMALL_RECT scroll;
291 COORD dest;
292 CHAR_INFO fill;
8c2ac482 293 struct frame * f = PICK_FRAME ();
6cdfb6e6
RS
294
295 scroll.Top = cursor_coords.Y;
296 scroll.Bottom = cursor_coords.Y;
297
298 if (direction == LEFT)
299 {
300 scroll.Left = cursor_coords.X + dist;
301 scroll.Right = FRAME_WIDTH (f) - 1;
302 }
303 else
304 {
305 scroll.Left = cursor_coords.X;
306 scroll.Right = FRAME_WIDTH (f) - dist - 1;
307 }
308
309 dest.X = cursor_coords.X;
310 dest.Y = cursor_coords.Y;
311
312 fill.Char.AsciiChar = 0x20;
338b1bb2
JR
313 fill.Attributes = char_attr_normal;
314
6cdfb6e6
RS
315 ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
316}
317
318
319/* If start is zero insert blanks instead of a string at start ?. */
320void
8c2ac482 321insert_glyphs (register struct glyph *start, register int len)
6cdfb6e6
RS
322{
323 scroll_line (len, RIGHT);
324
325 /* Move len chars to the right starting at cursor_coords, fill with blanks */
326 if (start)
327 {
328 /* Print the first len characters of start, cursor_coords.X adjusted
329 by write_glyphs. */
330
331 write_glyphs (start, len);
332 }
333 else
334 {
335 clear_end_of_line (cursor_coords.X + len);
336 }
337}
338
339void
8c2ac482 340write_glyphs (register struct glyph *string, register int len)
6cdfb6e6 341{
84f5bd81
AI
342 int produced, consumed;
343 DWORD r;
8c2ac482 344 struct frame * f = PICK_FRAME ();
338b1bb2 345 WORD char_attr;
4d5d6aab
KH
346 unsigned char conversion_buffer[1024];
347 int conversion_buffer_size = sizeof conversion_buffer;
338b1bb2
JR
348
349 if (len <= 0)
350 return;
b47278e1 351
8c2ac482
JR
352 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
353 the tail. */
354 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
6cdfb6e6 355
8c2ac482 356 while (len > 0)
6cdfb6e6 357 {
8c2ac482
JR
358 /* Identify a run of glyphs with the same face. */
359 int face_id = string->face_id;
360 int n;
361
362 for (n = 1; n < len; ++n)
363 if (string[n].face_id != face_id)
364 break;
365
366 /* Turn appearance modes of the face of the run on. */
338b1bb2 367 char_attr = w32_face_attributes (f, face_id);
8c2ac482
JR
368
369 while (n > 0)
370 {
4d5d6aab
KH
371 /* We use a fixed size (1024 bytes) of conversion buffer.
372 Usually it is sufficient, but if not, we just repeat the
373 loop. */
8c2ac482
JR
374 produced = encode_terminal_code (string, conversion_buffer,
375 n, conversion_buffer_size,
376 &consumed);
377 if (produced > 0)
378 {
379 /* Set the attribute for these characters. */
380 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
84f5bd81 381 produced, cursor_coords, &r))
8c2ac482
JR
382 {
383 printf ("Failed writing console attributes: %d\n",
384 GetLastError ());
385 fflush (stdout);
386 }
387
388 /* Write the characters. */
389 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
84f5bd81 390 produced, cursor_coords, &r))
8c2ac482
JR
391 {
392 printf ("Failed writing console characters: %d\n",
393 GetLastError ());
394 fflush (stdout);
395 }
396
397 cursor_coords.X += produced;
398 move_cursor (cursor_coords.Y, cursor_coords.X);
399 }
400 len -= consumed;
401 n -= consumed;
402 string += consumed;
403 }
6cdfb6e6
RS
404 }
405
8c2ac482
JR
406 /* We may have to output some codes to terminate the writing. */
407 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
6cdfb6e6 408 {
8c2ac482
JR
409 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
410 encode_coding (&terminal_coding, "", conversion_buffer,
411 0, conversion_buffer_size);
412 if (terminal_coding.produced > 0)
413 {
338b1bb2 414 if (!FillConsoleOutputAttribute (cur_screen, char_attr_normal,
8c2ac482 415 terminal_coding.produced,
84f5bd81 416 cursor_coords, &r))
8c2ac482
JR
417 {
418 printf ("Failed writing console attributes: %d\n",
419 GetLastError ());
420 fflush (stdout);
421 }
422
423 /* Write the characters. */
424 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
84f5bd81 425 produced, cursor_coords, &r))
8c2ac482
JR
426 {
427 printf ("Failed writing console characters: %d\n",
428 GetLastError ());
429 fflush (stdout);
430 }
431 }
6cdfb6e6 432 }
6cdfb6e6
RS
433}
434
8c2ac482 435
6cdfb6e6
RS
436void
437delete_glyphs (int n)
438{
439 /* delete chars means scroll chars from cursor_coords.X + n to
440 cursor_coords.X, anything beyond the edge of the screen should
441 come out empty... */
442
443 scroll_line (n, LEFT);
444}
445
0534d577 446static unsigned int sound_type = 0xFFFFFFFF;
78859b80 447#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
0534d577 448
6cdfb6e6 449void
fbd6baed 450w32_sys_ring_bell (void)
6cdfb6e6 451{
0534d577 452 if (sound_type == 0xFFFFFFFF)
78859b80 453 {
0534d577 454 Beep (666, 100);
78859b80
GV
455 }
456 else if (sound_type == MB_EMACS_SILENT)
457 {
458 /* Do nothing. */
459 }
0534d577 460 else
78859b80 461 MessageBeep (sound_type);
6cdfb6e6
RS
462}
463
0534d577
KH
464DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
465 "Set the sound generated when the bell is rung.\n\
78859b80
GV
466SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent\n\
467to use the corresponding system sound for the bell. The 'silent sound\n\
468prevents Emacs from making any sound at all.\n\
0534d577
KH
469SOUND is nil to use the normal beep.")
470 (sound)
471 Lisp_Object sound;
6cdfb6e6 472{
0534d577
KH
473 CHECK_SYMBOL (sound, 0);
474
475 if (NILP (sound))
476 sound_type = 0xFFFFFFFF;
477 else if (EQ (sound, intern ("asterisk")))
478 sound_type = MB_ICONASTERISK;
479 else if (EQ (sound, intern ("exclamation")))
480 sound_type = MB_ICONEXCLAMATION;
481 else if (EQ (sound, intern ("hand")))
482 sound_type = MB_ICONHAND;
483 else if (EQ (sound, intern ("question")))
484 sound_type = MB_ICONQUESTION;
485 else if (EQ (sound, intern ("ok")))
486 sound_type = MB_OK;
78859b80
GV
487 else if (EQ (sound, intern ("silent")))
488 sound_type = MB_EMACS_SILENT;
0534d577
KH
489 else
490 sound_type = 0xFFFFFFFF;
491
492 return sound;
6cdfb6e6 493}
6cdfb6e6
RS
494
495void
496reset_terminal_modes (void)
497{
338b1bb2
JR
498 hl_mode (0);
499
3e671d90 500#ifdef USE_SEPARATE_SCREEN
6cdfb6e6 501 SetConsoleActiveScreenBuffer (prev_screen);
3e671d90
GV
502#else
503 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
504#endif
505 SetConsoleMode (keyboard_handle, prev_console_mode);
6cdfb6e6
RS
506}
507
508void
509set_terminal_modes (void)
510{
511 CONSOLE_CURSOR_INFO cci;
512
338b1bb2
JR
513 hl_mode (0);
514
3e671d90
GV
515 /* make cursor big and visible (100 on Win95 makes it disappear) */
516 cci.dwSize = 99;
517 cci.bVisible = TRUE;
518 (void) SetConsoleCursorInfo (cur_screen, &cci);
6cdfb6e6 519
3e671d90 520 SetConsoleActiveScreenBuffer (cur_screen);
6cdfb6e6 521
3e671d90 522 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
6cdfb6e6 523
3e671d90
GV
524 /* Initialize input mode: interrupt_input off, no flow control, allow
525 8 bit character input, standard quit char. */
526 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6cdfb6e6
RS
527}
528
529/* hmmm... perhaps these let us bracket screen changes so that we can flush
530 clumps rather than one-character-at-a-time...
531
532 we'll start with not moving the cursor while an update is in progress. */
533void
8c2ac482 534update_begin (struct frame * f)
6cdfb6e6 535{
338b1bb2 536 hl_mode (0);
6cdfb6e6
RS
537}
538
539void
8c2ac482 540update_end (struct frame * f)
6cdfb6e6 541{
338b1bb2 542 hl_mode (0);
6cdfb6e6
RS
543 SetConsoleCursorPosition (cur_screen, cursor_coords);
544}
545
546void
547set_terminal_window (int size)
548{
549}
550
8c2ac482
JR
551/***********************************************************************
552 Faces
553 ***********************************************************************/
554
555
556/* Turn appearances of face FACE_ID on tty frame F on. */
557
338b1bb2
JR
558static WORD
559w32_face_attributes (f, face_id)
8c2ac482
JR
560 struct frame *f;
561 int face_id;
562{
338b1bb2
JR
563 WORD char_attr;
564 int highlight_on_p;
8c2ac482
JR
565 struct face *face = FACE_FROM_ID (f, face_id);
566
338b1bb2
JR
567 highlight_on_p = hl_mode (0);
568 hl_mode (highlight_on_p);
569
8c2ac482
JR
570 xassert (face != NULL);
571
572 char_attr = char_attr_normal;
573
338b1bb2
JR
574 if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
575 && face->foreground != FACE_TTY_DEFAULT_COLOR)
576 char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
577
578 if (face->background != FACE_TTY_DEFAULT_BG_COLOR
579 && face->background != FACE_TTY_DEFAULT_COLOR)
b93b26cb 580 char_attr = (char_attr & 0xff0f) + ((face->background % 16) << 4);
338b1bb2 581
8c2ac482 582
b93b26cb
JR
583 /* NTEMACS_TODO: Faces defined during startup get both foreground
584 and background of 0. Need a better way around this - for now detect
585 the problem and invert one of the faces to make the text readable. */
338b1bb2
JR
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}