X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/d9191744d0a7c970924eb191fb856b949d269b5b..3b58be21ad635ed6ae5a94c6b24187fb1ffb4f43:/src/w32console.c diff --git a/src/w32console.c b/src/w32console.c index c784f80463..d2f0e06a64 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -1,5 +1,6 @@ /* 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. @@ -15,8 +16,8 @@ GNU General Public License for more details. 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 @@ -53,20 +54,20 @@ extern int read_input_pending (); 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; @@ -103,8 +104,8 @@ ctrl_c_handler (unsigned long type) #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; @@ -116,18 +117,18 @@ move_cursor (int row, int col) } /* 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; @@ -138,13 +139,13 @@ clear_frame (void) 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); } @@ -152,8 +153,8 @@ 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) { @@ -164,12 +165,12 @@ clear_end_of_line (int end) } 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; @@ -180,17 +181,17 @@ ins_del_lines (int vpos, int n) 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; @@ -212,8 +213,8 @@ ins_del_lines (int vpos, int n) { 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)); } } } @@ -225,8 +226,8 @@ ins_del_lines (int vpos, int n) { 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)); } } } @@ -240,7 +241,7 @@ ins_del_lines (int vpos, int n) #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 @@ -256,12 +257,12 @@ scroll_line (int dist, int direction) 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; @@ -275,8 +276,8 @@ scroll_line (int dist, int direction) /* 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); @@ -286,27 +287,35 @@ insert_glyphs (register struct glyph *start, register int len) /* 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; @@ -324,75 +333,43 @@ write_glyphs (register struct glyph *string, register int len) /* 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 @@ -450,8 +427,8 @@ SOUND is nil to use the normal beep. */) return sound; } -void -reset_terminal_modes (void) +static void +w32con_reset_terminal_modes (void) { #ifdef USE_SEPARATE_SCREEN SetConsoleActiveScreenBuffer (prev_screen); @@ -461,8 +438,8 @@ reset_terminal_modes (void) SetConsoleMode (keyboard_handle, prev_console_mode); } -void -set_terminal_modes (void) +static void +w32con_set_terminal_modes (void) { CONSOLE_CURSOR_INFO cci; @@ -484,19 +461,19 @@ set_terminal_modes (void) 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) { } @@ -574,21 +551,21 @@ 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; - 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; @@ -659,18 +636,35 @@ initialize_w32_display (void) 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); } @@ -705,36 +699,22 @@ DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0, 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) */