Update years in copyright notice; nfc.
[bpt/emacs.git] / src / w32console.c
index b2d340d..dbadee3 100644 (file)
@@ -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, 2002, 2003, 2004,
+                 2005, 2006 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);
-void clear_frame (void);
-void clear_end_of_line (int);
-static void ins_del_lines (int vpos, int n);
-void insert_glyphs (struct glyph *start, int len);
-void write_glyphs (struct glyph *string, int len);
-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);
-void reset_terminal_modes (void);
-void set_terminal_modes (void);
-void set_terminal_window (int size);
-void update_begin (struct frame * f);
-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;
@@ -104,7 +105,7 @@ ctrl_c_handler (unsigned long type)
 
 /* Move the cursor to (row, col).  */
 static void
-move_cursor (int row, int col)
+w32con_move_cursor (int row, int col)
 {
   cursor_coords.X = col;
   cursor_coords.Y = row;
@@ -117,17 +118,17 @@ move_cursor (int row, int col)
 
 /* Clear from cursor to end of screen.  */
 static void
-clear_to_end (void)
+w32con_clear_to_end (void)
 {
   struct frame * f = PICK_FRAME ();
 
-  clear_end_of_line (FRAME_COLS (f) - 1);
-  ins_del_lines (cursor_coords.Y, FRAME_LINES (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;
@@ -144,7 +145,7 @@ clear_frame (void)
   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;
@@ -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_COLS (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_COLS (f));
+             w32con_move_cursor (i, 0);
+             w32con_clear_end_of_line (FRAME_COLS (f));
             }
         }
     }
@@ -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,7 +636,24 @@ 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_LINES (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
       SET_FRAME_COLS (SELECTED_FRAME (), info.dwSize.X);  /* characters per line */
@@ -715,7 +709,7 @@ 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 = 1;
+  w32_use_full_screen_buffer = 0;
 
   defsubr (&Sset_screen_color);
   defsubr (&Sset_cursor_size);