changeset 82990:2ecd1f669db9

Fixed X support, preliminary support for X-tty combo sessions. lib-src/emacsclient.c (copy_from_to, pty_conversation): Re-added SIGIO hack. (Sigh.) lisp/frame.el (make-frame-on-tty): Use make-terminal-frame, not make-frame. src/dispnew.c (line_hash_code, line_draw_cost): Updated to use the new display_method parameters. (Fredraw_frame): fflush the tty only if f is a termcap frame. (direct_output_for_insert): Updated to use the new display_method parameters. fflush the tty only if f is a termcap frame. (direct_output_forward_char, update_frame_1, scrolling): Ditto. (update_frame_line, Fding, bitch_at_user): Ditto. (Fsend_string_to_terminal): Fail if current frame is not on a tty. (init_display): Frame size change is safe here. src/frame.c (Vterminal_frame): Restored previously deleted variable. (syms_of_frame): Initialize it. (make_terminal_frame): Copy the frame's display_method from tty_display_info. (Fmake_terminal_frame): Enable simultaneous X and tty frames (buggy). (Fredirect_frame_focus): Don't call frame_rehighlight_hook if frame is on a termcap device. src/frame.h (struct frame): Renamed display to display_method. (Vterminal_frame): Re-added declaration. src/keyboard.c (flow_control): Moved to struct tty_display_info. (read_avail_input): Check ttys even if there is a read_socket_hook. (Fset_input_mode): Call reset_sys_modes/init_sys_modes and set flow_control or meta_key only when the frame is a termcap frame. (Fcurrent_input_mode): Handle flow_control and meta_key right on non-termcap frames. src/scroll.c (calculate_scrolling, calculate_direct_scrolling): Update to use the new display_method parameters. (scrolling_1, scroll_cost): Ditto. src/sysdep.c (init_sys_modes, reset_sys_modes): Always set the terminal parameters if tty_out->input is not stdin. Updated to the new location of flow_control. (hft_init): Moved HFT init code to term_init, as it needs the frame. src/term.c (tty_display_method_template): New variable. (update_begin): Added rif hack. (set_terminal_window, ins_del_lines, term_init): Updated to use the new display_method parameters. (insert_glyphs, ins_del_lines): Only call insert_glyphs_hook if the current frame is not on a tty. (calculate_costs): Don't calculate costs if not on a tty. (term_dummy_init): Fixed tty->output initialization. Preallocate Wcm and display_method. (term_init): Allocate & initialize display_method. Blindly fixed WINDOWSNT-specific parts. Added HFT-specific initialization exception from hft_init. (delete_tty): Only delete termcap frames. Free() the display_method. src/termchar.h (struct tty_display_info): Moved high-level terminal characteristics to struct display_method. Added flow_control and display_method members. src/termhooks.h (struct display_method): New struct (renamed from struct device). Added accessor macros. src/window.c (init_window_once): Initialize Vterminal_frame. src/xdisp.c (init_iterator, expose_frame): Added rif hack. (try_window_id): Updated to use the new display_method parameters. src/xfaces.c (realize_basic_faces): Don't call x_update_menu_appearance if the frame is a tty frame. src/xfns.c (Fx_create_frame): Added rif hack. Initialize display_method. (x_create_tip_frame): Initialize display_method. src/xterm.c (x_display_method): New variable. (x_flush, x_frame_of_widget, XTmouse_position): Ignore non-X frames. (x_window_to_scroll_bar, x_window_to_menu_bar): Ditto. (xim_destroy_callback, xim_instantiate_callback): Ditto. (frame_highlight, frame_unhighlight): Added rif hack. (x_initialize): Don't initialize rif. Do initialize x_display_method. src/xterm.h (x_display_method): New declaration. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-30
author Karoly Lorentey <lorentey@elte.hu>
date Fri, 02 Jan 2004 01:15:26 +0000
parents f3845715a5f6
children 2b26656ff804
files README.multi-tty lib-src/emacsclient.c lisp/frame.el src/Makefile.in src/dispnew.c src/frame.c src/frame.h src/keyboard.c src/scroll.c src/sysdep.c src/term.c src/termchar.h src/termhooks.h src/window.c src/xdisp.c src/xfaces.c src/xfns.c src/xterm.c src/xterm.h
diffstat 19 files changed, 443 insertions(+), 294 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Thu Jan 01 17:55:53 2004 +0000
+++ b/README.multi-tty	Fri Jan 02 01:15:26 2004 +0000
@@ -16,7 +16,7 @@
 Retrieving the latest version of the branch:
 
 	tla register-archive lorentey@elte.hu--2004 http://lorentey.web.elte.hu/arch/2004/
-	tla get lorentey@elte.hu--2004/emacs--multi-tty--0 <directory>
+	tla get lorentey@elte.hu--2004/emacs--multi-tty <directory>
 
 (I use tla 1.1.)
 
@@ -33,11 +33,11 @@
 
    	mkdir +build
 	cd +build
-	../configure --with-x-toolkit=no --without-x
+	../configure
 	make bootstrap
 
-then start up the emacs server (src/emacs, M-x server-start), and then
-(from a shell prompt on another terminal) start emacsclient with
+then start up the emacs server (src/emacs -nw, M-x server-start), and
+then (from a shell prompt on another terminal) start emacsclient with
 
 	lib-src/emacsclient -f /optional/file/names...
 
@@ -50,7 +50,10 @@
 If you exit emacs, all terminals should be restored to their previous
 states.
 
-X, Mac, Windows and DOS support is broken, probably doesn't even
+X support is (I hope) working, but at the moment there are problems
+with simultaneous X and tty devices, so don't do that.
+
+Mac, Windows and DOS support is broken, probably doesn't even
 compile -- this will be solved later.
 
 Only tested on my GNU/Linux box.
@@ -91,9 +94,9 @@
 
 (ex-TODO items with explanations.)
 
--- Introduce a new abstraction for terminal devices.  
+-- Introduce a new struct for terminal devices.  
 
-   (Done, see struct tty_output.  The abstraction is not yet
+   (Done, see struct tty_output.  The list of members is not yet
    complete.)
 
 -- Change the bootstrap procedure to initialize tty_list.
@@ -112,6 +115,8 @@
 
    (Update: They do, now.)
 
+   (Update2: After enabling X, they don't.)
+
 -- other-frame should cycle through the frames on the `current'
    terminal only.  
 
@@ -167,6 +172,8 @@
    read_input_waiting was not necessary.  Secondary ttys do seem to
    send signals on input.)
 
+   (Update^3: Not any more.)
+
 -- Make make-terminal-frame look up the `tty' and `tty-type' frame
    parameters from the currently selected terminal before the global
    default.
@@ -191,7 +198,7 @@
 
    (Done, but at the moment only called when an error happens during
    initialization.  There is a memory corruption error around this
-   somewhere.)
+   somewhere.)  (Update: now it is fully enabled.)
 
 -- Implement automatic deletion of terminals when the last frame on
    that terminal is closed.
@@ -214,9 +221,10 @@
    server-frames may be removed from server.el.)
 
    (Done, nothing to do.  It seems that Emacs does not receive SIGHUP
-   from secondary ttys.)
+   from secondary ttys, which is actually a good thing.)  (Update: I
+   think it would be a bad idea to remove server-frames anyway.)
 
--- Change emacsclient/server.el to support the -h argument better,
+-- Change emacsclient/server.el to support the -t argument better,
    i.e. automatically close the socket when the frame is closed.
 
    (Seems to be working OK.)
@@ -248,7 +256,7 @@
    earlier, but it seems to be fixed (there were several changes
    around request_sigio, maybe one of them did it).
    read_input_waiting() is only used in sys_select(), don't change
-   it.)
+   it.)  (Update: After adding X support, it's broken again.)
 
 -- Find out why does Emacs abort when it wants to close its
    controlling tty.  Hint: chan_process[] array.  Hey, maybe
@@ -262,6 +270,7 @@
    fcntl() kernel behaviour could be emulated by emacsclient.
 
    (Done.  Simply disabled the SIGIO emulation hack in emacsclient.)
+   (Update: it was added back.)
 
 -- server.el: There are issues with saving files in buffers of closed
    clients.  Try editing a file with emacsclient -f, and (without
@@ -273,7 +282,7 @@
    pending buffers, and modified buffers don't seem to be deleted.)
 
 -- emacsclient.el, server.el: Handle eval or file open errors when
-   doing -f.
+   doing -t.
 
    (Done.)
 
@@ -286,32 +295,52 @@
 
    (Done, see delete-tty.)
 
+-- Get rid of the accessor macros in termchar.h, or define macros for
+   all members.
+
+   (Done.)
+
+-- Move device-specific parameters (like costs) commonly used by
+   device backends to a common, device-dependent structure.
+
+   (Done.  See struct display_method in termhooks.h.)
+
+-- Fix X support.
+
+   (Done.  Well, it seems to be working.)
+
+-- Allow simultaneous X and tty frames.  (Handling input could be
+   tricky.  Or maybe not.)
+
+   (Done.  Allowed, that is.  It is currently extremely unstable, to
+   the point of being unusable.  The rif variable causes constant
+   core dumps.  Handling input is indeed tricky.)
 
 THINGS TO DO
 ------------
 
+** Fix rif issue with X-tty combo sessions.  IMHO the best thing to do
+   is to get rid of that global variable (and use the value value in
+   display_method, which is guaranteed to be correct).
+
+** Fix faces on tty frames during X-tty combo sessions.
+
 ** Find out the best way to support suspending Emacs with multiple
-   ttys.  My guess: disable it on the controlling tty, but other ttys
-   should pass it on to emacsclient somehow.  (It is (I hope) trivial
-   to extend emacsclient to handle suspend/resume.  A `kill -STOP'
-   almost works right now.)
+   ttys.  My guess: disable it on the controlling tty, but from other
+   ttys pass it on to emacsclient somehow.  (It is (I hope) trivial to
+   extend emacsclient to handle suspend/resume.  A `kill -STOP' almost
+   works right now.)
 
 ** Move baud_rate to tty_output.
 
-** Move device-specific parameters (like costs) commonly used by
-   device backends to a common, device-dependent structure.
-
 ** Do tty output through term_hooks, like graphical display backends.
 
-** Fix X support.
-
-** Allow simultaneous X and tty frames.  (Handling input could be
-   tricky.  Or maybe not.)
-
 ** Implement support for starting an interactive Emacs session without
    an initial frame.  (The user would connect to it and open frames
    later, with emacsclient.)  Not necessarily a good idea.
 
+** Fix input from raw ttys (again).
+
 ** Fix Mac support (I can't do this myself).
 
 ** Fix W32 support (I can't do this myself).
@@ -320,14 +349,22 @@
 
 ** Do a grep on XXX and ?? for more issues.
 
-** Get rid of the accessor macros in termchar.h, or define macros for
-   all members.
+** Understand Emacs's low-level input system (it seems complicated)
+   :-) and maybe rewrite multi-tty input in terms of MULTI_KBOARD.
+   (Update: This backtrace from a tty-X combo session hints that this
+   may be necessary.)
 
-** Understand Emacs's low-level input system (it seems complicated) :-)
-   and maybe rewrite multi-tty input in terms of MULTIKBOARD.
+	#0  abort () at /home/lorentey/work/emacs/emacs--multi-tty/src/emacs.c:417
+	#1  0x081104fb in read_char (commandflag=0, nmaps=0, maps=0x0, prev_event=675499188, used_mouse_menu=0x0) at /home/lorentey/work/emacs/emacs--multi-tty/src/keyboard.c:2581
+	#2  0x0819f23e in read_filtered_event (no_switch_frame=1, ascii_required=0, error_nonascii=0, input_method=0) at /home/lorentey/work/emacs/emacs--multi-tty/src/lread.c:468
+	#3  0x0819387c in Fy_or_n_p (prompt=1759896324) at /home/lorentey/work/emacs/emacs--multi-tty/src/fns.c:3115
+	...
 
 ** What does interrupt_input do?  I tried to disable it for raw
    secondary tty support, but it does not seem to do anything useful.
+   (Update: Look again. X unconditionally enables this, maybe that's
+   why raw terminal support is broken again.  I really do need to
+   understand input.)
 
 ** Make sure C-g goes to the right frame.  This is hard, as SIGINT
    doesn't have a tty parameter. :-(
@@ -335,7 +372,6 @@
 ** I have seen a case when Emacs with multiple ttys fell into a loop
    eating 100% of CPU time.  Strace showed this loop:
 
-
 	getpid()                                = 30284
 	kill(30284, SIGIO)                      = 0
 	--- SIGIO (I/O possible) @ 0 (0) ---
--- a/lib-src/emacsclient.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/lib-src/emacsclient.c	Fri Jan 02 01:15:26 2004 +0000
@@ -720,7 +720,7 @@
 }
 
 int
-copy_from_to (int in, int out)
+copy_from_to (int in, int out, int sigio)
 {
   static char buf[BUFSIZ];
   int nread = read (in, &buf, BUFSIZ);
@@ -740,6 +740,9 @@
       
       if (r < 0)
         return 0;
+
+      if (sigio && emacs_pid)
+        kill (emacs_pid, SIGIO);
     }
   return 1;
 }
@@ -774,7 +777,7 @@
         if (FD_ISSET (master, &rset))
           {
             /* Copy Emacs output to stdout. */
-            if (! copy_from_to (master, 0))
+            if (! copy_from_to (master, 0, 0))
               {
                 FD_CLR (master, &set);
               }
@@ -782,7 +785,7 @@
         if (FD_ISSET (1, &rset))
           {
             /* Forward user input to Emacs. */
-            if (! copy_from_to (1, master))
+            if (! copy_from_to (1, master, 1))
               {
                 FD_CLR (master, &set);
               }
--- a/lisp/frame.el	Thu Jan 01 17:55:53 2004 +0000
+++ b/lisp/frame.el	Fri Jan 02 01:15:26 2004 +0000
@@ -587,7 +587,7 @@
     (error "Invalid terminal device"))
   (unless type
     (error "Invalid terminal type"))
-  (make-frame `((tty . ,device) (tty-type . ,type) . ,parameters)))
+  (make-terminal-frame (append (list (cons 'tty device) (cons 'tty-type type)) parameters)))
 
 (defun make-frame-command ()
   "Make a new frame, and select it if the terminal displays only one frame."
--- a/src/Makefile.in	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/Makefile.in	Fri Jan 02 01:15:26 2004 +0000
@@ -1111,7 +1111,7 @@
 regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h
 region-cache.o: region-cache.c buffer.h region-cache.h
 scroll.o: scroll.c systty.h termchar.h dispextern.h frame.h msdos.h keyboard.h \
-   $(config_h)
+   termhooks.h $(config_h)
 search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
    blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h)
 strftime.o: strftime.c $(config_h)
--- a/src/dispnew.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/dispnew.c	Fri Jan 02 01:15:26 2004 +0000
@@ -297,8 +297,10 @@
 
 static struct frame *frame_matrix_frame;
 
-/* Current interface for window-based redisplay.  Set from init_xterm.
-   A null value means we are not using window-based redisplay.  */
+/* Current interface for window-based redisplay.  Set from
+   update_begin.  A null value means we are not using window-based
+   redisplay.  */
+/* XXX this variable causes frequent coredumps */
 
 struct redisplay_interface *rif;
 
@@ -1390,7 +1392,7 @@
 	{
 	  int c = glyph->u.ch;
 	  int face_id = glyph->face_id;
-	  if (TTY_MUST_WRITE_SPACES (CURTTY ()))
+	  if (FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
 	    c -= SPACEGLYPH;
 	  hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
 	  hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
@@ -1422,7 +1424,7 @@
   int glyph_table_len = GLYPH_TABLE_LENGTH;
 
   /* Ignore trailing and leading spaces if we can.  */
-  if (!TTY_MUST_WRITE_SPACES (CURTTY ()))
+  if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
     {
       /* Skip from the end over trailing spaces.  */
       while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
@@ -3317,7 +3319,8 @@
   clear_frame ();
   clear_current_matrices (f);
   update_end (f);
-  fflush (TTY_OUTPUT (FRAME_TTY (f)));
+  if (FRAME_TERMCAP_P (f))
+    fflush (TTY_OUTPUT (FRAME_TTY (f)));
   windows_or_buffers_changed++;
   /* Mark all windows as inaccurate, so that every window will have
      its redisplay done.  */
@@ -3457,7 +3460,7 @@
 
   /* If we can't insert glyphs, we can use this method only
      at the end of a line.  */
-  if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
+  if (!FRAME_CHAR_INS_DEL_OK (f))
     if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
       return 0;
 
@@ -3654,7 +3657,8 @@
     rif->update_window_end_hook (w, 1, 0);
   update_end (f);
   updated_row = NULL;
-  fflush (TTY_OUTPUT (CURTTY ()));
+  if (FRAME_TERMCAP_P (f))
+    fflush (TTY_OUTPUT (FRAME_TTY (f)));
 
   TRACE ((stderr, "direct output for insert\n"));
   mark_window_display_accurate (it.window, 1);
@@ -3745,7 +3749,8 @@
       cursor_to (y, x);
     }
 
-  fflush (TTY_OUTPUT (CURTTY ()));
+  if (FRAME_TERMCAP_P (f))
+    fflush (TTY_OUTPUT (FRAME_TTY (f)));
   redisplay_performed_directly_p = 1;
   return 1;
 }
@@ -5070,7 +5075,7 @@
     }
 
   /* If we cannot insert/delete lines, it's no use trying it.  */
-  if (!TTY_LINE_INS_DEL_OK (FRAME_TTY (f)))
+  if (!FRAME_LINE_INS_DEL_OK (f))
     inhibit_id_p = 1;
 
   /* See if any of the desired lines are enabled; don't compute for
@@ -5288,7 +5293,7 @@
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
-  if ((!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
+  if ((!FRAME_SCROLL_REGION_OK (frame)
        && changed_lines < baud_rate / 2400)
       || unchanged_at_bottom == FRAME_LINES (frame))
     return 1;
@@ -5296,14 +5301,14 @@
   window_size = (FRAME_LINES (frame) - unchanged_at_top
 		 - unchanged_at_bottom);
 
-  if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
+  if (FRAME_SCROLL_REGION_OK (frame))
     free_at_end_vpos -= unchanged_at_bottom;
-  else if (TTY_MEMORY_BELOW_FRAME (FRAME_TTY (frame)))
+  else if (FRAME_MEMORY_BELOW_FRAME (frame))
     free_at_end_vpos = -1;
 
   /* If large window, fast terminal and few lines in common between
      current frame and desired frame, don't bother with i/d calc.  */
-  if (!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
+  if (!FRAME_SCROLL_REGION_OK (frame)
       && window_size >= 18 && baud_rate > 2400
       && (window_size >=
 	  10 * scrolling_max_lines_saved (unchanged_at_top,
@@ -5384,7 +5389,7 @@
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
   int must_write_whole_line_p;
-  int write_spaces_p = TTY_MUST_WRITE_SPACES (FRAME_TTY (f));
+  int write_spaces_p = FRAME_MUST_WRITE_SPACES (f);
   int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
 			  != FACE_TTY_DEFAULT_BG_COLOR);
 
@@ -5463,7 +5468,7 @@
       nlen--;
 
   /* If there's no i/d char, quickly do the best we can without it.  */
-  if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
+  if (!FRAME_CHAR_INS_DEL_OK (f))
     {
       int i, j;
 
@@ -5566,7 +5571,7 @@
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
-      && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
+      && (!FRAME_CHAR_INS_DEL_OK (f)
           || endmatch <= char_ins_del_cost (f)[tem]))
     endmatch = 0;
 
@@ -5576,7 +5581,7 @@
      Is it worth it?  */
 
   if (nsp != osp
-      && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
+      && (!FRAME_CHAR_INS_DEL_OK (f)
 	  || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
     {
       begmatch = 0;
@@ -6167,6 +6172,9 @@
 {
   /* ??? Perhaps we should do something special for multibyte strings here.  */
   CHECK_STRING (string);
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
+    error ("Current frame is not on a tty device");
+  
   if (TTY_TERMSCRIPT (CURTTY ()))
     {
       fwrite (SDATA (string), 1, SBYTES (string),
@@ -6193,7 +6201,8 @@
 	putchar (07);
       else
 	ring_bell ();
-      fflush (TTY_OUTPUT (CURTTY ()));
+      if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+        fflush (TTY_OUTPUT (CURTTY ()));
     }
   else
     bitch_at_user ();
@@ -6210,7 +6219,8 @@
     error ("Keyboard macro terminated by a command ringing the bell");
   else
     ring_bell ();
-  fflush (TTY_OUTPUT (CURTTY ()));
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    fflush (TTY_OUTPUT (CURTTY ()));
 }
 
 
@@ -6628,7 +6638,7 @@
     struct tty_display_info *tty;
     
     tty = term_init (selected_frame, 0, terminal_type);
-    change_frame_size (XFRAME (selected_frame), FrameRows (tty), FrameCols (tty), 0, 0, 0);
+    change_frame_size (XFRAME (selected_frame), FrameRows (tty), FrameCols (tty), 0, 0, 1);
   }
   
   {
--- a/src/frame.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/frame.c	Fri Jan 02 01:15:26 2004 +0000
@@ -114,6 +114,7 @@
 
 Lisp_Object Qface_set_after_frame_default;
 
+Lisp_Object Vterminal_frame;
 Lisp_Object Vdefault_frame_alist;
 Lisp_Object Vdefault_frame_scroll_bars;
 Lisp_Object Vmouse_position_function;
@@ -122,8 +123,8 @@
 
 static void
 set_menu_bar_lines_1 (window, n)
-  Lisp_Object window;
-  int n;
+     Lisp_Object window;
+     int n;
 {
   struct window *w = XWINDOW (window);
 
@@ -565,6 +566,7 @@
         f->output_data.tty->display_info = term_dummy_init ();
       }
     FRAME_TTY (f)->reference_count++;
+    f->display_method = FRAME_TTY (f)->display_method;
   }
   
 #ifdef CANNOT_DUMP
@@ -614,9 +616,11 @@
   if (sf->output_method != output_mac)
     error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
 #else
+#if 0                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
+#endif
 #endif /* not MSDOS */
 
   { 
@@ -1909,7 +1913,7 @@
 
   XFRAME (frame)->focus_frame = focus_frame;
 
-  if (frame_rehighlight_hook)
+  if (!FRAME_TERMCAP_P (XFRAME (frame)) && frame_rehighlight_hook)
     (*frame_rehighlight_hook) (XFRAME (frame));
 
   return Qnil;
@@ -4137,6 +4141,9 @@
     = intern ("inhibit-default-face-x-resources");
   staticpro (&Qinhibit_default_face_x_resources);
 
+  DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
+               doc: /* The initial frame-object, which represents Emacs's stdout.  */);
+
   DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
 	       doc: /* Non-nil if all of emacs is iconified and frame updates are not needed.  */);
   Vemacs_iconified = Qnil;
--- a/src/frame.h	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/frame.h	Fri Jan 02 01:15:26 2004 +0000
@@ -257,7 +257,7 @@
   int line_height;
 
   /* The display hooks to use with this frame. */
-  struct display *display;
+  struct display_method *display_method;
   
   /* The output method says how the contents of this frame
      are displayed.  It could be using termcap, or using an X window.  */
@@ -783,6 +783,8 @@
 extern Lisp_Object Vframe_list;
 extern Lisp_Object Vdefault_frame_alist;
 
+extern Lisp_Object Vterminal_frame;
+
 extern Lisp_Object Vmouse_highlight;
 
 /* The currently selected frame.  */
--- a/src/keyboard.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/keyboard.c	Fri Jan 02 01:15:26 2004 +0000
@@ -617,9 +617,6 @@
 /* Nonzero while interrupts are temporarily deferred during redisplay.  */
 int interrupts_deferred;
 
-/* Nonzero means use ^S/^Q for flow control.  */
-int flow_control;
-
 /* Allow m- file to inhibit use of FIONREAD.  */
 #ifdef BROKEN_FIONREAD
 #undef FIONREAD
@@ -6605,7 +6602,8 @@
   if (read_socket_hook)
     /* No need for FIONREAD or fcntl; just say don't wait.  */
     nread = (*read_socket_hook) (buf, KBD_BUFFER_SIZE, expected);
-  else
+
+  if (!nread && tty_list)
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
 	 the kbd_buffer can really hold.  That may prevent loss
@@ -10433,7 +10431,8 @@
 
 #ifndef DOS_NT
   /* this causes startup screen to be restored and messes with the mouse */
-  reset_sys_modes (CURTTY ());
+  if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
+    reset_sys_modes (CURTTY ());
 #endif
 
 #ifdef SIGIO
@@ -10459,19 +10458,25 @@
   interrupt_input = 1;
 #endif
 
-  flow_control = !NILP (flow);
-  if (NILP (meta))
-    CURTTY ()->meta_key = 0;
-  else if (EQ (meta, Qt))
-    CURTTY ()->meta_key = 1;
-  else
-    CURTTY ()->meta_key = 2;
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    {
+      struct tty_display_info *tty = CURTTY ();
+      tty->flow_control = !NILP (flow);
+      if (NILP (meta))
+        tty->meta_key = 0;
+      else if (EQ (meta, Qt))
+        tty->meta_key = 1;
+      else
+        tty->meta_key = 2;
+    }
+  
   if (!NILP (quit))
     /* Don't let this value be out of range.  */
     quit_char = XINT (quit) & (CURTTY ()->meta_key ? 0377 : 0177);
 
 #ifndef DOS_NT
-  init_sys_modes (CURTTY ());
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    init_sys_modes (CURTTY ());
 #endif
 
 #ifdef POLL_FOR_INPUT
@@ -10498,12 +10503,21 @@
      ()
 {
   Lisp_Object val[4];
-
+  struct frame *sf = XFRAME (selected_frame);
+  
   val[0] = interrupt_input ? Qt : Qnil;
-  val[1] = flow_control ? Qt : Qnil;
-  val[2] = FRAME_TTY (SELECTED_FRAME ())->meta_key == 2
-    ? make_number (0)
-    : FRAME_TTY (SELECTED_FRAME ())->meta_key == 1 ? Qt : Qnil;
+  if (FRAME_TERMCAP_P (sf))
+    {
+      val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
+      val[2] = FRAME_TTY (sf)->meta_key == 2
+        ? make_number (0)
+        : CURTTY ()->meta_key == 1 ? Qt : Qnil;
+    }
+  else
+    {
+      val[1] = Qnil;
+      val[2] = Qt;
+    }
   XSETFASTINT (val[3], quit_char);
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
--- a/src/scroll.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/scroll.c	Fri Jan 02 01:15:26 2004 +0000
@@ -29,6 +29,7 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
+#include "termhooks.h"
 
 /* All costs measured in characters.
    So no cost can exceed the area of a frame, measured in characters.
@@ -102,7 +103,7 @@
   register int cost, cost1;
 
   int lines_moved = window_size
-    + (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) ? 0 : lines_below);
+    + (FRAME_SCROLL_REGION_OK (frame) ? 0 : lines_below);
   /* first_insert_cost[I] is the cost of doing the first insert-line
      at the i'th line of the lines we are considering,
      where I is origin 1 (as it is below).  */
@@ -469,7 +470,7 @@
      cost of scrolling by a distance of one.  The extra cost is
      added once for consistency with the cost vectors */
   scroll_overhead
-    = TTY_SCROLL_REGION_COST (FRAME_TTY (frame)) + extra_cost;
+    = FRAME_SCROLL_REGION_COST (frame) + extra_cost;
 
   /* initialize the top left corner of the matrix */
   matrix->writecost = 0;
@@ -821,7 +822,7 @@
   matrix = ((struct matrix_elt *)
 	    alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
 
-  if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
+  if (FRAME_SCROLL_REGION_OK (frame))
     {
       calculate_direct_scrolling (frame, matrix, window_size,
 				  unchanged_at_bottom,
@@ -917,7 +918,7 @@
   if (amount == 0)
     return 0;
 
-  if (! TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
+  if (! FRAME_SCROLL_REGION_OK (frame))
     limit = height;
   else if (amount > 0)
     limit += amount;
--- a/src/sysdep.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/sysdep.c	Fri Jan 02 01:15:26 2004 +0000
@@ -1368,7 +1368,7 @@
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the initialization code below.  */
-  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+  if (tty_out->input != stdin || (!read_socket_hook && EQ (Vwindow_system, Qnil)))
 #endif
     {
       if (! tty_out->old_tty)
@@ -1400,7 +1400,7 @@
       tty.main.c_lflag &= ~IEXTEN;	/* Disable other editing characters.  */
 #endif
       tty.main.c_lflag |= ISIG;	/* Enable signals */
-      if (flow_control)
+      if (tty_out->flow_control)
 	{
 	  tty.main.c_iflag |= IXON;	/* Enable start/stop output control */
 #ifdef IXANY
@@ -1454,7 +1454,7 @@
       tty.main.c_cc[VDISCARD] = CDISABLE;
 #endif /* VDISCARD */
 
-      if (flow_control)
+      if (tty_out->flow_control)
 	{
 #ifdef VSTART
 	  tty.main.c_cc[VSTART] = '\021';
@@ -1490,7 +1490,7 @@
       tty.main.c_cc[VSUSP] = 255;
       tty.main.c_cc[VDSUSP] = 255;
 #endif /* IBMR2AIX */
-      if (flow_control)
+      if (tty_out->flow_control)
 	{
 #ifdef VSTART
 	  tty.main.c_cc[VSTART] = '\021';
@@ -1511,7 +1511,7 @@
       tty.main.tt_char |= TT$M_NOECHO;
       if (meta_key)
 	tty.main.tt_char |= TT$M_EIGHTBIT;
-      if (flow_control)
+      if (tty_out->flow_control)
 	tty.main.tt_char |= TT$M_TTSYNC;
       else
 	tty.main.tt_char &= ~TT$M_TTSYNC;
@@ -1538,7 +1538,7 @@
 	 set this */
       tty.tchars = new_tchars;
       tty.tchars.t_intrc = quit_char;
-      if (flow_control)
+      if (tty_out->flow_control)
 	{
 	  tty.tchars.t_startc = '\021';
 	  tty.tchars.t_stopc = '\023';
@@ -1573,17 +1573,17 @@
 	 we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
+      if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
 #endif
 #ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
+      if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
 #endif
 #endif
 
 #if defined (HAVE_TERMIOS) || defined (HPUX9)
 #ifdef TCOON
-      if (!flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
+      if (!tty_out->flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
 #endif
 #endif
 
@@ -1658,6 +1658,7 @@
       Lisp_Object tail, frame;
       FOR_EACH_FRAME (tail, frame)
         {
+          /* XXX This needs to be revised. */
           if (FRAME_TERMCAP_P (XFRAME (frame))
               && FRAME_TTY (XFRAME (frame)) == tty_out)
             init_frame_faces (XFRAME (frame));
@@ -1817,13 +1818,14 @@
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the clean-up code below.  */
-  if (!EQ (Vwindow_system, Qnil)
+  if (tty_out->input != stdin
+      || (!EQ (Vwindow_system, Qnil)
 #ifndef WINDOWSNT
       /* When running in tty mode on NT/Win95, we have a read_socket
 	 hook, but still need the rest of the clean-up code below.  */
       || read_socket_hook
 #endif
-      )
+          ))
     return;
 #endif
 
@@ -5156,10 +5158,6 @@
     keymap.hfkey[1].hf_char = 127;
     hftctl (0, HFSKBD, &buf);
   }
-  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
-     at times.  */
-  TTY_LINE_INS_DEL_OK (tty_out) = 0;
-  TTY_CHAR_INS_DEL_OK (tty_out) = 0;
 }
 
 /* Reset the rubout key to backspace.  */
--- a/src/term.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/term.c	Fri Jan 02 01:15:26 2004 +0000
@@ -267,6 +267,10 @@
 
 int max_frame_lines;
 
+/* A template for tty display methods, with common values
+   preinitialized. */
+static struct display_method tty_display_method_template;
+
 /* Frame currently being redisplayed; 0 if not currently redisplaying.
    (Direct output does not count).  */
 
@@ -370,6 +374,8 @@
      struct frame *f;
 {
   updating_frame = f;
+  /* XXX rif hack */
+  rif = f->display_method->rif;
   if (!FRAME_TERMCAP_P (f))
     update_begin_hook (f);
 }
@@ -401,7 +407,7 @@
     {
       struct tty_display_info *tty = FRAME_TTY (f);
       tty->specified_window = size ? size : FRAME_LINES (f);
-      if (TTY_SCROLL_REGION_OK (tty))
+      if (FRAME_SCROLL_REGION_OK (f))
 	set_scroll_region (0, tty->specified_window);
     }
   else
@@ -537,7 +543,7 @@
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
-  
+
   if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
     {
       (*cursor_to_hook) (vpos, hpos);
@@ -595,7 +601,7 @@
 
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
-  
+
   if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
     {
       (*clear_to_end_hook) ();
@@ -624,7 +630,7 @@
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
-  
+
   if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
     {
       (*clear_frame_hook) ();
@@ -655,9 +661,8 @@
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
-  
-  if (clear_end_of_line_hook
-      && ! FRAME_TERMCAP_P (f))
+
+  if (clear_end_of_line_hook && ! FRAME_TERMCAP_P (f))
     {
       (*clear_end_of_line_hook) (first_unused_hpos);
       return;
@@ -822,8 +827,7 @@
   unsigned char conversion_buffer[1024];
   int conversion_buffer_size = sizeof conversion_buffer;
 
-  if (write_glyphs_hook
-      && ! FRAME_TERMCAP_P (f))
+  if (write_glyphs_hook && ! FRAME_TERMCAP_P (f))
     {
       (*write_glyphs_hook) (string, len);
       return;
@@ -924,17 +928,18 @@
   struct glyph *glyph = NULL;
   struct frame *f;
   struct tty_display_info *tty;
-  
+
   if (len <= 0)
     return;
 
-  if (insert_glyphs_hook)
+  f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f))
     {
       (*insert_glyphs_hook) (start, len);
       return;
     }
 
-  f = (updating_frame ? updating_frame : XFRAME (selected_frame));  
   tty = FRAME_TTY (f);
 
   if (tty->TS_ins_multi_chars)
@@ -1034,7 +1039,7 @@
       turn_off_insert (tty);
       OUTPUT_IF (tty, tty->TS_delete_mode);
     }
-  
+
   if (tty->TS_del_multi_chars)
     {
       buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
@@ -1066,10 +1071,10 @@
       char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
       char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
       char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
-      
+
       register int i = n > 0 ? n : -n;
       register char *buf;
-      
+
       /* 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
@@ -1077,13 +1082,13 @@
       /* If the lines below the deletion are blank lines coming
          out of the end of the window, don't bother,
          as there will be a matching inslines later that will flush them. */
-      if (TTY_SCROLL_REGION_OK (tty)
+      if (FRAME_SCROLL_REGION_OK (f)
           && vpos + i >= tty->specified_window)
         return;
-      if (!TTY_MEMORY_BELOW_FRAME (tty)
+      if (!FRAME_MEMORY_BELOW_FRAME (f)
           && vpos + i >= FRAME_LINES (f))
         return;
-      
+
       if (multi)
         {
           raw_cursor_to (vpos, 0);
@@ -1113,9 +1118,9 @@
             OUTPUTL (tty, scroll, tty->specified_window - vpos);
           set_scroll_region (0, tty->specified_window);
         }
-      
-      if (!TTY_SCROLL_REGION_OK (tty)
-          && TTY_MEMORY_BELOW_FRAME (tty)
+
+      if (!FRAME_SCROLL_REGION_OK (f)
+          && FRAME_MEMORY_BELOW_FRAME (f)
           && n < 0)
         {
           cursor_to (FRAME_LINES (f) + n, 0);
@@ -1243,60 +1248,64 @@
 calculate_costs (frame)
      FRAME_PTR frame;
 {
-  struct tty_display_info *tty = FRAME_TTY (frame);
-  register char *f = (tty->TS_set_scroll_region
-		      ? tty->TS_set_scroll_region
-		      : tty->TS_set_scroll_region_1);
-
   FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
   if (FRAME_TERMCAP_P (frame))
-    TTY_SCROLL_REGION_COST (FRAME_TTY (frame)) = string_cost (f);
-
-  /* These variables are only used for terminal stuff.  They are allocated
-     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. */
-
-  max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
-  max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
-
-  tty->costs_set = 1;
-
-  if (char_ins_del_vector != 0)
-    char_ins_del_vector
-      = (int *) xrealloc (char_ins_del_vector,
-			  (sizeof (int)
-			   + 2 * max_frame_cols * sizeof (int)));
-  else
-    char_ins_del_vector
-      = (int *) xmalloc (sizeof (int)
-			 + 2 * max_frame_cols * sizeof (int));
-
-  bzero (char_ins_del_vector, (sizeof (int)
-			       + 2 * max_frame_cols * sizeof (int)));
-
-  if (f && (!tty->TS_ins_line && !tty->TS_del_line))
-    do_line_insertion_deletion_costs (frame,
-				      tty->TS_rev_scroll, tty->TS_ins_multi_lines,
-				      tty->TS_fwd_scroll, tty->TS_del_multi_lines,
-				      f, f, 1);
-  else
-    do_line_insertion_deletion_costs (frame,
-				      tty->TS_ins_line, tty->TS_ins_multi_lines,
-				      tty->TS_del_line, tty->TS_del_multi_lines,
-				      0, 0, 1);
-
-  calculate_ins_del_char_costs (frame);
-
-  /* Don't use TS_repeat if its padding is worse than sending the chars */
-  if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
-    tty->RPov = string_cost (tty->TS_repeat);
-  else
-    tty->RPov = FRAME_COLS (frame) * 2;
-
-  cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
+    {
+      struct tty_display_info *tty = FRAME_TTY (frame);
+      register char *f = (tty->TS_set_scroll_region
+                          ? tty->TS_set_scroll_region
+                          : tty->TS_set_scroll_region_1);
+
+      FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
+
+      tty->costs_set = 1;
+
+      /* These variables are only used for terminal stuff.  They are
+         allocated 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. */
+
+      max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
+      max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
+
+      if (char_ins_del_vector != 0)
+        char_ins_del_vector
+          = (int *) xrealloc (char_ins_del_vector,
+                              (sizeof (int)
+                               + 2 * max_frame_cols * sizeof (int)));
+      else
+        char_ins_del_vector
+          = (int *) xmalloc (sizeof (int)
+                             + 2 * max_frame_cols * sizeof (int));
+
+      bzero (char_ins_del_vector, (sizeof (int)
+                                   + 2 * max_frame_cols * sizeof (int)));
+
+
+      if (f && (!tty->TS_ins_line && !tty->TS_del_line))
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_rev_scroll, tty->TS_ins_multi_lines,
+                                          tty->TS_fwd_scroll, tty->TS_del_multi_lines,
+                                          f, f, 1);
+      else
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_ins_line, tty->TS_ins_multi_lines,
+                                          tty->TS_del_line, tty->TS_del_multi_lines,
+                                          0, 0, 1);
+
+      calculate_ins_del_char_costs (frame);
+
+      /* Don't use TS_repeat if its padding is worse than sending the chars */
+      if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
+        tty->RPov = string_cost (tty->TS_repeat);
+      else
+        tty->RPov = FRAME_COLS (frame) * 2;
+
+      cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
+    }
 }
 
 struct fkey_table {
@@ -2142,7 +2151,7 @@
      Lisp_Object frame;
 {
   struct frame *f;
-  
+
   if (NILP (frame))
     {
       f = XFRAME (selected_frame);
@@ -2177,7 +2186,9 @@
   bzero (tty_list, sizeof (struct tty_display_info));
   tty_list->name = 0;
   tty_list->input = stdin;
-  tty_list->input = stdout;
+  tty_list->output = stdout;
+  tty_list->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+  tty_list->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
   return tty_list;
 }
 
@@ -2211,7 +2222,18 @@
     }
 
   if (! tty->Wcm)
-      tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+    tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+
+  if (! tty->display_method)
+    tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
+
+  /* Initialize the common members in the new display method with our
+     predefined template. */
+  *tty->display_method = tty_display_method_template;
+  f->display_method = tty->display_method;
+
+  /* Termcap-based displays don't support window-based redisplay. */
+  f->display_method->rif = 0;
 
   /* Make sure the frame is live; if an error happens, it must be
      deleted. */
@@ -2219,7 +2241,6 @@
   if (! f->output_data.tty)
     abort ();
   f->output_data.tty->display_info = tty;
-  
   if (name)
     {
       int fd;
@@ -2245,7 +2266,7 @@
   tty->type = xstrdup (terminal_type);
 
   add_keyboard_wait_descriptor (fileno (tty->input));
-  
+
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2253,22 +2274,21 @@
 
   area = (char *) xmalloc (2044);
 
-  FrameRows = FRAME_LINES (f);
-  FrameCols = FRAME_COLS (f);
-  specified_window = FRAME_LINES (f);
-
-  delete_in_insert_mode = 1;
-
-  UseTabs = 0;
-  TTY_SCROLL_REGION_OK (tty) = 0;
+  FrameRows (tty) = FRAME_LINES (f);
+  FrameCols (tty) = FRAME_COLS (f);
+  tty->specified_window = FRAME_LINES (f);
+
+  f->display_method->delete_in_insert_mode = 1;
+
+  UseTabs (tty) = 0;
+  FRAME_SCROLL_REGION_OK (f) = 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.  */
-  TTY_LINE_INS_DEL_OK (tty) = 0;
-
-  TTY_CHAR_INS_DEL_OK (tty) = 1;
+  FRAME_LINE_INS_DEL_OK (f) = 0;
+  FRAME_CHAR_INS_DEL_OK (f) = 1;
 
   baud_rate = 19200;
 
@@ -2449,9 +2469,9 @@
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
   AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
-  TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db");
+  FRAME_MEMORY_BELOW_FRAME (f) = tgetflag ("db");
   tty->TF_hazeltine = tgetflag ("hz");
-  TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in");
+  FRAME_MUST_WRITE_SPACES (f) = tgetflag ("in");
   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
   tty->TF_insmode_motion = tgetflag ("mi");
   tty->TF_standout_motion = tgetflag ("ms");
@@ -2489,7 +2509,7 @@
     }
 
 #if 0  /* This is not used anywhere. */
-  TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb");
+  f->display_method->min_padding_speed = tgetnum ("pb");
 #endif
 
   TabWidth (tty) = tgetnum ("tw");
@@ -2567,7 +2587,7 @@
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      TTY_MEMORY_BELOW_FRAME (tty) = 1;
+      FRAME_MEMORY_BELOW_FRAME (f) = 1;
       tty->Wcm->cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
@@ -2577,7 +2597,7 @@
 	 This string is not valid in general since it works only
 	 for windows starting at the upper left corner;
 	 but that is all Emacs uses.
-	 
+
 	 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.
@@ -2594,7 +2614,7 @@
 	    tty->TS_set_window = "\033v%C %C %C %C ";
 	}
       /* Termcap entry often fails to have :in: flag */
-      TTY_MUST_WRITE_SPACES (tty) = 1;
+      FRAME_MUST_WRITE_SPACES (f) = 1;
       /* :ti string typically fails to have \E^G! in it */
       /* This limits scope of insert-char to one line.  */
       strcpy (area, tty->TS_termcap_modes);
@@ -2649,7 +2669,7 @@
 # endif /* TERMINFO */
 #endif /*VMS */
     }
-  
+
   if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
     {
       if (name)
@@ -2671,22 +2691,22 @@
 
   UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
 
-  TTY_SCROLL_REGION_OK (tty)
+  FRAME_SCROLL_REGION_OK (f)
     = (tty->Wcm->cm_abs
        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
-  TTY_LINE_INS_DEL_OK (tty)
+  FRAME_LINE_INS_DEL_OK (f)
     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
         && (tty->TS_del_line || tty->TS_del_multi_lines))
-       || (TTY_SCROLL_REGION_OK (tty)
+       || (FRAME_SCROLL_REGION_OK (f)
            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
-  TTY_CHAR_INS_DEL_OK (tty)
+  FRAME_CHAR_INS_DEL_OK (f)
     = ((tty->TS_ins_char || tty->TS_insert_mode
         || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
        && (tty->TS_del_char || tty->TS_del_multi_chars));
 
-  TTY_FAST_CLEAR_END_OF_LINE (tty) = tty->TS_clr_line != 0;
+  FRAME_FAST_CLEAR_END_OF_LINE (f) = tty->TS_clr_line != 0;
 
   init_baud_rate (fileno (TTY_INPUT (tty)));
   if (read_socket_hook)		/* Baudrate is somewhat
@@ -2696,14 +2716,22 @@
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
 
+#ifdef AIXHFT
+  /* The HFT system on AIX doesn't optimize for scrolling, so it's
+     really ugly at times.  */
+  FRAME_LINE_INS_DEL_OK (f) = 0;
+  FRAME_CHAR_INS_DEL_OK (f) = 0;
+#endif
+
   /* Don't do this.  I think termcap may still need the buffer. */
   /* xfree (buffer); */
 
+  /* Set the top frame to the first frame on this display. */
   tty->top_frame = frame;
-  
+
   /* Init system terminal modes (RAW or CBREAK, etc.).  */
   init_sys_modes (tty);
-  
+
   tty_set_terminal_modes (tty);
 
   return tty;
@@ -2733,7 +2761,7 @@
   char *name = 0;
 
   CHECK_STRING (tty);
-  
+
   if (SBYTES (tty) > 0)
     {
       name = (char *) alloca (SBYTES (tty) + 1);
@@ -2745,7 +2773,7 @@
 
   if (! t)
     error ("No such tty device: %s", name);
-  
+
   delete_tty (t);
 }
 
@@ -2755,14 +2783,14 @@
 delete_tty (struct tty_display_info *tty)
 {
   Lisp_Object tail, frame;
-  
+
   if (deleting_tty)
     /* We get a recursive call when we delete the last frame on this
        tty. */
     return;
 
   deleting_tty = 1;
-  
+
   if (tty == tty_list)
     tty_list = tty->next;
   else
@@ -2782,20 +2810,20 @@
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
+      if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
         {
           Fdelete_frame (frame, Qt);
           f->output_data.tty = 0;
         }
     }
-  
+
   reset_sys_modes (tty);
 
   if (tty->name)
     xfree (tty->name);
   if (tty->type)
     xfree (tty->type);
-  
+
   if (tty->input)
     {
       delete_keyboard_wait_descriptor (fileno (tty->input));
@@ -2806,13 +2834,16 @@
     fclose (tty->output);
   if (tty->termscript)
     fclose (tty->termscript);
-  
+
   if (tty->old_tty)
     xfree (tty->old_tty);
 
   if (tty->Wcm)
-    xfree (tty->Wcm); 
-  
+    xfree (tty->Wcm);
+
+  if (tty->display_method)
+    xfree (tty->display_method);
+
   bzero (tty, sizeof (struct tty_display_info));
   xfree (tty);
   deleting_tty = 0;
@@ -2865,7 +2896,9 @@
   defsubr (&Sframe_tty_name);
   defsubr (&Sframe_tty_type);
   defsubr (&Sdelete_tty);
-  
+
+  /* XXX tty_display_method_template initialization will go here. */
+
   Fprovide (intern ("multi-tty"), Qnil);
 }
 
--- a/src/termchar.h	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/termchar.h	Fri Jan 02 01:15:26 2004 +0000
@@ -64,29 +64,6 @@
   /* The previous terminal frame we displayed on this tty.  */
   struct frame *previous_terminal_frame;
 
-  /* Terminal characteristics. */
-  
-  int must_write_spaces;	/* Nonzero means spaces in the text must
-				   actually be output; can't just skip over
-				   some columns to leave them blank.  */
-  int fast_clear_end_of_line;   /* Nonzero means terminal has a `ce' string */
-  
-  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 scroll_region_cost;	/* Cost of setting the scroll window,
-                                   measured in characters. */
-  int memory_below_frame;	/* Terminal remembers lines scrolled
-                                   off bottom */
-
-#if 0  /* These are not used anywhere. */
-  /* EMACS_INT baud_rate; */	/* Output speed in baud */
-  int min_padding_speed;	/* Speed below which no padding necessary. */
-  int dont_calculate_costs;     /* Nonzero means don't bother computing
-                                   various cost tables; we won't use them. */
-#endif
-
   /* Strings, numbers and flags taken from the termcap entry.  */
 
   char *TS_ins_line;		/* "al" */
@@ -198,6 +175,13 @@
   /* Flag used in tty_show/hide_cursor.  */
 
   int cursor_hidden;
+
+  /* Nonzero means use ^S/^Q for flow control.  */
+  int flow_control;
+
+  /* This is a copy of struct frame's display_method value; needed for
+     freeing up memory when deleting the tty. */
+  struct display_method *display_method;
 };
 
 /* A chain of structures for all tty devices currently in use. */
@@ -215,13 +199,5 @@
 #define TTY_OUTPUT(t) ((t)->output)
 #define TTY_TERMSCRIPT(t) ((t)->termscript)
 
-#define TTY_MUST_WRITE_SPACES(t) ((t)->must_write_spaces)
-#define TTY_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line)
-#define TTY_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok)
-#define TTY_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok)
-#define TTY_SCROLL_REGION_OK(t) ((t)->scroll_region_ok)
-#define TTY_SCROLL_REGION_COST(t) ((t)->scroll_region_cost)
-#define TTY_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame)
-
 /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193
    (do not change this comment) */
--- a/src/termhooks.h	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/termhooks.h	Fri Jan 02 01:15:26 2004 +0000
@@ -31,11 +31,46 @@
 #endif
 
 /* Device-local parameters. */
-struct device
+struct display_method
 {
+  /* Terminal characteristics. */
+  
+  int must_write_spaces;	/* Nonzero means spaces in the text must
+				   actually be output; can't just skip over
+				   some columns to leave them blank.  */
+  int fast_clear_end_of_line;   /* Nonzero means terminal has a `ce' string */
+  
+  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 scroll_region_cost;	/* Cost of setting the scroll window,
+                                   measured in characters. */
+  int memory_below_frame;	/* Terminal remembers lines scrolled
+                                   off bottom */
+
+#if 0  /* These are not used anywhere. */
+  /* EMACS_INT baud_rate; */	/* Output speed in baud */
+  int min_padding_speed;	/* Speed below which no padding necessary. */
+  int dont_calculate_costs;     /* Nonzero means don't bother computing
+                                   various cost tables; we won't use them. */
+#endif
+
+  /* Window-based redisplay interface for this frame (0 for termcap
+     frames). */
+  struct redisplay_interface *rif;
+  
   /* XXX Display hooks will go here. */
 };
 
+#define FRAME_MUST_WRITE_SPACES(f) ((f)->display_method->must_write_spaces)
+#define FRAME_FAST_CLEAR_END_OF_LINE(f) ((f)->display_method->fast_clear_end_of_line)
+#define FRAME_LINE_INS_DEL_OK(f) ((f)->display_method->line_ins_del_ok)
+#define FRAME_CHAR_INS_DEL_OK(f) ((f)->display_method->char_ins_del_ok)
+#define FRAME_SCROLL_REGION_OK(f) ((f)->display_method->scroll_region_ok)
+#define FRAME_SCROLL_REGION_COST(f) ((f)->display_method->scroll_region_cost)
+#define FRAME_MEMORY_BELOW_FRAME(f) ((f)->display_method->memory_below_frame)
+
 /* Text display hooks.  */
 
 extern void (*cursor_to_hook) P_ ((int vpos, int hpos));
@@ -432,7 +467,7 @@
   meta_modifier	=  CHAR_META	/* Under X, the XK_Meta_[LR] keysyms.  */
 };
 
-#endif
+#endif /* CONSP */
 
 /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d
    (do not change this comment) */
--- a/src/window.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/window.c	Fri Jan 02 01:15:26 2004 +0000
@@ -6384,6 +6384,7 @@
 {
   struct frame *f = make_terminal_frame (0, 0);
   XSETFRAME (selected_frame, f);
+  Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
   selected_window = f->selected_window;
   last_nonminibuf_frame = f;
--- a/src/xdisp.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/xdisp.c	Fri Jan 02 01:15:26 2004 +0000
@@ -2008,6 +2008,9 @@
   XSETWINDOW (it->window, w);
   it->w = w;
   it->f = XFRAME (w->frame);
+  
+  /* XXX rif hack: Make sure the redisplay interface is correctly set. */
+  rif = it->f->display_method->rif;
 
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
@@ -12899,7 +12902,7 @@
 
   /* Window must either use window-based redisplay or be full width.  */
   if (!FRAME_WINDOW_P (f)
-      && (!TTY_LINE_INS_DEL_OK (CURTTY ())
+      && (!FRAME_LINE_INS_DEL_OK (f)
 	  || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
@@ -13332,7 +13335,7 @@
 
 	      /* On dumb terminals delete dvpos lines at the end
 		 before inserting dvpos empty lines.  */
-	      if (!TTY_SCROLL_REGION_OK (FRAME_TTY (f)))
+	      if (!FRAME_SCROLL_REGION_OK (f))
 		ins_del_lines (end - dvpos, -dvpos);
 
 	      /* Insert dvpos empty lines in front of
@@ -13353,7 +13356,7 @@
 
 	      /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
-	      if (!TTY_SCROLL_REGION_OK (FRAME_TTY (f)))
+	      if (!FRAME_SCROLL_REGION_OK (f))
 		ins_del_lines (end + dvpos, -dvpos);
 	    }
 
@@ -21194,6 +21197,9 @@
 
   TRACE ((stderr, "expose_frame "));
 
+  /* XXX rif hack: Make sure redisplay interface is updated. */
+  rif = f->display_method->rif;
+  
   /* No need to redraw if frame will be redrawn soon.  */
   if (FRAME_GARBAGED_P (f))
     {
--- a/src/xfaces.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/xfaces.c	Fri Jan 02 01:15:26 2004 +0000
@@ -6640,7 +6640,8 @@
 	{
 	  FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
 #ifdef USE_X_TOOLKIT
-	  x_update_menu_appearance (f);
+          if (FRAME_WINDOW_P (f))
+            x_update_menu_appearance (f);
 #endif
 	}
 
--- a/src/xfns.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/xfns.c	Fri Jan 02 01:15:26 2004 +0000
@@ -3191,6 +3191,9 @@
 
   check_x ();
 
+  /* XXX rif hack:Make sure rif is set to the right value. */
+  rif = x_display_method.rif;
+  
   /* Use this general default value to start with
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
@@ -3245,6 +3248,7 @@
   /* Note that X Windows does support scroll bars.  */
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
 
+  f->display_method = &x_display_method;
   f->output_method = output_x_window;
   f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
   bzero (f->output_data.x, sizeof (struct x_output));
@@ -9980,6 +9984,8 @@
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
+  f->display_method = &x_display_method;
+
   /* By setting the output method, we're essentially saying that
      the frame is live, as per FRAME_LIVE_P.  If we get a signal
      from this point on, x_destroy_window might screw up reference
--- a/src/xterm.c	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/xterm.c	Fri Jan 02 01:15:26 2004 +0000
@@ -184,6 +184,10 @@
 
 int x_use_underline_position_properties;
 
+/* Generic display parameters for X displays. */
+
+struct display_method x_display_method;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -382,7 +386,8 @@
     {
       Lisp_Object rest, frame;
       FOR_EACH_FRAME (rest, frame)
-	x_flush (XFRAME (frame));
+        if (FRAME_X_P (XFRAME (frame)))
+          x_flush (XFRAME (frame));
     }
   else if (FRAME_X_P (f))
     XFlush (FRAME_X_DISPLAY (f));
@@ -469,7 +474,6 @@
   /* Nothing to do.  */
 }
 
-
 /* Start update of window W.  Set the global variable updated_window
    to the window being updated and set output_cursor to the cursor
    position of W.  */
@@ -1365,7 +1369,8 @@
   for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     if (GC_FRAMEP (XCAR (tail))
 	&& (f = XFRAME (XCAR (tail)),
-	    (f->output_data.nothing != 1
+	    (FRAME_X_P (f)
+             && f->output_data.nothing != 1
 	     && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
 	&& f->output_data.x->widget == widget)
       return f;
@@ -3057,6 +3062,9 @@
 frame_highlight (f)
      struct frame *f;
 {
+  /* XXX hack: make sure rif is right. */
+  rif = f->display_method->rif;
+  
   /* We used to only do this if Vx_no_window_manager was non-nil, but
      the ICCCM (section 4.1.6) says that the window's border pixmap
      and border pixel are window attributes which are "private to the
@@ -3072,6 +3080,9 @@
 frame_unhighlight (f)
      struct frame *f;
 {
+  /* XXX hack: make sure rif is right. */
+  rif = f->display_method->rif;
+  
   /* We used to only do this if Vx_no_window_manager was non-nil, but
      the ICCCM (section 4.1.6) says that the window's border pixmap
      and border pixel are window attributes which are "private to the
@@ -3663,7 +3674,8 @@
 
       /* Clear the mouse-moved flag for every frame on this display.  */
       FOR_EACH_FRAME (tail, frame)
-	if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+	if (FRAME_X_P (XFRAME (frame))
+            && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
 	  XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
@@ -3877,6 +3889,9 @@
       if (! GC_FRAMEP (frame))
 	abort ();
 
+      if (! FRAME_X_P (XFRAME (frame)))
+        continue;
+      
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -3911,11 +3926,14 @@
        XGCTYPE (tail) == Lisp_Cons;
        tail = XCDR (tail))
     {
-      Lisp_Object frame = XCAR (tail);
-      Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
-
-      if (menu_bar && xlwmenu_window_p (menu_bar, window))
-	return menu_bar;
+      if (FRAME_X_P (XFRAME (XCAR (tail))))
+        {
+          Lisp_Object frame = XCAR (tail);
+          Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+
+          if (menu_bar && xlwmenu_window_p (menu_bar, window))
+            return menu_bar;
+        }
     }
 
   return NULL;
@@ -8027,7 +8045,7 @@
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
 	{
 	  FRAME_XIC (f) = NULL;
 	  if (FRAME_XIC_FONTSET (f))
@@ -8130,7 +8148,8 @@
 	{
 	  struct frame *f = XFRAME (frame);
 
-	  if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+	  if (FRAME_X_P (f)
+              && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
 	    if (FRAME_XIC (f) == NULL)
 	      {
 		create_frame_xic (f);
@@ -10801,43 +10820,41 @@
 extern frame_parm_handler x_frame_parm_handlers[];
 
 static struct redisplay_interface x_redisplay_interface =
-{
-  x_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
+  {
+    x_frame_parm_handlers,
+    x_produce_glyphs,
+    x_write_glyphs,
+    x_insert_glyphs,
+    x_clear_end_of_line,
+    x_scroll_run,
+    x_after_update_window_line,
+    x_update_window_begin,
+    x_update_window_end,
+    x_cursor_to,
+    x_flush,
 #ifndef XFlush
-  x_flush,
+    x_flush,
 #else
-  0,  /* flush_display_optional */
-#endif
-  x_clear_window_mouse_face,
-  x_get_glyph_overhangs,
-  x_fix_overlapping_area,
-  x_draw_fringe_bitmap,
-  x_per_char_metric,
-  x_encode_char,
-  x_compute_glyph_string_overhangs,
-  x_draw_glyph_string,
-  x_define_frame_cursor,
-  x_clear_frame_area,
-  x_draw_window_cursor,
-  x_draw_vertical_window_border,
-  x_shift_glyphs_for_insert
-};
+    0,  /* flush_display_optional */
+#endif
+    x_clear_window_mouse_face,
+    x_get_glyph_overhangs,
+    x_fix_overlapping_area,
+    x_draw_fringe_bitmap,
+    x_per_char_metric,
+    x_encode_char,
+    x_compute_glyph_string_overhangs,
+    x_draw_glyph_string,
+    x_define_frame_cursor,
+    x_clear_frame_area,
+    x_draw_window_cursor,
+    x_draw_vertical_window_border,
+    x_shift_glyphs_for_insert
+  };
 
 void
 x_initialize ()
 {
-  rif = &x_redisplay_interface;
-
   clear_frame_hook = x_clear_frame;
   ins_del_lines_hook = x_ins_del_lines;
   delete_glyphs_hook = x_delete_glyphs;
@@ -10857,13 +10874,13 @@
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
 
-  TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1;
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */
-  TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */
-  TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what
-                                                         scrolls off the
-                                                         bottom */
+  x_display_method.rif = &x_redisplay_interface;
+  x_display_method.scroll_region_ok = 1; /* We'll scroll partial frames. */
+  x_display_method.char_ins_del_ok = 1;
+  x_display_method.line_ins_del_ok = 1; /* We'll just blt 'em. */
+  x_display_method.fast_clear_end_of_line = 1; /* X does this well. */
+  x_display_method.memory_below_frame = 0; /* We don't remember what scrolls off the
+                                              bottom. */
   baud_rate = 19200;
 
   x_noop_count = 0;
--- a/src/xterm.h	Thu Jan 01 17:55:53 2004 +0000
+++ b/src/xterm.h	Fri Jan 02 01:15:26 2004 +0000
@@ -134,6 +134,9 @@
   int height, width, depth;
 };
 
+/* Generic parameters for X displays. */
+extern struct display_method x_display_method;
+
 /* For each X display, we have a structure that records
    information about it.  */