/* Terminal hooks for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1999 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
Tim Fleehart (apollo@online.com) 1-17-92
Geoff Voelker (voelker@cs.washington.edu) 9-12-93
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
+#include <string.h>
#include "lisp.h"
#include "charset.h"
-#include "frame.h"
+#include "coding.h"
#include "disptab.h"
#include "termhooks.h"
+#include "dispextern.h"
+/* Disable features in frame.h that require a Window System. */
+#undef HAVE_WINDOW_SYSTEM
+#include "frame.h"
#include "w32inevt.h"
/* from window.c */
/* from sysdep.c */
extern int read_input_pending ();
-extern FRAME_PTR updating_frame;
+extern struct frame * updating_frame;
extern int meta_key;
-static void move_cursor (int row, int col);
-static void clear_to_end (void);
-static void clear_frame (void);
-static void clear_end_of_line (int);
-static void ins_del_lines (int vpos, int n);
-static void change_line_highlight (int, int, int);
-static void reassert_line_highlight (int, int);
-static void insert_glyphs (GLYPH *start, int len);
-static void write_glyphs (GLYPH *string, int len);
-static void delete_glyphs (int n);
+static void w32con_move_cursor (int row, int col);
+static void w32con_clear_to_end (void);
+static void w32con_clear_frame (void);
+static void w32con_clear_end_of_line (int);
+static void w32con_ins_del_lines (int vpos, int n);
+static void w32con_insert_glyphs (struct glyph *start, int len);
+static void w32con_write_glyphs (struct glyph *string, int len);
+static void w32con_delete_glyphs (int n);
void w32_sys_ring_bell (void);
-static void reset_terminal_modes (void);
-static void set_terminal_modes (void);
-static void set_terminal_window (int size);
-static void update_begin (FRAME_PTR f);
-static void update_end (FRAME_PTR f);
-static int hl_mode (int new_highlight);
-
-COORD cursor_coords;
-HANDLE prev_screen, cur_screen;
-UCHAR char_attr, char_attr_normal, char_attr_reverse;
-HANDLE keyboard_handle;
-DWORD prev_console_mode;
+static void w32con_reset_terminal_modes (void);
+static void w32con_set_terminal_modes (void);
+static void w32con_set_terminal_window (int size);
+static void w32con_update_begin (struct frame * f);
+static void w32con_update_end (struct frame * f);
+static WORD w32_face_attributes (struct frame *f, int face_id);
+
+static COORD cursor_coords;
+static HANDLE prev_screen, cur_screen;
+static WORD char_attr_normal;
+static DWORD prev_console_mode;
#ifndef USE_SEPARATE_SCREEN
-CONSOLE_CURSOR_INFO prev_console_cursor;
+static CONSOLE_CURSOR_INFO prev_console_cursor;
#endif
+/* Determine whether to make frame dimensions match the screen buffer,
+ or the current window size. The former is desirable when running
+ over telnet, while the latter is more useful when working directly at
+ the console with a large scroll-back buffer. */
+int w32_use_full_screen_buffer;
+HANDLE keyboard_handle;
+
/* Setting this as the ctrl handler prevents emacs from being killed when
someone hits ^C in a 'suspended' session (child shell).
/* If we're updating a frame, use it as the current frame
Otherwise, use the selected frame. */
-#define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
+#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
/* Move the cursor to (row, col). */
-void
-move_cursor (int row, int col)
+static void
+w32con_move_cursor (int row, int col)
{
cursor_coords.X = col;
cursor_coords.Y = row;
-
- if (updating_frame == (FRAME_PTR) NULL)
+
+ if (updating_frame == (struct frame *) NULL)
{
SetConsoleCursorPosition (cur_screen, cursor_coords);
}
}
/* Clear from cursor to end of screen. */
-void
-clear_to_end (void)
+static void
+w32con_clear_to_end (void)
{
- FRAME_PTR f = PICK_FRAME ();
-
- clear_end_of_line (FRAME_WIDTH (f) - 1);
- ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
+ struct frame * f = PICK_FRAME ();
+
+ w32con_clear_end_of_line (FRAME_COLS (f) - 1);
+ w32con_ins_del_lines (cursor_coords.Y, FRAME_LINES (f) - cursor_coords.Y - 1);
}
/* Clear the frame. */
-void
-clear_frame (void)
+static void
+w32con_clear_frame (void)
{
- FRAME_PTR f = PICK_FRAME ();
+ struct frame * f = PICK_FRAME ();
COORD dest;
- int n, r;
+ int n;
+ DWORD r;
+ CONSOLE_SCREEN_BUFFER_INFO info;
- hl_mode (0);
-
- n = FRAME_HEIGHT (f) * FRAME_WIDTH (f);
+ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
+
+ /* Remember that the screen buffer might be wider than the window. */
+ n = FRAME_LINES (f) * info.dwSize.X;
dest.X = dest.Y = 0;
- FillConsoleOutputAttribute (cur_screen, char_attr, n, dest, &r);
+ FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
- move_cursor (0, 0);
+ w32con_move_cursor (0, 0);
}
-static GLYPH glyph_base[256];
+static struct glyph glyph_base[256];
static BOOL ceol_initialized = FALSE;
/* Clear from Cursor to end (what's "standout marker"?). */
-void
-clear_end_of_line (int end)
+static void
+w32con_clear_end_of_line (int end)
{
if (!ceol_initialized)
{
int i;
for (i = 0; i < 256; i++)
{
- glyph_base[i] = SPACEGLYPH; /* empty space */
+ memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
}
ceol_initialized = TRUE;
}
- write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
+ w32con_write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
}
/* Insert n lines at vpos. if n is negative delete -n lines. */
-void
-ins_del_lines (int vpos, int n)
+static void
+w32con_ins_del_lines (int vpos, int n)
{
- int i, nb, save_highlight;
+ int i, nb;
SMALL_RECT scroll;
COORD dest;
CHAR_INFO fill;
- FRAME_PTR f = PICK_FRAME ();
+ struct frame * f = PICK_FRAME ();
if (n < 0)
{
scroll.Top = vpos - n;
- scroll.Bottom = FRAME_HEIGHT (f);
+ scroll.Bottom = FRAME_LINES (f);
dest.Y = vpos;
}
else
{
scroll.Top = vpos;
- scroll.Bottom = FRAME_HEIGHT (f) - n;
+ scroll.Bottom = FRAME_LINES (f) - n;
dest.Y = vpos + n;
}
scroll.Left = 0;
- scroll.Right = FRAME_WIDTH (f);
-
+ scroll.Right = FRAME_COLS (f);
+
dest.X = 0;
-
- save_highlight = hl_mode (0);
-
+
fill.Char.AsciiChar = 0x20;
- fill.Attributes = char_attr;
-
+ fill.Attributes = char_attr_normal;
+
ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
/* Here we have to deal with a w32 console flake: If the scroll
{
for (i = scroll.Bottom; i < dest.Y; i++)
{
- move_cursor (i, 0);
- clear_end_of_line (FRAME_WIDTH (f));
+ w32con_move_cursor (i, 0);
+ w32con_clear_end_of_line (FRAME_COLS (f));
}
}
}
nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
if (nb < scroll.Top)
- {
+ {
for (i = nb; i < scroll.Top; i++)
{
- move_cursor (i, 0);
- clear_end_of_line (FRAME_WIDTH (f));
+ w32con_move_cursor (i, 0);
+ w32con_clear_end_of_line (FRAME_COLS (f));
}
}
}
-
+
cursor_coords.X = 0;
cursor_coords.Y = vpos;
-
- hl_mode (save_highlight);
-}
-
-/* Changes attribute to use when drawing characters to control. */
-static int
-hl_mode (int new_highlight)
-{
- static int highlight = 0;
- int old_highlight;
-
- old_highlight = highlight;
- highlight = (new_highlight != 0);
- if (highlight)
- {
- char_attr = char_attr_reverse;
- }
- else
- {
- char_attr = char_attr_normal;
- }
- return old_highlight;
-}
-
-/* Call this when about to modify line at position VPOS and change whether it
- is highlighted. */
-void
-change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
-{
- hl_mode (new_highlight);
- move_cursor (vpos, 0);
- clear_end_of_line (first_unused_hpos);
-}
-
-/* External interface to control of standout mode. Call this when about to
- * modify line at position VPOS and not change whether it is highlighted. */
-void
-reassert_line_highlight (int highlight, int vpos)
-{
- hl_mode (highlight);
- vpos; /* pedantic compiler silencer */
}
#undef LEFT
#define LEFT 1
#define RIGHT 0
-void
+static void
scroll_line (int dist, int direction)
{
/* The idea here is to implement a horizontal scroll in one line to
SMALL_RECT scroll;
COORD dest;
CHAR_INFO fill;
- FRAME_PTR f = PICK_FRAME ();
-
+ struct frame * f = PICK_FRAME ();
+
scroll.Top = cursor_coords.Y;
scroll.Bottom = cursor_coords.Y;
-
+
if (direction == LEFT)
{
scroll.Left = cursor_coords.X + dist;
- scroll.Right = FRAME_WIDTH (f) - 1;
+ scroll.Right = FRAME_COLS (f) - 1;
}
else
{
scroll.Left = cursor_coords.X;
- scroll.Right = FRAME_WIDTH (f) - dist - 1;
+ scroll.Right = FRAME_COLS (f) - dist - 1;
}
-
+
dest.X = cursor_coords.X;
dest.Y = cursor_coords.Y;
-
+
fill.Char.AsciiChar = 0x20;
- fill.Attributes = char_attr;
-
+ fill.Attributes = char_attr_normal;
+
ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
}
/* If start is zero insert blanks instead of a string at start ?. */
-void
-insert_glyphs (register GLYPH *start, register int len)
+static void
+w32con_insert_glyphs (register struct glyph *start, register int len)
{
scroll_line (len, RIGHT);
{
/* Print the first len characters of start, cursor_coords.X adjusted
by write_glyphs. */
-
- write_glyphs (start, len);
+
+ w32con_write_glyphs (start, len);
}
else
{
- clear_end_of_line (cursor_coords.X + len);
+ w32con_clear_end_of_line (cursor_coords.X + len);
}
}
-void
-write_glyphs (register GLYPH *string, register int len)
+extern unsigned char *encode_terminal_code P_ ((struct glyph *, int,
+ struct coding_system *));
+
+static void
+w32con_write_glyphs (register struct glyph *string, register int len)
{
- register unsigned int glyph_len = GLYPH_TABLE_LENGTH;
- Lisp_Object *glyph_table = GLYPH_TABLE_BASE;
- FRAME_PTR f = PICK_FRAME ();
- register char *ptr;
- GLYPH glyph;
- WORD *attrs;
- char *chars;
- int i;
-
+ int produced, consumed;
+ DWORD r;
+ struct frame * f = PICK_FRAME ();
+ WORD char_attr;
+ unsigned char *conversion_buffer;
+ struct coding_system *coding;
+
if (len <= 0)
return;
- attrs = alloca (len * sizeof (*attrs));
- chars = alloca (len * sizeof (*chars));
- if (attrs == NULL || chars == NULL)
- {
- printf ("alloca failed in write_glyphs\n");
- return;
- }
-
- /* We have to deal with the glyph indirection...go over the glyph
- buffer and extract the characters. */
- ptr = chars;
- while (--len >= 0)
- {
- glyph = *string++;
+ /* If terminal_coding does any conversion, use it, otherwise use
+ safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
+ because it always return 1 if the member src_multibyte is 1. */
+ coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
+ ? &terminal_coding : &safe_terminal_coding);
+ /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+ the tail. */
+ terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
- if (glyph > glyph_len)
- {
- *ptr++ = glyph & 0xFF;
- continue;
- }
- GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph);
-#ifndef HAVE_NTGUI
- if (GLYPH_FACE (fixfix, glyph) != 0)
- printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph));
-#endif /* !HAVE_NTGUI */
- if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph))
- {
- *ptr++ = glyph & 0xFF;
- continue;
- }
- for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++)
- {
- *ptr++ = (GLYPH_STRING (glyph_table, glyph))[i];
- }
- }
-
- /* Number of characters we have in the buffer. */
- len = ptr-chars;
-
- /* Fill in the attributes for these characters. */
- for (i = 0; i < len; i++)
- attrs[i] = char_attr;
-
- /* Write the attributes. */
- if (!WriteConsoleOutputAttribute (cur_screen, attrs, len, cursor_coords, &i))
+ while (len > 0)
{
- printf ("Failed writing console attributes: %d\n", GetLastError ());
- fflush (stdout);
- }
-
- /* Write the characters. */
- if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i))
- {
- printf ("Failed writing console characters: %d\n", GetLastError ());
- fflush (stdout);
+ /* Identify a run of glyphs with the same face. */
+ int face_id = string->face_id;
+ int n;
+
+ for (n = 1; n < len; ++n)
+ if (string[n].face_id != face_id)
+ break;
+
+ /* Turn appearance modes of the face of the run on. */
+ char_attr = w32_face_attributes (f, face_id);
+
+ if (n == len)
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer = encode_terminal_code (string, n, coding);
+ if (coding->produced > 0)
+ {
+ /* Set the attribute for these characters. */
+ if (!FillConsoleOutputAttribute (cur_screen, char_attr,
+ coding->produced, cursor_coords,
+ &r))
+ {
+ printf ("Failed writing console attributes: %d\n",
+ GetLastError ());
+ fflush (stdout);
+ }
+
+ /* Write the characters. */
+ if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+ coding->produced, cursor_coords,
+ &r))
+ {
+ printf ("Failed writing console characters: %d\n",
+ GetLastError ());
+ fflush (stdout);
+ }
+
+ cursor_coords.X += coding->produced;
+ w32con_move_cursor (cursor_coords.Y, cursor_coords.X);
+ }
+ len -= n;
+ string += n;
}
-
- cursor_coords.X += len;
- move_cursor (cursor_coords.Y, cursor_coords.X);
}
-void
-delete_glyphs (int n)
+
+static void
+w32con_delete_glyphs (int n)
{
- /* delete chars means scroll chars from cursor_coords.X + n to
- cursor_coords.X, anything beyond the edge of the screen should
+ /* delete chars means scroll chars from cursor_coords.X + n to
+ cursor_coords.X, anything beyond the edge of the screen should
come out empty... */
scroll_line (n, LEFT);
void
w32_sys_ring_bell (void)
{
- if (sound_type == 0xFFFFFFFF)
+ if (sound_type == 0xFFFFFFFF)
{
Beep (666, 100);
}
}
DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
- "Set the sound generated when the bell is rung.\n\
-SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent\n\
-to use the corresponding system sound for the bell. The 'silent sound\n\
-prevents Emacs from making any sound at all.\n\
-SOUND is nil to use the normal beep.")
+ doc: /* Set the sound generated when the bell is rung.
+SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
+to use the corresponding system sound for the bell. The 'silent sound
+prevents Emacs from making any sound at all.
+SOUND is nil to use the normal beep. */)
(sound)
Lisp_Object sound;
{
- CHECK_SYMBOL (sound, 0);
+ CHECK_SYMBOL (sound);
- if (NILP (sound))
+ if (NILP (sound))
sound_type = 0xFFFFFFFF;
else if (EQ (sound, intern ("asterisk")))
sound_type = MB_ICONASTERISK;
- else if (EQ (sound, intern ("exclamation")))
+ else if (EQ (sound, intern ("exclamation")))
sound_type = MB_ICONEXCLAMATION;
- else if (EQ (sound, intern ("hand")))
+ else if (EQ (sound, intern ("hand")))
sound_type = MB_ICONHAND;
- else if (EQ (sound, intern ("question")))
+ else if (EQ (sound, intern ("question")))
sound_type = MB_ICONQUESTION;
- else if (EQ (sound, intern ("ok")))
+ else if (EQ (sound, intern ("ok")))
sound_type = MB_OK;
else if (EQ (sound, intern ("silent")))
sound_type = MB_EMACS_SILENT;
return sound;
}
-
-void
-reset_terminal_modes (void)
+
+static void
+w32con_reset_terminal_modes (void)
{
#ifdef USE_SEPARATE_SCREEN
SetConsoleActiveScreenBuffer (prev_screen);
SetConsoleMode (keyboard_handle, prev_console_mode);
}
-void
-set_terminal_modes (void)
+static void
+w32con_set_terminal_modes (void)
{
CONSOLE_CURSOR_INFO cci;
/* hmmm... perhaps these let us bracket screen changes so that we can flush
clumps rather than one-character-at-a-time...
-
+
we'll start with not moving the cursor while an update is in progress. */
-void
-update_begin (FRAME_PTR f)
+static void
+w32con_update_begin (struct frame * f)
{
}
-void
-update_end (FRAME_PTR f)
+static void
+w32con_update_end (struct frame * f)
{
SetConsoleCursorPosition (cur_screen, cursor_coords);
}
-void
-set_terminal_window (int size)
+static void
+w32con_set_terminal_window (int size)
{
}
+/***********************************************************************
+ Faces
+ ***********************************************************************/
+
+
+/* Turn appearances of face FACE_ID on tty frame F on. */
+
+static WORD
+w32_face_attributes (f, face_id)
+ struct frame *f;
+ int face_id;
+{
+ WORD char_attr;
+ struct face *face = FACE_FROM_ID (f, face_id);
+
+ xassert (face != NULL);
+
+ char_attr = char_attr_normal;
+
+ if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
+ && face->foreground != FACE_TTY_DEFAULT_COLOR)
+ char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
+
+ if (face->background != FACE_TTY_DEFAULT_BG_COLOR
+ && face->background != FACE_TTY_DEFAULT_COLOR)
+ char_attr = (char_attr & 0xff0f) + ((face->background % 16) << 4);
+
+
+ /* NTEMACS_TODO: Faces defined during startup get both foreground
+ and background of 0. Need a better way around this - for now detect
+ the problem and invert one of the faces to make the text readable. */
+ if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
+ char_attr ^= 0x0007;
+
+ if (face->tty_reverse_p)
+ char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
+ + ((char_attr & 0x00f0) >> 4);
+
+ return char_attr;
+}
+
+
+/* Emulation of some X window features from xfns.c and xfaces.c. */
+
+extern char unspecified_fg[], unspecified_bg[];
+
+
+/* Given a color index, return its standard name. */
+Lisp_Object
+vga_stdcolor_name (int idx)
+{
+ /* Standard VGA colors, in the order of their standard numbering
+ in the default VGA palette. */
+ static char *vga_colors[16] = {
+ "black", "blue", "green", "cyan", "red", "magenta", "brown",
+ "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
+ "lightred", "lightmagenta", "yellow", "white"
+ };
+
+ extern Lisp_Object Qunspecified;
+
+ if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
+ return build_string (vga_colors[idx]);
+ else
+ return Qunspecified; /* meaning the default */
+}
+
typedef int (*term_hook) ();
void
initialize_w32_display (void)
{
CONSOLE_SCREEN_BUFFER_INFO info;
-
- cursor_to_hook = move_cursor;
- raw_cursor_to_hook = move_cursor;
- clear_to_end_hook = clear_to_end;
- clear_frame_hook = clear_frame;
- clear_end_of_line_hook = clear_end_of_line;
- ins_del_lines_hook = ins_del_lines;
- change_line_highlight_hook = change_line_highlight;
- reassert_line_highlight_hook = reassert_line_highlight;
- insert_glyphs_hook = insert_glyphs;
- write_glyphs_hook = write_glyphs;
- delete_glyphs_hook = delete_glyphs;
+
+ cursor_to_hook = w32con_move_cursor;
+ raw_cursor_to_hook = w32con_move_cursor;
+ clear_to_end_hook = w32con_clear_to_end;
+ clear_frame_hook = w32con_clear_frame;
+ clear_end_of_line_hook = w32con_clear_end_of_line;
+ ins_del_lines_hook = w32con_ins_del_lines;
+ insert_glyphs_hook = w32con_insert_glyphs;
+ write_glyphs_hook = w32con_write_glyphs;
+ delete_glyphs_hook = w32con_delete_glyphs;
ring_bell_hook = w32_sys_ring_bell;
- reset_terminal_modes_hook = reset_terminal_modes;
- set_terminal_modes_hook = set_terminal_modes;
- set_terminal_window_hook = set_terminal_window;
- update_begin_hook = update_begin;
- update_end_hook = update_end;
-
+ reset_terminal_modes_hook = w32con_reset_terminal_modes;
+ set_terminal_modes_hook = w32con_set_terminal_modes;
+ set_terminal_window_hook = w32con_set_terminal_window;
+ update_begin_hook = w32con_update_begin;
+ update_end_hook = w32con_update_end;
+
read_socket_hook = w32_console_read_socket;
mouse_position_hook = w32_console_mouse_position;
GetConsoleMode (keyboard_handle, &prev_console_mode);
prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
-
+
#ifdef USE_SEPARATE_SCREEN
cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
0, NULL,
GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
#endif
+ /* Respect setting of LINES and COLUMNS environment variables. */
+ {
+ char * lines = getenv("LINES");
+ char * columns = getenv("COLUMNS");
+
+ if (lines != NULL && columns != NULL)
+ {
+ SMALL_RECT new_win_dims;
+ COORD new_size;
+
+ new_size.X = atoi (columns);
+ new_size.Y = atoi (lines);
+
+ GetConsoleScreenBufferInfo (cur_screen, &info);
+
+ /* Shrink the window first, so the buffer dimensions can be
+ reduced if necessary. */
+ new_win_dims.Top = 0;
+ new_win_dims.Left = 0;
+ new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
+ new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
+ SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
+
+ SetConsoleScreenBufferSize (cur_screen, new_size);
+
+ /* Set the window size to match the buffer dimension. */
+ new_win_dims.Top = 0;
+ new_win_dims.Left = 0;
+ new_win_dims.Bottom = new_size.Y - 1;
+ new_win_dims.Right = new_size.X - 1;
+ SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
+ }
+ }
+
GetConsoleScreenBufferInfo (cur_screen, &info);
-
+
meta_key = 1;
- char_attr = info.wAttributes & 0xFF;
- char_attr_normal = char_attr;
- char_attr_reverse = ((char_attr & 0xf) << 4) + ((char_attr & 0xf0) >> 4);
-
- FRAME_HEIGHT (selected_frame) = info.dwSize.Y; /* lines per page */
- SET_FRAME_WIDTH (selected_frame, info.dwSize.X); /* characters per line */
-
-// move_cursor (0, 0);
-
-// clear_frame ();
+ char_attr_normal = info.wAttributes;
+
+ /* Determine if the info returned by GetConsoleScreenBufferInfo
+ is realistic. Old MS Telnet servers used to only fill out
+ the dwSize portion, even modern one fill the whole struct with
+ garbage when using non-MS telnet clients. */
+ if ((w32_use_full_screen_buffer
+ && (info.dwSize.Y < 20 || info.dwSize.Y > 100
+ || info.dwSize.X < 40 || info.dwSize.X > 200))
+ || (!w32_use_full_screen_buffer
+ && (info.srWindow.Bottom - info.srWindow.Top < 20
+ || info.srWindow.Bottom - info.srWindow.Top > 100
+ || info.srWindow.Right - info.srWindow.Left < 40
+ || info.srWindow.Right - info.srWindow.Left > 100)))
+ {
+ FRAME_LINES (SELECTED_FRAME ()) = 25;
+ SET_FRAME_COLS (SELECTED_FRAME (), 80);
+ }
+
+ else if (w32_use_full_screen_buffer)
+ {
+ FRAME_LINES (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
+ SET_FRAME_COLS (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
+ }
+ else
+ {
+ /* Lines per page. Use buffer coords instead of buffer size. */
+ FRAME_LINES (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
+ info.srWindow.Top;
+ /* Characters per line. Use buffer coords instead of buffer size. */
+ SET_FRAME_COLS (SELECTED_FRAME (), 1 + info.srWindow.Right -
+ info.srWindow.Left);
+ }
+
+ /* Setup w32_display_info structure for this frame. */
+
+ w32_initialize_display_info (build_string ("Console"));
+
}
DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
- "Set screen colors.")
+ doc: /* Set screen colors. */)
(foreground, background)
Lisp_Object foreground;
Lisp_Object background;
{
char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
- char_attr_reverse = XFASTINT (background) + (XFASTINT (foreground) << 4);
Frecenter (Qnil);
return Qt;
}
DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
- "Set cursor size.")
+ doc: /* Set cursor size. */)
(size)
Lisp_Object size;
{
cci.dwSize = XFASTINT (size);
cci.bVisible = TRUE;
(void) SetConsoleCursorInfo (cur_screen, &cci);
-
- return Qt;
-}
-#ifndef HAVE_NTGUI
-void
-pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
- void *bounds, int noclip)
-{
- *x = pix_x;
- *y = pix_y;
-}
-
-void
-glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
-{
- *pix_x = x;
- *pix_y = y;
+ return Qt;
}
-#endif /* !HAVE_NTGUI */
void
syms_of_ntterm ()
{
+ DEFVAR_BOOL ("w32-use-full-screen-buffer",
+ &w32_use_full_screen_buffer,
+ doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
+This is desirable when running Emacs over telnet, and is the default.
+A value of nil means use the current console window dimensions; this
+may be preferrable when working directly at the console with a large
+scroll-back buffer. */);
+ w32_use_full_screen_buffer = 0;
+
defsubr (&Sset_screen_color);
defsubr (&Sset_cursor_size);
defsubr (&Sset_message_beep);
}
+
+/* arch-tag: a390a07f-f661-42bc-aeb4-e6d8bf860337
+ (do not change this comment) */