]> code.delx.au - gnu-emacs/blobdiff - src/term.c
(set_text_properties): New function. Like
[gnu-emacs] / src / term.c
index 3663c44ff91fed7dd6bbd496c430b488e2101488..fc6fa1031872b9cd6d3f78fa96610288854646b8 100644 (file)
@@ -1,5 +1,6 @@
 /* terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 98
+     Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,32 +16,64 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
+/* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>.  */
 
+
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
-#include "config.h"
+#include <string.h>
 #include "termchar.h"
 #include "termopts.h"
-#include "cm.h"
-#undef NULL
 #include "lisp.h"
-#include "screen.h"
+#include "charset.h"
+#include "coding.h"
+#include "frame.h"
 #include "disptab.h"
 #include "termhooks.h"
 #include "keyboard.h"
+#include "dispextern.h"
+#include "window.h"
+
+#ifdef HAVE_TERMCAP_H
+#include <termcap.h>
+#endif
+
+#include "cm.h"
+#ifdef HAVE_X_WINDOWS
+#include "xterm.h"
+#endif
+
+static void turn_on_face P_ ((struct frame *, int face_id));
+static void turn_off_face P_ ((struct frame *, int face_id));
+static void tty_show_cursor P_ ((void));
+static void tty_hide_cursor P_ ((void));
 
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
-#define OUTPUT(a) tputs (a, SCREEN_HEIGHT (selected_screen) - curY, cmputc)
+#define OUTPUT(a) \
+     tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame)) - curY), cmputc)
 #define OUTPUT1(a) tputs (a, 1, cmputc)
 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
-#define OUTPUT_IF(a) { if (a) tputs (a, SCREEN_HEIGHT (selected_screen) - curY, cmputc); }
-#define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
 
-/* Terminal charateristics that higher levels want to look at.
+#define OUTPUT_IF(a)                                                   \
+     do {                                                              \
+       if (a)                                                          \
+         tputs (a, (int) (FRAME_HEIGHT (XFRAME (selected_frame))       \
+                         - curY), cmputc);                             \
+     } while (0)
+     
+#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
+
+/* Function to use to ring the bell.  */
+
+Lisp_Object Vring_bell_function;
+
+/* Terminal characteristics that higher levels want to look at.
    These are all extern'd in termchar.h */
 
 int must_write_spaces;         /* Nonzero means spaces in the text
@@ -52,69 +85,156 @@ int line_ins_del_ok;               /* Terminal can insert and delete lines */
 int char_ins_del_ok;           /* Terminal can insert and delete chars */
 int scroll_region_ok;          /* Terminal supports setting the
                                   scroll window */
-int memory_below_screen;       /* Terminal remembers lines
+int scroll_region_cost;                /* Cost of setting a scroll window,
+                                  measured in characters */
+int memory_below_frame;                /* Terminal remembers lines
                                   scrolled off bottom */
 int fast_clear_end_of_line;    /* Terminal has a `ce' string */
 
-int dont_calculate_costs;      /* Nonzero means don't bother computing */
-                               /* various cost tables; we won't use them.  */
-
-/* Nonzero means no need to redraw the entire screen on resuming
+/* Nonzero means no need to redraw the entire frame on resuming
    a suspended Emacs.  This is useful on terminals with multiple pages,
    where one page is used for Emacs and another for all else. */
+
 int no_redraw_on_reenter;
 
 /* Hook functions that you can set to snap out the functions in this file.
    These are all extern'd in termhooks.h  */
 
-int (*cursor_to_hook) ();
-int (*raw_cursor_to_hook) ();
+void (*cursor_to_hook) P_ ((int, int));
+void (*raw_cursor_to_hook) P_ ((int, int));
+void (*clear_to_end_hook) P_ ((void));
+void (*clear_frame_hook) P_ ((void));
+void (*clear_end_of_line_hook) P_ ((int));
+
+void (*ins_del_lines_hook) P_ ((int, int));
+
+void (*change_line_highlight_hook) P_ ((int, int, int, int));
+void (*reassert_line_highlight_hook) P_ ((int, int));
+
+void (*delete_glyphs_hook) P_ ((int));
+
+void (*ring_bell_hook) P_ ((void));
+
+void (*reset_terminal_modes_hook) P_ ((void));
+void (*set_terminal_modes_hook) P_ ((void));
+void (*update_begin_hook) P_ ((struct frame *));
+void (*update_end_hook) P_ ((struct frame *));
+void (*set_terminal_window_hook) P_ ((int));
+void (*insert_glyphs_hook) P_ ((struct glyph *, int));
+void (*write_glyphs_hook) P_ ((struct glyph *, int));
+void (*delete_glyphs_hook) P_ ((int));
 
-int (*clear_to_end_hook) ();
-int (*clear_screen_hook) ();
-int (*clear_end_of_line_hook) ();
+int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
 
-int (*ins_del_lines_hook) ();
+void (*frame_up_to_date_hook) P_ ((struct frame *));
 
-int (*change_line_highlight_hook) ();
-int (*reassert_line_highlight_hook) ();
+/* Return the current position of the mouse.
 
-int (*insert_glyphs_hook) ();
-int (*write_glyphs_hook) ();
-int (*delete_glyphs_hook) ();
+   Set *f to the frame the mouse is in, or zero if the mouse is in no
+   Emacs frame.  If it is set to zero, all the other arguments are
+   garbage.
 
-int (*ring_bell_hook) ();
+   If the motion started in a scroll bar, set *bar_window to the
+   scroll bar's window, *part to the part the mouse is currently over,
+   *x to the position of the mouse along the scroll bar, and *y to the
+   overall length of the scroll bar.
 
-int (*reset_terminal_modes_hook) ();
-int (*set_terminal_modes_hook) ();
-int (*update_begin_hook) ();
-int (*update_end_hook) ();
-int (*set_terminal_window_hook) ();
+   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
+   row of the character cell the mouse is over.
 
-int (*read_socket_hook) ();
+   Set *time to the time the mouse was at the returned position.
 
-/* Return the current position of the mouse.  This should clear
-   mouse_moved until the next motion event arrives.  */
-void (*mouse_position_hook) ( /* SCREEN_PTR *s,
-                                       Lisp_Object *x,
-                                       Lisp_Object *y,
-                                       unsigned long *time */ );
+   This should clear mouse_moved until the next motion
+   event arrives.  */
+void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
+                                Lisp_Object *bar_window,
+                                enum scroll_bar_part *part,
+                                Lisp_Object *x,
+                                Lisp_Object *y,
+                                unsigned long *time));
 
-/* When reading from a minibuffer in a different screen, Emacs wants
-   to shift the highlight from the selected screen to the minibuffer's
-   screen; under X, this means it lies about where the focus is.
+/* When reading from a minibuffer in a different frame, Emacs wants
+   to shift the highlight from the selected frame to the mini-buffer's
+   frame; under X, this means it lies about where the focus is.
    This hook tells the window system code to re-decide where to put
    the highlight.  */
-void (*screen_rehighlight_hook) ( /* SCREEN_PTR s */ );
+void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
+
+/* If we're displaying frames using a window system that can stack
+   frames on top of each other, this hook allows you to bring a frame
+   to the front, or bury it behind all the other windows.  If this
+   hook is zero, that means the device we're displaying on doesn't
+   support overlapping frames, so there's no need to raise or lower
+   anything.
+
+   If RAISE is non-zero, F is brought to the front, before all other
+   windows.  If RAISE is zero, F is sent to the back, behind all other
+   windows.  */
+void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
+
+/* Set the vertical scroll bar for WINDOW to have its upper left corner
+   at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
+   indicate that we are displaying PORTION characters out of a total
+   of WHOLE characters, starting at POSITION.  If WINDOW doesn't yet
+   have a scroll bar, create one for it.  */
+
+void (*set_vertical_scroll_bar_hook)
+     P_ ((struct window *window,
+         int portion, int whole, int position));
+
+
+/* The following three hooks are used when we're doing a thorough
+   redisplay of the frame.  We don't explicitly know which scroll bars
+   are going to be deleted, because keeping track of when windows go
+   away is a real pain - can you say set-window-configuration?
+   Instead, we just assert at the beginning of redisplay that *all*
+   scroll bars are to be removed, and then save scroll bars from the
+   fiery pit when we actually redisplay their window.  */
+
+/* Arrange for all scroll bars on FRAME to be removed at the next call
+   to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
+   `*redeem_scroll_bar_hook' is applied to its window before the judgment. 
+
+   This should be applied to each frame each time its window tree is
+   redisplayed, even if it is not displaying scroll bars at the moment;
+   if the HAS_SCROLL_BARS flag has just been turned off, only calling
+   this and the judge_scroll_bars_hook will get rid of them.
+
+   If non-zero, this hook should be safe to apply to any frame,
+   whether or not it can support scroll bars, and whether or not it is
+   currently displaying them.  */
+void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
+
+/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
+   Note that it's okay to redeem a scroll bar that is not condemned.  */
+void (*redeem_scroll_bar_hook) P_ ((struct window *window));
+
+/* Remove all scroll bars on FRAME that haven't been saved since the
+   last call to `*condemn_scroll_bars_hook'.  
+
+   This should be applied to each frame after each time its window
+   tree is redisplayed, even if it is not displaying scroll bars at the
+   moment; if the HAS_SCROLL_BARS flag has just been turned off, only
+   calling this and condemn_scroll_bars_hook will get rid of them.
+
+   If non-zero, this hook should be safe to apply to any frame,
+   whether or not it can support scroll bars, and whether or not it is
+   currently displaying them.  */
+void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
+
+/* Hook to call in estimate_mode_line_height, if any.  */
+
+int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id));
+
 
 /* Strings, numbers and flags taken from the termcap entry.  */
 
-char *TS_ins_line;             /* termcap "al" */
+char *TS_ins_line;             /* "al" */
 char *TS_ins_multi_lines;      /* "AL" (one parameter, # lines to insert) */
 char *TS_bell;                 /* "bl" */
 char *TS_clr_to_bottom;                /* "cd" */
 char *TS_clr_line;             /* "ce", clear to end of line */
-char *TS_clr_screen;           /* "cl" */
+char *TS_clr_frame;            /* "cl" */
 char *TS_set_scroll_region;    /* "cs" (2 params, first line and last line) */
 char *TS_set_scroll_region_1;   /* "cS" (4 params: total lines,
                                   lines above scroll region, lines below it,
@@ -142,16 +262,68 @@ char *TS_rev_scroll;              /* "sr" */
 char *TS_end_termcap_modes;    /* "te" */
 char *TS_termcap_modes;                /* "ti" */
 char *TS_visible_bell;         /* "vb" */
-char *TS_end_visual_mode;      /* "ve" */
-char *TS_visual_mode;          /* "vi" */
+char *TS_cursor_normal;                /* "ve" */
+char *TS_cursor_visible;       /* "vs" */
+char *TS_cursor_invisible;     /* "vi" */
 char *TS_set_window;           /* "wi" (4 params, start and end of window,
                                   each as vpos and hpos) */
 
+/* "md" -- turn on bold (extra bright mode).  */
+
+char *TS_enter_bold_mode;
+
+/* "mh" -- turn on half-bright mode.  */
+
+char *TS_enter_dim_mode;
+
+/* "mb" -- enter blinking mode.  */
+
+char *TS_enter_blink_mode;
+
+/* "mr" -- enter reverse video mode.  */
+
+char *TS_enter_reverse_mode;
+
+/* "us"/"ue" -- start/end underlining.  */
+
+char *TS_exit_underline_mode, *TS_enter_underline_mode;
+
+/* "ug" -- number of blanks left by underline.  */
+
+int TN_magic_cookie_glitch_ul;
+
+/* "as"/"ae" -- start/end alternate character set.  Not really
+   supported, yet.  */
+
+char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
+
+/* "me" -- switch appearances off.  */
+
+char *TS_exit_attribute_mode;
+
+/* "Co" -- number of colors.  */
+
+int TN_max_colors;
+
+/* "pa" -- max. number of color pairs on screen.  Not handled yet.
+   Could be a problem if not equal to TN_max_colors * TN_max_colors.  */
+
+int TN_max_pairs;
+
+/* "op" -- SVr4 set default pair to its original value.  */
+
+char *TS_orig_pair;
+
+/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
+   1 param, the color index.  */
+
+char *TS_set_foreground, *TS_set_background;
+
 int TF_hazeltine;      /* termcap hz flag. */
 int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
 int TF_standout_motion;        /* termcap mi flag: can move while in standout mode. */
-int TF_underscore;     /* termcap ul flag: _ underlines if overstruck on
-                          nonblank position.  Must clear before writing _.  */
+int TF_underscore;     /* termcap ul flag: _ underlines if over-struck on
+                          non-blank position.  Must clear before writing _.  */
 int TF_teleray;                /* termcap xt flag: many weird consequences.
                           For t1061. */
 
@@ -171,8 +343,17 @@ static int se_is_so;       /* 1 if same string both enters and leaves
 
 /* internal state */
 
+/* The largest frame width in any call to calculate_costs.  */
+
+int max_frame_width;
+
+/* The largest frame height in any call to calculate_costs.  */
+
+int max_frame_height;
+
 /* Number of chars of space used for standout marker at beginning of line,
    or'd with 0100.  Zero if no standout marker at all.
+   The length of these vectors is max_frame_height.
 
    Used IFF TN_standout_width >= 0. */
 
@@ -180,30 +361,71 @@ static char *chars_wasted;
 static char *copybuf;
 
 /* nonzero means supposed to write text in standout mode.  */
+
 int standout_requested;
 
 int insert_mode;                       /* Nonzero when in insert mode.  */
 int standout_mode;                     /* Nonzero when in standout mode.  */
 
 /* Size of window specified by higher levels.
-   This is the number of lines, from the top of screen downwards,
+   This is the number of lines, from the top of frame downwards,
    which can participate in insert-line/delete-line operations.
 
-   Effectively it excludes the bottom screen_height - specified_window_size
+   Effectively it excludes the bottom frame_height - specified_window_size
    lines from those operations.  */
 
 int specified_window;
 
-/* Screen currently being redisplayed; 0 if not currently redisplaying.
+/* Frame currently being redisplayed; 0 if not currently redisplaying.
    (Direct output does not count).  */
 
-SCREEN_PTR updating_screen;
+FRAME_PTR updating_frame;
+
+/* Provided for lisp packages.  */
+
+static int system_uses_terminfo;
 
 char *tparam ();
+
+extern char *tgetstr ();
 \f
+
+#ifdef WINDOWSNT
+
+/* We aren't X windows, but we aren't termcap either.  This makes me
+   uncertain as to what value to use for frame.output_method.  For
+   this file, we'll define FRAME_TERMCAP_P to be zero so that our
+   output hooks get called instead of the termcap functions.  Probably
+   the best long-term solution is to define an output_windows_nt...  */
+
+#undef FRAME_TERMCAP_P
+#define FRAME_TERMCAP_P(_f_) 0
+#endif /* WINDOWSNT */
+
+void
 ring_bell ()
 {
-  if (! SCREEN_IS_TERMCAP (selected_screen))
+  if (! NILP (Vring_bell_function))
+    {
+      Lisp_Object function;
+
+      /* Temporarily set the global variable to nil
+        so that if we get an error, it stays nil
+        and we don't call it over and over.
+
+        We don't specbind it, because that would carefully
+        restore the bad value if there's an error
+        and make the loop of errors happen anyway.  */
+      function = Vring_bell_function;
+      Vring_bell_function = Qnil;
+
+      call0 (function);
+
+      Vring_bell_function = function;
+      return;
+    }
+
+  if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
       (*ring_bell_hook) ();
       return;
@@ -211,81 +433,97 @@ ring_bell ()
   OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
 }
 
+void
 set_terminal_modes ()
 {
-  if (! SCREEN_IS_TERMCAP (selected_screen))
+  if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
       (*set_terminal_modes_hook) ();
       return;
     }
   OUTPUT_IF (TS_termcap_modes);
-  OUTPUT_IF (TS_visual_mode);
+  OUTPUT_IF (TS_cursor_visible);
   OUTPUT_IF (TS_keypad_mode);
   losecursor ();
 }
 
+void
 reset_terminal_modes ()
 {
-  if (! SCREEN_IS_TERMCAP (selected_screen))
+  if (! FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      (*reset_terminal_modes_hook) ();
+      if (reset_terminal_modes_hook)
+       (*reset_terminal_modes_hook) ();
       return;
     }
   if (TN_standout_width < 0)
     turn_off_highlight ();
   turn_off_insert ();
   OUTPUT_IF (TS_end_keypad_mode);
-  OUTPUT_IF (TS_end_visual_mode);
+  OUTPUT_IF (TS_cursor_normal);
   OUTPUT_IF (TS_end_termcap_modes);
+  OUTPUT_IF (TS_orig_pair);
   /* Output raw CR so kernel can track the cursor hpos.  */
   /* But on magic-cookie terminals this can erase an end-standout marker and
-     cause the rest of the screen to be in standout, so move down first.  */
+     cause the rest of the frame to be in standout, so move down first.  */
   if (TN_standout_width >= 0)
     cmputc ('\n');
   cmputc ('\r');
 }
 
-update_begin (s)
-     SCREEN_PTR s;
+void
+update_begin (f)
+     FRAME_PTR f;
 {
-  updating_screen = s;
-  if (! SCREEN_IS_TERMCAP (updating_screen))
-    (*update_begin_hook) (s);
+  updating_frame = f;
+  if (! FRAME_TERMCAP_P (updating_frame))
+    (*update_begin_hook) (f);
+  else
+    tty_hide_cursor ();
 }
 
-update_end (s)
-     SCREEN_PTR s;
+void
+update_end (f)
+     FRAME_PTR f;
 {
-  if (! SCREEN_IS_TERMCAP (updating_screen))
+  if (! FRAME_TERMCAP_P (updating_frame))
     {
-      (*update_end_hook) (s);
-      updating_screen = 0;
+      (*update_end_hook) (f);
+      updating_frame = 0;
       return;
     }
+
+  if (!XWINDOW (selected_window)->cursor_off_p)
+    tty_show_cursor ();
+  
   turn_off_insert ();
   background_highlight ();
   standout_requested = 0;
-  updating_screen = 0;
+  updating_frame = 0;
 }
 
+void
 set_terminal_window (size)
      int size;
 {
-  if (! SCREEN_IS_TERMCAP (updating_screen))
+  if (! FRAME_TERMCAP_P (updating_frame))
     {
       (*set_terminal_window_hook) (size);
       return;
     }
-  specified_window = size ? size : SCREEN_HEIGHT (selected_screen);
+  specified_window = size ? size : FRAME_HEIGHT (XFRAME (selected_frame));
   if (!scroll_region_ok)
     return;
   set_scroll_region (0, specified_window);
 }
 
+void
 set_scroll_region (start, stop)
      int start, stop;
 {
   char *buf;
+  struct frame *sf = XFRAME (selected_frame);
+  
   if (TS_set_scroll_region)
     {
       buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
@@ -293,19 +531,20 @@ set_scroll_region (start, stop)
   else if (TS_set_scroll_region_1)
     {
       buf = tparam (TS_set_scroll_region_1, 0, 0,
-                   SCREEN_HEIGHT (selected_screen), start,
-                   SCREEN_HEIGHT (selected_screen) - stop,
-                   SCREEN_HEIGHT (selected_screen));
+                   FRAME_HEIGHT (sf), start,
+                   FRAME_HEIGHT (sf) - stop,
+                   FRAME_HEIGHT (sf));
     }
   else
     {
-      buf = tparam (TS_set_window, 0, 0, start, 0, stop, SCREEN_WIDTH (selected_screen));
+      buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (sf));
     }
   OUTPUT (buf);
-  free (buf);
+  xfree (buf);
   losecursor ();
 }
 \f
+void
 turn_on_insert ()
 {
   if (!insert_mode)
@@ -313,6 +552,7 @@ turn_on_insert ()
   insert_mode = 1;
 }
 
+void
 turn_off_insert ()
 {
   if (insert_mode)
@@ -327,6 +567,7 @@ turn_off_insert ()
    These functions are called on all terminals, but do nothing
    on terminals whose standout mode does not work that way.  */
 
+void
 turn_off_highlight ()
 {
   if (TN_standout_width < 0)
@@ -337,6 +578,7 @@ turn_off_highlight ()
     }
 }
 
+void
 turn_on_highlight ()
 {
   if (TN_standout_width < 0)
@@ -347,10 +589,31 @@ turn_on_highlight ()
     }
 }
 
+
+/* Make cursor invisible.  */
+
+static void
+tty_hide_cursor ()
+{
+  OUTPUT_IF (TS_cursor_invisible);
+}
+
+
+/* Ensure that cursor is visible.  */
+
+static void
+tty_show_cursor ()
+{
+  OUTPUT_IF (TS_cursor_normal);
+  OUTPUT_IF (TS_cursor_visible);
+}
+
+
 /* Set standout mode to the state it should be in for
    empty space inside windows.  What this is,
    depends on the user option inverse-video.  */
 
+void
 background_highlight ()
 {
   if (TN_standout_width >= 0)
@@ -363,7 +626,7 @@ background_highlight ()
 
 /* Set standout mode to the mode specified for the text to be output.  */
 
-static
+static void
 highlight_if_desired ()
 {
   if (TN_standout_width >= 0)
@@ -376,7 +639,7 @@ highlight_if_desired ()
 \f
 /* Handle standout mode for terminals in which TN_standout_width >= 0.
    On these terminals, standout is controlled by markers that
-   live inside the screen memory.  TN_standout_width is the width
+   live inside the terminal's memory.  TN_standout_width is the width
    that the marker occupies in memory.  Standout runs from the marker
    to the end of the line on some terminals, or to the next
    turn-off-standout marker (TS_end_standout_mode) string
@@ -385,6 +648,7 @@ highlight_if_desired ()
 /* Write a standout marker or end-standout marker at the front of the line
    at vertical position vpos.  */
 
+void
 write_standout_marker (flag, vpos)
      int flag, vpos;
 {
@@ -402,11 +666,13 @@ write_standout_marker (flag, vpos)
    Call this when about to modify line at position VPOS
    and not change whether it is highlighted.  */
 
+void
 reassert_line_highlight (highlight, vpos)
      int highlight;
      int vpos;
 {
-  if (! SCREEN_IS_TERMCAP ((updating_screen ? updating_screen : selected_screen)))
+  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
+  if (! FRAME_TERMCAP_P (f))
     {
       (*reassert_line_highlight_hook) (highlight, vpos);
       return;
@@ -414,7 +680,7 @@ reassert_line_highlight (highlight, vpos)
   if (TN_standout_width < 0)
     /* Handle terminals where standout takes affect at output time */
     standout_requested = highlight;
-  else if (chars_wasted[vpos] == 0)
+  else if (chars_wasted && chars_wasted[vpos] == 0)
     /* For terminals with standout markers, write one on this line
        if there isn't one already.  */
     write_standout_marker (highlight, vpos);
@@ -423,13 +689,14 @@ reassert_line_highlight (highlight, vpos)
 /* Call this when about to modify line at position VPOS
    and change whether it is highlighted.  */
 
-change_line_highlight (new_highlight, vpos, first_unused_hpos)
-     int new_highlight, vpos, first_unused_hpos;
+void
+change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
+     int new_highlight, vpos, y, first_unused_hpos;
 {
   standout_requested = new_highlight;
-  if (! SCREEN_IS_TERMCAP (updating_screen))
+  if (! FRAME_TERMCAP_P (updating_frame))
     {
-      (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
+      (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos);
       return;
     }
 
@@ -444,7 +711,7 @@ change_line_highlight (new_highlight, vpos, first_unused_hpos)
       /* On Teleray, make sure to erase the SO marker.  */
       if (TF_teleray)
        {
-         cmgoto (curY - 1, SCREEN_WIDTH (selected_screen) - 4);
+         cmgoto (curY - 1, FRAME_WIDTH (XFRAME (selected_frame)) - 4);
          OUTPUT ("\033S");
          curY++;               /* ESC S moves to next line where the TS_standout_mode was */
          curX = 0;
@@ -457,36 +724,44 @@ change_line_highlight (new_highlight, vpos, first_unused_hpos)
 }
 \f
 
-/* Move to absolute position, specified origin 0 */
+/* Move cursor to row/column position VPOS/HPOS.  HPOS/VPOS are
+   frame-relative coordinates.  */
 
-cursor_to (row, col)
-     int row, col;
+void
+cursor_to (vpos, hpos)
+     int vpos, hpos;
 {
-  if (! SCREEN_IS_TERMCAP ((updating_screen
-                           ? updating_screen
-                           : selected_screen))
-      && cursor_to_hook)
+  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
+  
+  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
     {
-      (*cursor_to_hook) (row, col);
+      (*cursor_to_hook) (vpos, hpos);
       return;
     }
 
-  col += chars_wasted[row] & 077;
-  if (curY == row && curX == col)
+  /* Detect the case where we are called from reset_sys_modes
+     and the costs have never been calculated.  Do nothing.  */
+  if (chars_wasted == 0)
+    return;
+
+  hpos += chars_wasted[vpos] & 077;
+  if (curY == vpos && curX == hpos)
     return;
   if (!TF_standout_motion)
     background_highlight ();
   if (!TF_insmode_motion)
     turn_off_insert ();
-  cmgoto (row, col);
+  cmgoto (vpos, hpos);
 }
 
 /* Similar but don't take any account of the wasted characters.  */
 
+void
 raw_cursor_to (row, col)
      int row, col;
 {
-  if (! SCREEN_IS_TERMCAP ((updating_screen ? updating_screen : selected_screen)))
+  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
+  if (! FRAME_TERMCAP_P (f))
     {
       (*raw_cursor_to_hook) (row, col);
       return;
@@ -502,12 +777,13 @@ raw_cursor_to (row, col)
 \f
 /* Erase operations */
 
-/* clear from cursor to end of screen */
+/* clear from cursor to end of frame */
+void
 clear_to_end ()
 {
   register int i;
 
-  if (clear_to_end_hook && SCREEN_IS_TERMCAP (updating_screen))
+  if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
     {
       (*clear_to_end_hook) ();
       return;
@@ -516,33 +792,37 @@ clear_to_end ()
     {
       background_highlight ();
       OUTPUT (TS_clr_to_bottom);
-      bzero (chars_wasted + curY, SCREEN_HEIGHT (selected_screen) - curY);
+      bzero (chars_wasted + curY,
+            FRAME_HEIGHT (XFRAME (selected_frame)) - curY);
     }
   else
     {
-      for (i = curY; i < SCREEN_HEIGHT (selected_screen); i++)
+      for (i = curY; i < FRAME_HEIGHT (XFRAME (selected_frame)); i++)
        {
          cursor_to (i, 0);
-         clear_end_of_line_raw (SCREEN_WIDTH (selected_screen));
+         clear_end_of_line_raw (FRAME_WIDTH (XFRAME (selected_frame)));
        }
     }
 }
 
-/* Clear entire screen */
+/* Clear entire frame */
 
-clear_screen ()
+void
+clear_frame ()
 {
-  if (clear_screen_hook
-      && ! SCREEN_IS_TERMCAP ((updating_screen ? updating_screen : selected_screen)))
+  struct frame *sf = XFRAME (selected_frame);
+  
+  if (clear_frame_hook
+      && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
     {
-      (*clear_screen_hook) ();
+      (*clear_frame_hook) ();
       return;
     }
-  if (TS_clr_screen)
+  if (TS_clr_frame)
     {
       background_highlight ();
-      OUTPUT (TS_clr_screen);
-      bzero (chars_wasted, SCREEN_HEIGHT (selected_screen));
+      OUTPUT (TS_clr_frame);
+      bzero (chars_wasted, FRAME_HEIGHT (sf));
       cmat (0, 0);
     }
   else
@@ -559,13 +839,14 @@ clear_screen ()
 
    Note that the cursor may be moved.  */
 
+void
 clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
-  static GLYPH buf[1] = {SPACEGLYPH};
-  if (SCREEN_IS_TERMCAP (selected_screen)
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+      && chars_wasted != 0
       && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
-    write_glyphs (buf, 1);
+    write_glyphs (&space_glyph, 1);
   clear_end_of_line_raw (first_unused_hpos);
 }
 
@@ -575,20 +856,26 @@ clear_end_of_line (first_unused_hpos)
 
    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
 
+void
 clear_end_of_line_raw (first_unused_hpos)
      int first_unused_hpos;
 {
   register int i;
 
   if (clear_end_of_line_hook
-      && ! SCREEN_IS_TERMCAP ((updating_screen
-                              ? updating_screen
-                              : selected_screen)))
+      && ! FRAME_TERMCAP_P ((updating_frame
+                              ? updating_frame
+                            : XFRAME (selected_frame))))
     {
       (*clear_end_of_line_hook) (first_unused_hpos);
       return;
     }
 
+  /* Detect the case where we are called from reset_sys_modes
+     and the costs have never been calculated.  Do nothing.  */
+  if (chars_wasted == 0)
+    return;
+
   first_unused_hpos += chars_wasted[curY] & 077;
   if (curX >= first_unused_hpos)
     return;
@@ -602,11 +889,12 @@ clear_end_of_line_raw (first_unused_hpos)
     }
   else
     {                  /* have to do it the hard way */
+      struct frame *sf = XFRAME (selected_frame);
       turn_off_insert ();
 
-      /* Do not write in last row last col with Autowrap on. */
-      if (AutoWrap && curY == SCREEN_HEIGHT (selected_screen) - 1
-         && first_unused_hpos == SCREEN_WIDTH (selected_screen))
+      /* Do not write in last row last col with Auto-wrap on. */
+      if (AutoWrap && curY == FRAME_HEIGHT (sf) - 1
+         && first_unused_hpos == FRAME_WIDTH (sf))
        first_unused_hpos--;
 
       for (i = curX; i < first_unused_hpos; i++)
@@ -619,17 +907,112 @@ clear_end_of_line_raw (first_unused_hpos)
     }
 }
 \f
+/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
+   store them at DST.  Do not write more than DST_LEN bytes.  That may
+   require stopping before all SRC_LEN input glyphs have been
+   converted.
 
-write_glyphs (string, len)
-     register GLYPH *string;
-     register int len;
+   We store the number of glyphs actually converted in *CONSUMED.  The
+   return value is the number of bytes store in DST.  */
+
+int
+encode_terminal_code (src, dst, src_len, dst_len, consumed)
+     struct glyph *src;
+     int src_len;
+     unsigned char *dst;
+     int dst_len, *consumed;
 {
+  struct glyph *src_start = src, *src_end = src + src_len;
+  unsigned char *dst_start = dst, *dst_end = dst + dst_len;
   register GLYPH g;
+  unsigned int c;
+  unsigned char workbuf[4], *buf;
+  int len;
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
+  int result;
+  struct coding_system *coding;
+
+  coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
+           ? &terminal_coding
+           : &safe_terminal_coding);
+
+  while (src < src_end)
+    {
+      g = GLYPH_FROM_CHAR_GLYPH (*src);
+      
+      /* We must skip glyphs to be padded for a wide character.  */
+      if (! CHAR_GLYPH_PADDING_P (*src))
+       {
+         c = src->u.ch.code;
+         if (! GLYPH_CHAR_VALID_P (c))
+           {
+             c = ' ';
+             g = MAKE_GLYPH (sf, c, GLYPH_FACE (sf, g));
+           }
+         if (COMPOSITE_CHAR_P (c))
+           {
+             /* If C is a composite character, we can display
+                only the first component.  */
+             g = cmpchar_table[COMPOSITE_CHAR_ID (c)]->glyph[0],
+             c = GLYPH_CHAR (sf, g);
+           }
+         if (c < tlen)
+           {
+             /* G has an entry in Vglyph_table,
+                so process any alias before testing for simpleness.  */
+             GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
+             c = GLYPH_CHAR (sf, g);
+           }
+         if (GLYPH_SIMPLE_P (tbase, tlen, g))
+           /* We set the multi-byte form of C at BUF.  */
+           len = CHAR_STRING (c, workbuf, buf);
+         else
+           {
+             /* We have a string in Vglyph_table.  */
+             len = GLYPH_LENGTH (tbase, g);
+             buf = GLYPH_STRING (tbase, g);
+           }
+         
+         result = encode_coding (coding, buf, dst, len, dst_end - dst);
+         len -= coding->consumed;
+         dst += coding->produced;
+         if (result == CODING_FINISH_INSUFFICIENT_DST
+             || (result == CODING_FINISH_INSUFFICIENT_SRC
+                 && len > dst_end - dst))
+           /* The remaining output buffer is too short.  We must
+              break the loop here without increasing SRC so that the
+              next call of this function starts from the same glyph.  */
+           break;
+
+         if (len > 0)
+           {
+             /* This is the case that a code of the range 0200..0237
+                exists in buf.  We must just write out such a code.  */
+             buf += coding->consumed;
+             while (len--)
+               *dst++ = *buf++;
+           }
+       }
+      src++;
+    }
+  
+  *consumed = src - src_start;
+  return (dst - dst_start);
+}
+
+
+void
+write_glyphs (string, len)
+     register struct glyph *string;
+     register int len;
+{
+  int produced, consumed;
+  struct frame *sf = XFRAME (selected_frame);
+  struct frame *f = updating_frame ? updating_frame : sf;
 
   if (write_glyphs_hook
-      && ! SCREEN_IS_TERMCAP ((updating_screen ? updating_screen : selected_screen)))
+      && ! FRAME_TERMCAP_P (f))
     {
       (*write_glyphs_hook) (string, len);
       return;
@@ -638,76 +1021,109 @@ write_glyphs (string, len)
   highlight_if_desired ();
   turn_off_insert ();
 
-  /* Don't dare write in last column of bottom line, if AutoWrap,
-     since that would scroll the whole screen on some terminals.  */
+  /* Don't dare write in last column of bottom line, if Auto-Wrap,
+     since that would scroll the whole frame on some terminals.  */
 
   if (AutoWrap
-      && curY + 1 == SCREEN_HEIGHT (selected_screen)
-      && (curX + len - (chars_wasted[curY] & 077)
-         == SCREEN_WIDTH (selected_screen)))
+      && curY + 1 == FRAME_HEIGHT (sf)
+      && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (sf)))
     len --;
+  if (len <= 0)
+    return;
 
   cmplus (len);
-  while (--len >= 0)
+  
+  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+     the tail.  */
+  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+  
+  while (len > 0)
     {
-      g = *string++;
-      /* Check quickly for G beyond length of table.
-        That implies it isn't an alias and is simple.  */
-      if (g >= tlen)
+      /* Identify a run of glyphs with the same face.  */
+      int face_id = string->u.ch.face_id;
+      int n;
+      
+      for (n = 1; n < len; ++n)
+       if (string[n].u.ch.face_id != face_id)
+         break;
+
+      /* Turn appearance modes of the face of the run on.  */
+      turn_on_face (f, face_id);
+
+      while (n > 0)
        {
-       simple:
-         putc (g & 0xff, stdout);
-         if (ferror (stdout))
-           clearerr (stdout);
-         if (termscript)
-           putc (g & 0xff, termscript);
-       }
-      else
-       {
-         /* G has an entry in Vglyph_table,
-            so process any alias and then test for simpleness.  */
-         while (GLYPH_ALIAS_P (tbase, tlen, g))
-           g = GLYPH_ALIAS (tbase, g);
-         if (GLYPH_SIMPLE_P (tbase, tlen, g))
-           goto simple;
-         else
+         /* We use a shared conversion buffer of the current size
+            (1024 bytes at least).  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)
            {
-             /* Here if G (or its definition as an alias) is not simple.  */
-             fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
-                     stdout);
+             fwrite (conversion_buffer, 1, produced, stdout);
              if (ferror (stdout))
                clearerr (stdout);
              if (termscript)
-               fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
-                       termscript);
+               fwrite (conversion_buffer, 1, produced, termscript);
            }
+         len -= consumed;
+         n -= consumed;
+         string += consumed;
        }
+
+      /* Turn appearance modes off.  */
+      turn_off_face (f, face_id);
     }
+  
+  /* 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)
+       {
+         fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
+         if (ferror (stdout))
+           clearerr (stdout);
+         if (termscript)
+           fwrite (conversion_buffer, 1, terminal_coding.produced,
+                   termscript);
+       }
+    }
+  
+  cmcheckmagic ();
 }
 
 /* If start is zero, insert blanks instead of a string at start */
  
+void
 insert_glyphs (start, len)
-     register GLYPH *start;
+     register struct glyph *start;
      register int len;
 {
   char *buf;
-  register GLYPH g;
-  register int tlen = GLYPH_TABLE_LENGTH;
-  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
+  GLYPH g;
+  struct frame *f, *sf;
+
+  if (len <= 0)
+    return;
 
-  if (insert_glyphs_hook && ! SCREEN_IS_TERMCAP (updating_screen))
+  if (insert_glyphs_hook)
     {
       (*insert_glyphs_hook) (start, len);
       return;
     }
+
+  sf = XFRAME (selected_frame);
+  f = updating_frame ? updating_frame : sf;
   highlight_if_desired ();
 
   if (TS_ins_multi_chars)
     {
       buf = tparam (TS_ins_multi_chars, 0, 0, len);
       OUTPUT1 (buf);
-      free (buf);
+      xfree (buf);
       if (start)
        write_glyphs (start, len);
       return;
@@ -715,43 +1131,63 @@ insert_glyphs (start, len)
 
   turn_on_insert ();
   cmplus (len);
-  while (--len >= 0)
+  /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail.  */
+  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+  while (len-- > 0)
     {
+      int produced, consumed;
+      struct glyph glyph;
+
       OUTPUT1_IF (TS_ins_char);
       if (!start)
        g = SPACEGLYPH;
       else
-       g = *start++;
-
-      if (GLYPH_SIMPLE_P (tbase, tlen, g))
        {
-         putc (g & 0xff, stdout);
-         if (ferror (stdout))
-           clearerr (stdout);
-         if (termscript)
-           putc (g & 0xff, termscript);
+         g = GLYPH_FROM_CHAR_GLYPH (*start);
+         ++start;
+         /* We must open sufficient space for a character which
+            occupies more than one column.  */
+         while (len && CHAR_GLYPH_PADDING_P (*start))
+           {
+             OUTPUT1_IF (TS_ins_char);
+             start++, len--;
+           }
        }
-      else
+
+      if (len <= 0)
+       /* This is the last glyph.  */
+       terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
+
+      /* We use shared conversion buffer of the current size (1024
+        bytes at least).  It is surely sufficient for just one glyph.  */
+      SET_CHAR_GLYPH_FROM_GLYPH (glyph, g);
+      turn_on_face (f, glyph.u.ch.face_id);
+      produced = encode_terminal_code (&glyph, conversion_buffer,
+                                      1, conversion_buffer_size, &consumed);
+      if (produced > 0)
        {
-         fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout);
+         fwrite (conversion_buffer, 1, produced, stdout);
          if (ferror (stdout))
            clearerr (stdout);
          if (termscript)
-           fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g),
-                   termscript);
+           fwrite (conversion_buffer, 1, produced, termscript);
        }
 
-       OUTPUT1_IF (TS_pad_inserted_char);
-      }
+      OUTPUT1_IF (TS_pad_inserted_char);
+      turn_off_face (f, glyph.u.ch.face_id);
+    }
+  
+  cmcheckmagic ();
 }
 
+void
 delete_glyphs (n)
      register int n;
 {
   char *buf;
   register int i;
 
-  if (delete_glyphs_hook && ! SCREEN_IS_TERMCAP (updating_screen))
+  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
     {
       (*delete_glyphs_hook) (n);
       return;
@@ -771,7 +1207,7 @@ delete_glyphs (n)
     {
       buf = tparam (TS_del_multi_chars, 0, 0, n);
       OUTPUT1 (buf);
-      free (buf);
+      xfree (buf);
     }
   else
     for (i = 0; i < n; i++)
@@ -782,22 +1218,26 @@ delete_glyphs (n)
 \f
 /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
 
+void
 ins_del_lines (vpos, n)
      int vpos, n;
 {
   char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
   char *single = n > 0 ? TS_ins_line : TS_del_line;
   char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
+  struct frame *sf;
 
   register int i = n > 0 ? n : -n;
   register char *buf;
 
-  if (ins_del_lines_hook && ! SCREEN_IS_TERMCAP (updating_screen))
+  if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
     {
       (*ins_del_lines_hook) (vpos, n);
       return;
     }
 
+  sf = XFRAME (selected_frame);
+  
   /* If the lines below the insertion are being pushed
      into the end of the window, this is the same as clearing;
      and we know the lines are already clear, since the matching
@@ -807,7 +1247,7 @@ ins_del_lines (vpos, n)
      as there will be a matching inslines later that will flush them. */
   if (scroll_region_ok && vpos + i >= specified_window)
     return;
-  if (!memory_below_screen && vpos + i >= SCREEN_HEIGHT (selected_screen))
+  if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (sf))
     return;
 
   if (multi)
@@ -816,7 +1256,7 @@ ins_del_lines (vpos, n)
       background_highlight ();
       buf = tparam (multi, 0, 0, i);
       OUTPUT (buf);
-      free (buf);
+      xfree (buf);
     }
   else if (single)
     {
@@ -842,10 +1282,10 @@ ins_del_lines (vpos, n)
 
   if (TN_standout_width >= 0)
     {
-      register lower_limit
+      register int lower_limit
        = (scroll_region_ok
           ? specified_window
-          : SCREEN_HEIGHT (selected_screen));
+          : FRAME_HEIGHT (sf));
 
       if (n < 0)
        {
@@ -861,9 +1301,9 @@ ins_del_lines (vpos, n)
          bzero (&chars_wasted[vpos], n);
        }
     }
-  if (!scroll_region_ok && memory_below_screen && n < 0)
+  if (!scroll_region_ok && memory_below_frame && n < 0)
     {
-      cursor_to (SCREEN_HEIGHT (selected_screen) + n, 0);
+      cursor_to (FRAME_HEIGHT (sf) + n, 0);
       clear_to_end ();
     }
 }
@@ -912,17 +1352,18 @@ per_line_cost (str)
 
 #ifndef old
 /* char_ins_del_cost[n] is cost of inserting N characters.
-   char_ins_del_cost[-n] is cost of deleting N characters. */
+   char_ins_del_cost[-n] is cost of deleting N characters.
+   The length of this vector is based on max_frame_width.  */
 
 int *char_ins_del_vector;
 
-#define char_ins_del_cost(s) (&char_ins_del_vector[SCREEN_WIDTH ((s))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
 #endif
 
 /* ARGSUSED */
 static void
-calculate_ins_del_char_costs (screen)
-     SCREEN_PTR screen;
+calculate_ins_del_char_costs (frame)
+     FRAME_PTR frame;
 {
   int ins_startup_cost, del_startup_cost;
   int ins_cost_per_char, del_cost_per_char;
@@ -968,44 +1409,43 @@ calculate_ins_del_char_costs (screen)
     }
 
   /* Delete costs are at negative offsets */
-  p = &char_ins_del_cost (screen)[0];
-  for (i = SCREEN_WIDTH (selected_screen); --i >= 0;)
+  p = &char_ins_del_cost (frame)[0];
+  for (i = FRAME_WIDTH (frame); --i >= 0;)
     *--p = (del_startup_cost += del_cost_per_char);
 
   /* Doing nothing is free */
-  p = &char_ins_del_cost (screen)[0];
+  p = &char_ins_del_cost (frame)[0];
   *p++ = 0;
 
   /* Insert costs are at positive offsets */
-  for (i = SCREEN_WIDTH (screen); --i >= 0;)
+  for (i = FRAME_WIDTH (frame); --i >= 0;)
     *p++ = (ins_startup_cost += ins_cost_per_char);
 }
 
-#ifdef HAVE_X_WINDOWS
-extern int x_screen_planes;
-#endif
-
-calculate_costs (screen)
-     SCREEN_PTR screen;
+void
+calculate_costs (frame)
+     FRAME_PTR frame;
 {
-  register char *s = TS_set_scroll_region ?
-                       TS_set_scroll_region
-                    : TS_set_scroll_region_1;
+  register char *f = (TS_set_scroll_region
+                     ? TS_set_scroll_region
+                     : TS_set_scroll_region_1);
 
-  if (dont_calculate_costs)
-    return;
+  FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
+  scroll_region_cost = string_cost (f);
 #ifdef HAVE_X_WINDOWS
-  if (SCREEN_IS_X (screen))
+  if (FRAME_X_P (frame))
     {
-      do_line_insertion_deletion_costs (screen, 0, ".5*", 0, ".5*",
-                                       0, 0, x_screen_planes);
+      do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
+                                       0, 0,
+                                       x_screen_planes (frame));
+      scroll_region_cost = 0;
       return;
     }
 #endif
 
   /* These variables are only used for terminal stuff.  They are allocated
-     once for the terminal screen of X-windows emacs, but not used afterwards.
+     once for the terminal frame of X-windows emacs, but not used afterwards.
 
      char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
      X turns off char_ins_del_ok.
@@ -1013,53 +1453,147 @@ calculate_costs (screen)
      chars_wasted and copybuf are only used here in term.c in cases where
      the term hook isn't called. */
 
+  max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
+  max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
+
   if (chars_wasted != 0)
-    chars_wasted = (char *) xrealloc (chars_wasted, SCREEN_HEIGHT (screen));
+    chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
   else
-    chars_wasted = (char *) xmalloc (SCREEN_HEIGHT (screen));
+    chars_wasted = (char *) xmalloc (max_frame_height);
 
   if (copybuf != 0)
-    copybuf = (char *) xrealloc (copybuf, SCREEN_HEIGHT (screen));
+    copybuf = (char *) xrealloc (copybuf, max_frame_height);
   else
-    copybuf = (char *) xmalloc (SCREEN_HEIGHT (screen));
+    copybuf = (char *) xmalloc (max_frame_height);
 
   if (char_ins_del_vector != 0)
     char_ins_del_vector
       = (int *) xrealloc (char_ins_del_vector,
                          (sizeof (int)
-                          + 2 * SCREEN_WIDTH (screen) * sizeof (int)));
+                          + 2 * max_frame_width * sizeof (int)));
   else
     char_ins_del_vector
       = (int *) xmalloc (sizeof (int)
-                        + 2 * SCREEN_WIDTH (screen) * sizeof (int));
+                        + 2 * max_frame_width * sizeof (int));
 
-  bzero (chars_wasted, SCREEN_HEIGHT (screen));
-  bzero (copybuf, SCREEN_HEIGHT (screen));
+  bzero (chars_wasted, max_frame_height);
+  bzero (copybuf, max_frame_height);
   bzero (char_ins_del_vector, (sizeof (int)
-                              + 2 * SCREEN_WIDTH (screen) * sizeof (int)));
+                              + 2 * max_frame_width * sizeof (int)));
 
-  if (s && (!TS_ins_line && !TS_del_line))
-    do_line_insertion_deletion_costs (screen,
+  if (f && (!TS_ins_line && !TS_del_line))
+    do_line_insertion_deletion_costs (frame,
                                      TS_rev_scroll, TS_ins_multi_lines,
                                      TS_fwd_scroll, TS_del_multi_lines,
-                                     s, s, 1);
+                                     f, f, 1);
   else
-    do_line_insertion_deletion_costs (screen,
+    do_line_insertion_deletion_costs (frame,
                                      TS_ins_line, TS_ins_multi_lines,
                                      TS_del_line, TS_del_multi_lines,
                                      0, 0, 1);
 
-  calculate_ins_del_char_costs (screen);
+  calculate_ins_del_char_costs (frame);
 
   /* Don't use TS_repeat if its padding is worse than sending the chars */
   if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
     RPov = string_cost (TS_repeat);
   else
-    RPov = SCREEN_WIDTH (screen) * 2;
+    RPov = FRAME_WIDTH (frame) * 2;
 
   cmcostinit ();               /* set up cursor motion costs */
 }
 \f
+struct fkey_table {
+  char *cap, *name;
+};
+
+  /* Termcap capability names that correspond directly to X keysyms.
+     Some of these (marked "terminfo") aren't supplied by old-style
+     (Berkeley) termcap entries.  They're listed in X keysym order;
+     except we put the keypad keys first, so that if they clash with
+     other keys (as on the IBM PC keyboard) they get overridden.
+  */
+
+static struct fkey_table keys[] =
+{
+  "kh", "home",                /* termcap */
+  "kl", "left",                /* termcap */
+  "ku", "up",          /* termcap */
+  "kr", "right",       /* termcap */
+  "kd", "down",                /* termcap */
+  "%8", "prior",       /* terminfo */
+  "%5", "next",                /* terminfo */
+  "@7",        "end",          /* terminfo */
+  "@1", "begin",       /* terminfo */
+  "*6", "select",      /* terminfo */
+  "%9", "print",       /* terminfo */
+  "@4", "execute",     /* terminfo --- actually the `command' key */
+  /*
+   * "insert" --- see below
+   */
+  "&8",        "undo",         /* terminfo */
+  "%0",        "redo",         /* terminfo */
+  "%7",        "menu",         /* terminfo --- actually the `options' key */
+  "@0",        "find",         /* terminfo */
+  "@2",        "cancel",       /* terminfo */
+  "%1", "help",                /* terminfo */
+  /*
+   * "break" goes here, but can't be reliably intercepted with termcap
+   */
+  "&4", "reset",       /* terminfo --- actually `restart' */
+  /*
+   * "system" and "user" --- no termcaps
+   */
+  "kE", "clearline",   /* terminfo */
+  "kA", "insertline",  /* terminfo */
+  "kL", "deleteline",  /* terminfo */
+  "kI", "insertchar",  /* terminfo */
+  "kD", "deletechar",  /* terminfo */
+  "kB", "backtab",     /* terminfo */
+  /*
+   * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
+   */
+  "@8", "kp-enter",    /* terminfo */
+  /*
+   * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
+   * "kp-multiply", "kp-add", "kp-separator",
+   * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
+   * --- no termcaps for any of these.
+   */
+  "K4", "kp-1",                /* terminfo */
+  /*
+   * "kp-2" --- no termcap
+   */
+  "K5", "kp-3",                /* terminfo */
+  /*
+   * "kp-4" --- no termcap
+   */
+  "K2", "kp-5",                /* terminfo */
+  /*
+   * "kp-6" --- no termcap
+   */
+  "K1", "kp-7",                /* terminfo */
+  /*
+   * "kp-8" --- no termcap
+   */
+  "K3", "kp-9",                /* terminfo */
+  /*
+   * "kp-equal" --- no termcap
+   */
+  "k1",        "f1",
+  "k2",        "f2",
+  "k3",        "f3",
+  "k4",        "f4",
+  "k5",        "f5",
+  "k6",        "f6",
+  "k7",        "f7",
+  "k8",        "f8",
+  "k9",        "f9",
+  };
+
+static char **term_get_fkeys_arg;
+static Lisp_Object term_get_fkeys_1 ();
+
 /* Find the escape codes sent by the function keys for Vfunction_key_map.
    This function scans the termcap function key sequence entries, and 
    adds entries to Vfunction_key_map for each function key it finds.  */
@@ -1068,55 +1602,459 @@ void
 term_get_fkeys (address)
      char **address;
 {
-  extern char *tgetstr ();
-  struct fkey_table {
-    char *cap, *name;
-  };
-  static struct fkey_table keys[] = {
-    "kl", "left",
-    "kr", "right",
-    "ku", "up",
-    "kd", "down",
-    "kh", "home",
-    "k1", "f1",
-    "k2", "f2",
-    "k3", "f3",
-    "k4", "f4",
-    "k5", "f5",
-    "k6", "f6",
-    "k7", "f7",
-    "k8", "f8",
-    "k9", "f9",
-    "k0", "f10",
-    "kH", "home-down",
-    "ka", "clear-tabs",
-    "kt", "clear-tab",
-    "kT", "set-tab",
-    "kC", "clear",
-    "kL", "deleteline",
-    "kM", "exit-insert",
-    "kE", "clear-eol",
-    "kS", "clear-eos",
-    "kI", "insert",
-    "kA", "insertline",
-    "kN", "next",
-    "kP", "prior",
-    "kF", "scroll-forward",
-    "kR", "scroll-reverse"
-  };
+  /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
+     errors during the call.  The only errors should be from Fdefine_key
+     when given a key sequence containing an invalid prefix key.  If the
+     termcap defines function keys which use a prefix that is already bound
+     to a command by the default bindings, we should silently ignore that
+     function key specification, rather than giving the user an error and
+     refusing to run at all on such a terminal.  */
+
+  extern Lisp_Object Fidentity ();
+  term_get_fkeys_arg = address;
+  internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
+}
+
+static Lisp_Object
+term_get_fkeys_1 ()
+{
   int i;
 
+  char **address = term_get_fkeys_arg;
+
+  /* This can happen if CANNOT_DUMP or with strange options.  */
+  if (!initialized)
+    Vfunction_key_map = Fmake_sparse_keymap (Qnil);
+
   for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
     {
       char *sequence = tgetstr (keys[i].cap, address);
       if (sequence)
-       Fdefine_key (Vfunction_key_map,
-                    build_string (sequence),
-                    Fmake_vector (make_number (1), intern (keys[i].name)));
+       Fdefine_key (Vfunction_key_map, build_string (sequence),
+                    Fmake_vector (make_number (1),
+                                  intern (keys[i].name)));
+    }
+
+  /* The uses of the "k0" capability are inconsistent; sometimes it
+     describes F10, whereas othertimes it describes F0 and "k;" describes F10.
+     We will attempt to politely accommodate both systems by testing for
+     "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
+     */
+  {
+    char *k_semi  = tgetstr ("k;", address);
+    char *k0      = tgetstr ("k0", address);
+    char *k0_name = "f10";
+
+    if (k_semi)
+      {
+       Fdefine_key (Vfunction_key_map, build_string (k_semi),
+                    Fmake_vector (make_number (1), intern ("f10")));
+       k0_name = "f0";
+      }
+
+    if (k0)
+      Fdefine_key (Vfunction_key_map, build_string (k0),
+                  Fmake_vector (make_number (1), intern (k0_name)));
+  }
+
+  /* Set up cookies for numbered function keys above f10. */
+  {
+    char fcap[3], fkey[4];
+
+    fcap[0] = 'F'; fcap[2] = '\0';
+    for (i = 11; i < 64; i++)
+      {
+       if (i <= 19)
+         fcap[1] = '1' + i - 11;
+       else if (i <= 45)
+         fcap[1] = 'A' + i - 20;
+       else
+         fcap[1] = 'a' + i - 46;
+
+       {
+         char *sequence = tgetstr (fcap, address);
+         if (sequence)
+           {
+             sprintf (fkey, "f%d", i);
+             Fdefine_key (Vfunction_key_map, build_string (sequence),
+                          Fmake_vector (make_number (1),
+                                        intern (fkey)));
+           }
+       }
+      }
+   }
+
+  /*
+   * Various mappings to try and get a better fit.
+   */
+  {
+#define CONDITIONAL_REASSIGN(cap1, cap2, sym)                          \
+      if (!tgetstr (cap1, address))                                    \
+       {                                                               \
+         char *sequence = tgetstr (cap2, address);                     \
+         if (sequence)                                                 \
+           Fdefine_key (Vfunction_key_map, build_string (sequence),    \
+                        Fmake_vector (make_number (1), \
+                                      intern (sym)));  \
+       }
+         
+      /* if there's no key_next keycap, map key_npage to `next' keysym */
+      CONDITIONAL_REASSIGN ("%5", "kN", "next");
+      /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
+      CONDITIONAL_REASSIGN ("%8", "kP", "prior");
+      /* if there's no key_dc keycap, map key_ic to `insert' keysym */
+      CONDITIONAL_REASSIGN ("kD", "kI", "insert");
+      /* if there's no key_end keycap, map key_ll to 'end' keysym */
+      CONDITIONAL_REASSIGN ("@7", "kH", "end");
+
+      /* IBM has their own non-standard dialect of terminfo.
+        If the standard name isn't found, try the IBM name.  */
+      CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
+      CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
+      CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
+      CONDITIONAL_REASSIGN ("%7", "ki", "menu");
+      CONDITIONAL_REASSIGN ("@7", "kw", "end");
+      CONDITIONAL_REASSIGN ("F1", "k<", "f11");
+      CONDITIONAL_REASSIGN ("F2", "k>", "f12");
+      CONDITIONAL_REASSIGN ("%1", "kq", "help");
+      CONDITIONAL_REASSIGN ("*6", "kU", "select");
+#undef CONDITIONAL_REASSIGN
+  }
+
+  return Qnil;
+}
+
+\f
+/***********************************************************************
+                      Character Display Information
+ ***********************************************************************/
+
+static void append_glyph P_ ((struct it *));
+
+
+/* Append glyphs to IT's glyph_row.  Called from produce_glyphs for
+   terminal frames if IT->glyph_row != NULL.  IT->c is the character
+   for which to produce glyphs; IT->face_id contains the character's
+   face.  Padding glyphs are appended if IT->c has a IT->pixel_width >
+   1.  */
+   
+static void
+append_glyph (it)
+     struct it *it;
+{
+  struct glyph *glyph, *end;
+  int i;
+
+  xassert (it->glyph_row);
+  glyph = (it->glyph_row->glyphs[it->area]
+          + it->glyph_row->used[it->area]);
+  end = it->glyph_row->glyphs[1 + it->area];
+
+  for (i = 0; 
+       i < it->pixel_width && glyph < end; 
+       ++i)
+    {
+      glyph->type = CHAR_GLYPH;
+      glyph->pixel_width = 1;
+      glyph->u.ch.code = it->c;
+      glyph->u.ch.face_id = it->face_id;
+      glyph->u.ch.padding_p = i > 0;
+      glyph->charpos = CHARPOS (it->position);
+      glyph->object = it->object;
+      
+      ++it->glyph_row->used[it->area];
+      ++glyph;
+    }
+}
+
+
+/* Produce glyphs for the display element described by IT.  The
+   function fills output fields of IT with pixel information like the
+   pixel width and height of a character, and maybe produces glyphs at
+   the same time if IT->glyph_row is non-null.  See the explanation of
+   struct display_iterator in dispextern.h for an overview.  */
+
+void 
+produce_glyphs (it)
+     struct it *it;
+{
+  /* If a hook is installed, let it do the work.  */
+  xassert (it->what == IT_CHARACTER
+          || it->what == IT_IMAGE
+          || it->what == IT_STRETCH);
+  
+  /* Nothing but characters are supported on terminal frames.  */
+  xassert (it->what == IT_CHARACTER);
+
+  if (it->c >= 040 && it->c < 0177)
+    {
+      it->pixel_width = it->nglyphs = 1;
+      if (it->glyph_row)
+       append_glyph (it);
+    }
+  else if (it->c == '\n')
+    it->pixel_width = it->nglyphs = 0;
+  else if (it->c == '\t')
+    {
+      int absolute_x = (it->current_x - it->prompt_width
+                       + it->continuation_lines_width);
+      int next_tab_x 
+       = (((1 + absolute_x + it->tab_width - 1) 
+           / it->tab_width)
+          * it->tab_width);
+      int nspaces;
+
+      /* If part of the TAB has been displayed on the previous line
+        which is continued now, continuation_lines_width will have
+        been incremented already by the part that fitted on the
+        continued line.  So, we will get the right number of spaces
+        here.  */
+      nspaces = next_tab_x - absolute_x;
+      
+      if (it->glyph_row)
+       {
+         int n = nspaces;
+         
+         it->c = ' ';
+         it->pixel_width = it->len = 1;
+         
+         while (n--)
+           append_glyph (it);
+         
+         it->c = '\t';
+       }
+
+      it->pixel_width = nspaces;
+      it->nglyphs = nspaces;
+    }
+  else
+    {
+      /* A multi-byte character.  The display width is a per character
+        value for characters of set CHARSET_COMPOSITION; otherwise
+        it is fixed for all characters of the set.  Some of the 
+        glyphs may have to be ignored because they are already 
+        displayed in a continued line.  */
+      int charset = CHAR_CHARSET (it->c);
+
+      if (charset == CHARSET_COMPOSITION)
+       it->pixel_width = cmpchar_table[COMPOSITE_CHAR_ID (it->c)]->width;
+      else
+       it->pixel_width = CHARSET_WIDTH (charset);
+      it->nglyphs = it->pixel_width;
+      
+      if (it->glyph_row)
+       append_glyph (it);
+    }
+
+  /* Advance current_x by the pixel width as a convenience for 
+     the caller.  */
+  if (it->area == TEXT_AREA)
+    it->current_x += it->pixel_width;
+  it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
+  it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
+}
+
+
+/* Get information about special display element WHAT in an
+   environment described by IT.  WHAT is one of IT_TRUNCATION or
+   IT_CONTINUATION.  Maybe produce glyphs for WHAT if IT has a
+   non-null glyph_row member.  This function ensures that fields like
+   face_id, c, len of IT are left untouched.  */
+
+void
+produce_special_glyphs (it, what)
+     struct it *it;
+     enum display_element_type what;
+{
+  struct it temp_it;
+  
+  temp_it = *it;
+  temp_it.dp = NULL;
+  temp_it.what = IT_CHARACTER;
+  temp_it.len = 1;
+  temp_it.object = 0;
+  bzero (&temp_it.current, sizeof temp_it.current);
+
+  if (what == IT_CONTINUATION)
+    {
+      /* Continuation glyph.  */
+      if (it->dp
+         && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
+         && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
+       {
+         temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
+         temp_it.len = CHAR_LEN (temp_it.c);
+       }
+      else
+       temp_it.c = '\\';
+      
+      produce_glyphs (&temp_it);
+      it->pixel_width = temp_it.pixel_width;
+      it->nglyphs = temp_it.pixel_width;
+    }
+  else if (what == IT_TRUNCATION)
+    {
+      /* Truncation glyph.  */
+      if (it->dp
+         && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
+         && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
+       {
+         temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
+         temp_it.len = CHAR_LEN (temp_it.c);
+       }
+      else
+       temp_it.c = '$';
+      
+      produce_glyphs (&temp_it);
+      it->pixel_width = temp_it.pixel_width;
+      it->nglyphs = temp_it.pixel_width;
+    }
+  else
+    abort ();
+}
+
+
+/* Return an estimation of the pixel height of mode or top lines on
+   frame F.  FACE_ID specifies what line's height to estimate.  */
+
+int
+estimate_mode_line_height (f, face_id)
+     struct frame *f;
+     enum face_id face_id;
+{
+  if (estimate_mode_line_height_hook)
+    return estimate_mode_line_height_hook (f, face_id);
+  else
+    return 1;
+}
+
+
+\f
+/***********************************************************************
+                               Faces
+ ***********************************************************************/
+
+
+/* Turn appearances of face FACE_ID on tty frame F on.  */
+
+static void
+turn_on_face (f, face_id)
+     struct frame *f;
+     int face_id;
+{
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+  xassert (face != NULL);
+
+  if (face->tty_bold_p)
+    OUTPUT1_IF (TS_enter_bold_mode);
+  else if (face->tty_dim_p)
+    OUTPUT1_IF (TS_enter_dim_mode);
+
+  /* Alternate charset and blinking not yet used.  */
+  if (face->tty_alt_charset_p)
+    OUTPUT1_IF (TS_enter_alt_charset_mode);
+
+  if (face->tty_blinking_p)
+    OUTPUT1_IF (TS_enter_blink_mode);
+
+  if (face->tty_underline_p
+      /* Don't underline if that's difficult.  */
+      && TN_magic_cookie_glitch_ul <= 0)
+    OUTPUT1_IF (TS_enter_underline_mode);
+
+  if (face->tty_reverse_p)
+    OUTPUT1_IF (TS_enter_reverse_mode);
+
+  if (TN_max_colors > 0)
+    {
+      char *p;
+      
+      if (face->foreground != FACE_TTY_DEFAULT_COLOR
+         && TS_set_foreground)
+       {
+         p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
+         OUTPUT (p);
+         xfree (p);
+       }
+
+      if (face->background != FACE_TTY_DEFAULT_COLOR
+         && TS_set_background)
+       {
+         p = tparam (TS_set_background, NULL, 0, (int) face->background);
+         OUTPUT (p);
+         xfree (p);
+       }
     }
 }
+  
+
+/* Turn off appearances of face FACE_ID on tty frame F.  */
+
+static void
+turn_off_face (f, face_id)
+     struct frame *f;
+     int face_id;
+{
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+  xassert (face != NULL);
+
+  if (TS_exit_attribute_mode)
+    {
+      /* Capability "me" will turn off appearance modes double-bright,
+        half-bright, reverse-video, standout, underline.  It may or
+        may not turn off alt-char-mode.  */
+      if (face->tty_bold_p
+         || face->tty_dim_p
+         || face->tty_reverse_p
+         || face->tty_alt_charset_p
+         || face->tty_blinking_p
+         || face->tty_underline_p)
+       OUTPUT1_IF (TS_exit_attribute_mode);
+
+      if (face->tty_alt_charset_p)
+       OUTPUT_IF (TS_exit_alt_charset_mode);
+    }
+  else
+    {
+      /* If we don't have "me" we can only have those appearances
+        that have exit sequences defined.  */
+      if (face->tty_alt_charset_p)
+       OUTPUT_IF (TS_exit_alt_charset_mode);
+
+      if (face->tty_underline_p
+         /* We don't underline if that's difficult.  */
+         && TN_magic_cookie_glitch_ul <= 0)
+       OUTPUT_IF (TS_exit_underline_mode);
+    }
+
+  /* Switch back to default colors.  */
+  if (TN_max_colors > 0
+      && (face->foreground != FACE_TTY_DEFAULT_COLOR
+         || face->background != FACE_TTY_DEFAULT_COLOR))
+    OUTPUT1_IF (TS_orig_pair);
+}
+  
+    
+/* Return non-zero if the terminal is capable to display colors.  */
+
+DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
+       0, 0, 0,
+  "Return non-nil if TTY can display colors.")
+     ()
+{
+  return TN_max_colors > 0 ? Qt : Qnil;
+}
+
+
 
 \f
+/***********************************************************************
+                           Initialization
+ ***********************************************************************/
+
+void
 term_init (terminal_type)
      char *terminal_type;
 {
@@ -1125,22 +2063,76 @@ term_init (terminal_type)
   char buffer[2044];
   register char *p;
   int status;
+  struct frame *sf = XFRAME (selected_frame);
+
+#ifdef WINDOWSNT
+  initialize_w32_display ();
+
+  Wcm_clear ();
+
+  area = (char *) xmalloc (2044);
+
+  if (area == 0)
+    abort ();
+
+  FrameRows = FRAME_HEIGHT (sf);
+  FrameCols = FRAME_WIDTH (sf);
+  specified_window = FRAME_HEIGHT (sf);
+
+  delete_in_insert_mode = 1;
+
+  UseTabs = 0;
+  scroll_region_ok = 0;
+
+  /* Seems to insert lines when it's not supposed to, messing
+     up the display.  In doing a trace, it didn't seem to be
+     called much, so I don't think we're losing anything by
+     turning it off.  */
+
+  line_ins_del_ok = 0;
+  char_ins_del_ok = 1;
 
-  extern char *tgetstr ();
+  baud_rate = 19200;
+
+  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
+
+  return;
+#else  /* not WINDOWSNT */
 
   Wcm_clear ();
-  dont_calculate_costs = 0;
 
   status = tgetent (buffer, terminal_type);
   if (status < 0)
-    fatal ("Cannot open termcap database file.\n");
+    {
+#ifdef TERMINFO
+      fatal ("Cannot open terminfo database file");
+#else
+      fatal ("Cannot open termcap database file");
+#endif
+    }
   if (status == 0)
-    fatal ("Terminal type %s is not defined.\n", terminal_type);
-
+    {
 #ifdef TERMINFO
-  area = (char *) malloc (2044);
+      fatal ("Terminal type %s is not defined.\n\
+If that is not the actual type of terminal you have,\n\
+use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
+`setenv TERM ...') to specify the correct type.  It may be necessary\n\
+to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
+            terminal_type);
 #else
-  area = (char *) malloc (strlen (buffer));
+      fatal ("Terminal type %s is not defined.\n\
+If that is not the actual type of terminal you have,\n\
+use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
+`setenv TERM ...') to specify the correct type.  It may be necessary\n\
+to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
+            terminal_type);
+#endif
+    }
+#ifdef TERMINFO
+  area = (char *) xmalloc (2044);
+#else
+  area = (char *) xmalloc (strlen (buffer));
 #endif /* not TERMINFO */
   if (area == 0)
     abort ();
@@ -1151,7 +2143,7 @@ term_init (terminal_type)
   BackTab = tgetstr ("bt", address);
   TS_clr_to_bottom = tgetstr ("cd", address);
   TS_clr_line = tgetstr ("ce", address);
-  TS_clr_screen = tgetstr ("cl", address);
+  TS_clr_frame = tgetstr ("cl", address);
   ColPosition = tgetstr ("ch", address);
   AbsPosition = tgetstr ("cm", address);
   CR = tgetstr ("cr", address);
@@ -1200,35 +2192,80 @@ term_init (terminal_type)
   TS_termcap_modes = tgetstr ("ti", address);
   Up = tgetstr ("up", address);
   TS_visible_bell = tgetstr ("vb", address);
-  TS_end_visual_mode = tgetstr ("ve", address);
-  TS_visual_mode = tgetstr ("vs", address);
+  TS_cursor_normal = tgetstr ("ve", address);
+  TS_cursor_visible = tgetstr ("vs", address);
+  TS_cursor_invisible = tgetstr ("vi", address);
   TS_set_window = tgetstr ("wi", address);
+  
+  TS_enter_underline_mode = tgetstr ("us", address);
+  TS_exit_underline_mode = tgetstr ("ue", address);
+  TN_magic_cookie_glitch_ul = tgetnum ("ug");
+  TS_enter_bold_mode = tgetstr ("md", address);
+  TS_enter_dim_mode = tgetstr ("mh", address);
+  TS_enter_blink_mode = tgetstr ("mb", address);
+  TS_enter_reverse_mode = tgetstr ("mr", address);
+  TS_enter_alt_charset_mode = tgetstr ("as", address);
+  TS_exit_alt_charset_mode = tgetstr ("ae", address);
+  TS_exit_attribute_mode = tgetstr ("me", address);
+  
   MultiUp = tgetstr ("UP", address);
   MultiDown = tgetstr ("DO", address);
   MultiLeft = tgetstr ("LE", address);
   MultiRight = tgetstr ("RI", address);
 
-  AutoWrap = tgetflag ("am");
-  memory_below_screen = tgetflag ("db");
+  /* SVr4/ANSI color suppert.  If "op" isn't available, don't support
+     color because we can't switch back to the default foreground and
+     background.  */
+  TS_orig_pair = tgetstr ("op", address);
+  if (TS_orig_pair)
+    {
+      TS_set_foreground = tgetstr ("AF", address);
+      TS_set_background = tgetstr ("AB", address);
+      if (!TS_set_foreground)
+       {
+         /* SVr4.  */
+         TS_set_foreground = tgetstr ("Sf", address);
+         TS_set_background = tgetstr ("Sb", address);
+       }
+      TN_max_colors = tgetnum ("Co");
+      TN_max_pairs = tgetnum ("pa");
+    }
+
+  MagicWrap = tgetflag ("xn");
+  /* Since we make MagicWrap terminals look like AutoWrap, we need to have
+     the former flag imply the latter.  */
+  AutoWrap = MagicWrap || tgetflag ("am");
+  memory_below_frame = tgetflag ("db");
   TF_hazeltine = tgetflag ("hz");
   must_write_spaces = tgetflag ("in");
   meta_key = tgetflag ("km") || tgetflag ("MT");
   TF_insmode_motion = tgetflag ("mi");
   TF_standout_motion = tgetflag ("ms");
   TF_underscore = tgetflag ("ul");
-  MagicWrap = tgetflag ("xn");
   TF_xs = tgetflag ("xs");
   TF_teleray = tgetflag ("xt");
 
   term_get_fkeys (address);
 
-  /* Get screen size from system, or else from termcap.  */
-  get_screen_size (&SCREEN_WIDTH (selected_screen),
-                  &SCREEN_HEIGHT (selected_screen));
-  if (SCREEN_WIDTH (selected_screen) <= 0)
-    SCREEN_WIDTH (selected_screen) = tgetnum ("co");
-  if (SCREEN_HEIGHT (selected_screen) <= 0)
-    SCREEN_HEIGHT (selected_screen) = tgetnum ("li");
+  /* Get frame size from system, or else from termcap.  */
+  {
+    int height, width;
+    get_frame_size (&width, &height);
+    FRAME_WIDTH (sf) = width;
+    FRAME_HEIGHT (sf) = height;
+  }
+
+  if (FRAME_WIDTH (sf) <= 0)
+    SET_FRAME_WIDTH (sf, tgetnum ("co"));
+  else
+    /* Keep width and external_width consistent */
+    SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf));
+  if (FRAME_HEIGHT (sf) <= 0)
+    FRAME_HEIGHT (sf) = tgetnum ("li");
+  
+  if (FRAME_HEIGHT (sf) < 3 || FRAME_WIDTH (sf) < 3)
+    fatal ("Screen size %dx%d is too small",
+          FRAME_HEIGHT (sf), FRAME_WIDTH (sf));
 
   min_padding_speed = tgetnum ("pb");
   TN_standout_width = tgetnum ("sg");
@@ -1267,6 +2304,17 @@ term_init (terminal_type)
       TS_standout_mode = tgetstr ("us", address);
     }
 
+  /* If no `se' string, try using a `me' string instead.
+     If that fails, we can't use standout mode at all.  */
+  if (TS_end_standout_mode == 0)
+    {
+      char *s = tgetstr ("me", address);
+      if (s != 0)
+       TS_end_standout_mode = s;
+      else
+       TS_standout_mode = 0;
+    }
+
   if (TF_teleray)
     {
       Wcm.cm_tab = 0;
@@ -1285,7 +2333,7 @@ term_init (terminal_type)
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      memory_below_screen = 1;
+      memory_below_frame = 1;
       Wcm.cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
@@ -1296,7 +2344,7 @@ term_init (terminal_type)
         for windows starting at the upper left corner;
         but that is all Emacs uses.
 
-        This string works only if the screen is using
+        This string works only if the frame is using
         the top of the video memory, because addressing is memory-relative.
         So first check the :ti string to see if that is true.
 
@@ -1330,9 +2378,9 @@ term_init (terminal_type)
        }
     }
 
-  ScreenRows = SCREEN_HEIGHT (selected_screen);
-  ScreenCols = SCREEN_WIDTH (selected_screen);
-  specified_window = SCREEN_HEIGHT (selected_screen);
+  FrameRows = FRAME_HEIGHT (sf);
+  FrameCols = FRAME_WIDTH (sf);
+  specified_window = FRAME_HEIGHT (sf);
 
   if (Wcm_init () == -1)       /* can't do cursor motion */
 #ifdef VMS
@@ -1340,19 +2388,30 @@ term_init (terminal_type)
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have, use either the\n\
 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
-or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.\n",
+or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
            terminal_type);
-#else
+#else /* not VMS */
+# ifdef TERMINFO
     fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have,\n\
-use the C-shell command `setenv TERM ...' to specify the correct type.\n\
-It may be necessary to do `unsetenv TERMCAP' as well.\n",
+use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
+`setenv TERM ...') to specify the correct type.  It may be necessary\n\
+to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
           terminal_type);
-#endif
-  if (SCREEN_HEIGHT (selected_screen) <= 0
-      || SCREEN_WIDTH (selected_screen) <= 0)
-    fatal ("The screen size has not been specified.");
+# else /* TERMCAP */
+    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+It lacks the ability to position the cursor.\n\
+If that is not the actual type of terminal you have,\n\
+use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
+`setenv TERM ...') to specify the correct type.  It may be necessary\n\
+to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
+          terminal_type);
+# endif /* TERMINFO */
+#endif /*VMS */
+  if (FRAME_HEIGHT (sf) <= 0
+      || FRAME_WIDTH (sf) <= 0)
+    fatal ("The frame size has not been specified");
 
   delete_in_insert_mode
     = TS_delete_mode && TS_insert_mode
@@ -1364,7 +2423,7 @@ It may be necessary to do `unsetenv TERMCAP' as well.\n",
 
   /* Remove width of standout marker from usable width of line */
   if (TN_standout_width > 0)
-    SCREEN_WIDTH (selected_screen) -= TN_standout_width;
+    SET_FRAME_WIDTH (sf, FRAME_WIDTH (sf) - TN_standout_width);
 
   UseTabs = tabs_safe_p () && TabWidth == 8;
 
@@ -1386,14 +2445,41 @@ It may be necessary to do `unsetenv TERMCAP' as well.\n",
   if (read_socket_hook)                /* Baudrate is somewhat */
                                /* meaningless in this case */
     baud_rate = 9600;
+
+  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
+#endif /* WINDOWSNT */
 }
 
 /* VARARGS 1 */
+void
 fatal (str, arg1, arg2)
      char *str, *arg1, *arg2;
 {
   fprintf (stderr, "emacs: ");
   fprintf (stderr, str, arg1, arg2);
+  fprintf (stderr, "\n");
   fflush (stderr);
   exit (1);
 }
+
+void
+syms_of_term ()
+{
+  DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
+    "Non-nil means the system uses terminfo rather than termcap.\n\
+This variable can be used by terminal emulator packages.");
+#ifdef TERMINFO
+  system_uses_terminfo = 1;
+#else
+  system_uses_terminfo = 0;
+#endif
+
+  DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
+    "Non-nil means call this function to ring the bell.\n\
+The function should accept no arguments.");
+  Vring_bell_function = Qnil;
+
+  defsubr (&Stty_display_color_p);
+}
+