/* Terminal hooks for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1992, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1999, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007 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
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 insert_glyphs (struct glyph *start, int len);
-static void write_glyphs (struct 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 (struct frame * f);
-static void update_end (struct frame * f);
+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;
#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;
}
/* Clear from cursor to end of screen. */
-void
-clear_to_end (void)
+static void
+w32con_clear_to_end (void)
{
struct frame * f = PICK_FRAME ();
- clear_end_of_line (FRAME_WIDTH (f) - 1);
- ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
+ 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)
{
struct frame * f = PICK_FRAME ();
COORD dest;
GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
/* Remember that the screen buffer might be wider than the window. */
- n = FRAME_HEIGHT (f) * info.dwSize.X;
+ n = FRAME_LINES (f) * info.dwSize.X;
dest.X = dest.Y = 0;
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 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)
{
}
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;
SMALL_RECT scroll;
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;
{
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));
}
}
}
{
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));
}
}
}
#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
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;
/* If start is zero insert blanks instead of a string at start ?. */
-void
-insert_glyphs (register struct 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 struct 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)
{
int produced, consumed;
DWORD r;
struct frame * f = PICK_FRAME ();
WORD char_attr;
- unsigned char conversion_buffer[1024];
- int conversion_buffer_size = sizeof conversion_buffer;
+ unsigned char *conversion_buffer;
+ struct coding_system *coding;
if (len <= 0)
return;
+ /* 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;
/* Turn appearance modes of the face of the run on. */
char_attr = w32_face_attributes (f, face_id);
- while (n > 0)
- {
- /* We use a fixed size (1024 bytes) of conversion buffer.
- Usually it is sufficient, but if not, we just repeat the
- loop. */
- produced = encode_terminal_code (string, conversion_buffer,
- n, conversion_buffer_size,
- &consumed);
- if (produced > 0)
+ 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))
{
- /* Set the attribute for these characters. */
- if (!FillConsoleOutputAttribute (cur_screen, char_attr,
- produced, cursor_coords, &r))
- {
- printf ("Failed writing console attributes: %d\n",
- GetLastError ());
- fflush (stdout);
- }
-
- /* Write the characters. */
- if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
- produced, cursor_coords, &r))
- {
- printf ("Failed writing console characters: %d\n",
- GetLastError ());
- fflush (stdout);
- }
-
- cursor_coords.X += produced;
- move_cursor (cursor_coords.Y, cursor_coords.X);
- }
- len -= consumed;
- n -= consumed;
- string += consumed;
- }
- }
-
- /* We may have to output some codes to terminate the writing. */
- if (CODING_REQUIRE_FLUSHING (&terminal_coding))
- {
- terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
- encode_coding (&terminal_coding, "", conversion_buffer,
- 0, conversion_buffer_size);
- if (terminal_coding.produced > 0)
- {
- if (!FillConsoleOutputAttribute (cur_screen, char_attr_normal,
- terminal_coding.produced,
- cursor_coords, &r))
- {
- printf ("Failed writing console attributes: %d\n",
- GetLastError ());
- fflush (stdout);
- }
-
- /* Write the characters. */
- if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
- produced, cursor_coords, &r))
- {
- printf ("Failed writing console characters: %d\n",
- GetLastError ());
- fflush (stdout);
- }
- }
+ 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;
}
}
-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
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;
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 (struct frame * f)
+static void
+w32con_update_begin (struct frame * f)
{
}
-void
-update_end (struct frame * 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)
{
}
{
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;
- 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;
- estimate_mode_line_height_hook = 0;
/* Initialize interrupt_handle. */
init_crit ();
meta_key = 1;
char_attr_normal = info.wAttributes;
- if (w32_use_full_screen_buffer)
+ /* 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_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
- SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
+ 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_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
+ FRAME_LINES (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
info.srWindow.Top;
/* Characters per line. Use buffer coords instead of buffer size. */
- SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right -
+ SET_FRAME_COLS (SELECTED_FRAME (), 1 + info.srWindow.Right -
info.srWindow.Left);
}
return Qt;
}
-#ifndef HAVE_NTGUI
-void
-pixel_to_glyph_coords (struct frame * 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 (struct window * f, int x, int y, int *pix_x, int *pix_y)
-{
- *pix_x = x;
- *pix_y = y;
-}
-#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.
+This is desirable when running Emacs over telnet.
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 = 1;
+ 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) */