changeset 83004:7900111db01c

Converted display hooks to be display-local. Plus many bugfixes. lib-src/emacsclient.c (window_change_signal): Renamed to pass_signal_to_emacs. (init_signal): Pass SIGINT and SIGQUIT to the emacs process. lisp/faces.el (face-valid-attribute-values): Use the window-system function, not the variable. (read-face-attribute, face-spec-set-match-display, frame-set-background-mode) (face-set-after-frame-default): Ditto. lisp/frame.el (make-frame-on-tty): Added interactive declaration (suggested by Robert J. Chassell). Use tty-create-frame-with-faces, not make-terminal-frame. src/termhooks.h (struct display_method): Renamed to display for brevity. (struct display): Added all display hook variables as members of this structure. Added next_display, reference_count, type and display_info components. (FRAME_MUST_WRITE_SPACES, FRAME_FAST_CLEAR_END_OF_LINE, FRAME_LINE_INS_DEL_OK) (FRAME_CHAR_INS_DEL_OK, FRAME_SCROLL_REGION_OK, FRAME_SCROLL_REGION_COST) (FRAME_MEMORY_BELOW_FRAME, FRAME_RIF): Updated for struct display. (FRAME_DISPLAY): New macro. (create_display, delete_display): New prototypes. src/frame.h (struct frame): Added `display' member, removed display_method. (FRAME_LIVE_P): Look at f->display, not f->output_data. src/termchar.h (struct tty_display_info): Removed display_method component. (FRAME_TTY): Use the display structure, not output_data. src/term.c (display_list): New variable. (cursor_to_hook, raw_cursor_to_hook, clear_to_end_hook, clear_frame_hook) (clear_end_of_line_hook, ins_del_lines_hook, delete_glyphs_hook) (ring_bell_hook, reset_terminal_modes_hook, set_terminal_modes_hook) (update_begin_hook, update_end_hook, set_terminal_window_hook) (insert_glyphs_hook, write_glyphs_hook, delete_glyphs_hoo, read_socket_hook) (frame_up_to_date_hook, mouse_position_hook, frame_rehighlight_hook) (frame_raise_lower_hook, set_vertical_scroll_bar_hook, condemn_scroll_bars_hook) (redeem_scroll_bar_hook, judge_scroll_bars_hook): Moved to struct display. (tty_display_method_template): Removed. (syms_of_term): Don't initialize tty_display_method_template. (ring_bell, set_terminal_modes, reset_terminal_modes, update_begin) (update_end, set_terminal_window, cursor_to, raw_cursor_to, clear_to_end) (clear_frame, clear_end_of_line, write_glyphs, insert_glyphs) (delete_glyphs, ins_del_lines): Access display hooks through the frame pointer. (Ftty_display_color_p): Use the frame given as a parameter, or else return nil. (Ftty_display_color_cells): Ditto. (get_named_tty): Renamed to get_named_tty_display, changed return type to struct display. (term_dummy_init): Renamed to initial_term_init. Create and return an initial display. (term_init): Initialize a new struct display and return a pointer to it instead of tty_display_info. Removed frame initialization kludge. (Fdelete_tty): Updated for struct display. (delete_tty): The parameter type is now struct display, not tty_display_info. Delete the display, too. (create_tty_output): New function for creating tty_output structures. (delete_tty_output): New function for deleting tty_output structures. (create_display): New function for creating and registering display structures. (delete_display): New function for deleting and unregistering display structures. src/dispextern.h: Updated prototypes. src/dispnew.c: Include frame.h before termhooks.h. (init_display): Updated term_init call to new signature. src/emacs.c: Include frame.h (for termhooks.h). src/keymap.c: Ditto. src/lread.c: Ditto. src/xsmfns.c: Ditto. src/process.c: Include frame.h before termhooks.h. src/frame.c (Fwindow_system): New function. (syms_of_frame): Initialize it. (make_terminal_frame): Open the terminal device before creating the new frame. Disable scrollbars here, term_init cannot do that anymore. (Fdelete_frame): Use the new delete_frame_hook, don't do display-specific frame deletion here. Ditto for delete_display_hook. (Fmouse_position, Fmouse_pixel_position, Fraise_frame, Flower_frame) (Fredirect_frame_focus): Access display hooks through the frame pointer. src/keyboard.c: Include frame.h before termhooks.h. (start_polling, input_polling_used, stop_polling, gobble_input): Ignore read_socket_hook. (kbd_buffer_get_event, Fset_input_mode): Access display hooks through the frame pointer. (read_avail_input): Loop through all display devices for and call all read_socket_hook functions. Check ttys even if read_socket_hook returned an error. src/sysdep.c (discard_tty_input): Ignore read_socket_hook. (stuff_char): Don't do anything if the current frame is not on a termcap display. (request_sigio, unrequest_sigio): Ignore read_socket_hook. (init_sys_modes): Always call narrow_foreground_group. Set up terminal modes and sigio even under X. src/xdisp.c (message2_nolog, message3_nolog, redisplay_internal) (set_vertical_scroll_bar, redisplay_window): Access display hooks through the frame pointer. (echo_area_display): Don't be afraid of termcap frames during an X+tty combo session. src/xfaces.c: Include termhooks.h. (Ftty_supports_face_attributes_p): Use the given frame, not selected_frame. src/xfns.c (x_set_scroll_bar_foreground, x_set_scroll_bar_background): Access display hooks through the frame pointer. (Fx_create_frame, x_create_tip_frame): Initialize the frame's display structure. src/xmenu.c: Include termhooks.h after frame.h. src/xselect.c (x_own_selection, some_frame_on_display, x_get_foreign_selection) (Fx_disown_selection_internal, Fx_get_cut_buffer_internal) (Fx_store_cut_buffer_internal, Fx_rotate_cut_buffers_internal): Don't do anything if the selected frame is not an X frame. src/xterm.c (x_display_method): Removed. (x_create_frame_display, x_delete_frame_display): New functions for handling struct display objects. (x_term_init): Set up a new struct display object, too. (x_delete_display): Delete the struct display corresponding to the X display. (x_initialize): Moved hook initialization to x_create_frame_display. src/xterm.h (x_display_method): Removed. (struct x_display_info): Added frame_display component. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-44
author Karoly Lorentey <lorentey@elte.hu>
date Mon, 05 Jan 2004 05:54:35 +0000
parents 19208c3cbcc9
children 0b195559ccf5
files README.multi-tty lib-src/emacsclient.c lisp/faces.el lisp/frame.el src/Makefile.in src/cm.c src/dispextern.h src/dispnew.c src/emacs.c src/frame.c src/frame.h src/indent.c src/keyboard.c src/keymap.c src/lread.c src/print.c src/process.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/xmenu.c src/xselect.c src/xsmfns.c src/xterm.c src/xterm.h
diffstat 31 files changed, 878 insertions(+), 722 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Sat Jan 03 19:06:35 2004 +0000
+++ b/README.multi-tty	Mon Jan 05 05:54:35 2004 +0000
@@ -127,15 +127,13 @@
 THINGS TO DO
 ------------
 
-** Something with (maybe) multi-keyboard support broke function keys
-   and arrows on ttys during X+tty combo sessions.  Debug this.
+** Fix color handling during X+tty combo sessions.  (It seems that tty
+   sessions automatically convert the face colors to terminal colors
+   when the face is loaded.  This conversion must happen instead on
+   the fly in write_glyphs, which might be problematic, as color
+   approximation is done in lisp (term/tty-colors.el).)
 
-** Fix faces on tty frames during X-tty combo sessions.  There is an
-   init_frame_faces call in init_sys_modes, see if there is a problem
-   with it.
-
-** During an X-tty combo session, a (message "Hello") from a tty frame
-   goes to the X frame.  Fix this.
+** The command `emacsclient -t -e '(delete-frame)'' fails to exit.
 
 ** Find out the best way to support suspending Emacs with multiple
    ttys.  My guess: disable it on the controlling tty, but from other
@@ -143,16 +141,17 @@
    extend emacsclient to handle suspend/resume.  A `kill -STOP' almost
    works right now.)
 
-** Move baud_rate to tty_output.
+** During an X session, Emacs seems to read from stdin.
 
-** Do tty output through term_hooks, like graphical display backends.
+** Move baud_rate to struct display.
+
+** Do tty output through struct display, like graphical display
+   backends.
 
 ** 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).
@@ -162,15 +161,14 @@
 ** Do a grep on XXX and ?? for more issues.
 
 ** Understand Emacs's low-level input system (it seems complicated) :-)
-
-** What does interrupt_input do?  I tried to disable it for raw
+   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. :-(
+** Make sure C-g goes to the right frame with ttys.  This is hard, as
+   SIGINT doesn't have a tty parameter. :-(
 
 ** I have seen a case when Emacs with multiple ttys fell into a loop
    eating 100% of CPU time.  Strace showed this loop:
@@ -191,19 +189,19 @@
    I have seen something similar with a single X frame, but have not
    been able to reproduce it for debugging.
 
-** Define a output_initial value for output_method for the initial
+   Update: This may have been caused by checking for nread != 0
+   instead of nread > 0 after calling read_socket_hook in
+   read_avail_input.
+
+** Define an output_initial value for output_method for the initial
    frame that is dumped with Emacs.  Checking for this frame (e.g. in
    cmd_error_internal) is ugly.
 
 ** emacsclient -t from an Emacs term buffer does not work, complains
    about face problems.  This can even lock up Emacs (if the recursive
-   frame sets single_kboard).
-
-** Clean up the source of emacsclient.  It is a mess.
-
-** C-x 5 2, C-x 5 o, C-x 5 0 on an emacsclient frame unexpectedly
-   exits emacsclient.  This is a result of trying to be clever with
-   delete-frame-functions.
+   frame sets single_kboard).  Update: the face problems are caused by
+   bugs in term.el, not in multi-tty.  The lockup is caused by
+   single_kboard mode.
 
 DIARY OF CHANGES
 ----------------
@@ -449,4 +447,38 @@
 
    (Done.)
 
+-- Clean up the source of emacsclient.  It is a mess.
+
+   (Done, eliminated stupid proxy-pty kludge.)
+
+-- Fix faces on tty frames during X-tty combo sessions.  There is an
+   init_frame_faces call in init_sys_modes, see if there is a problem
+   with it.
+
+   (Done, there was a stupid mistake in
+   Ftty_supports_face_attributes_p. Colors are broken, though.)
+
+-- C-x 5 2, C-x 5 o, C-x 5 0 on an emacsclient frame unexpectedly
+   exits emacsclient.  This is a result of trying to be clever with
+   delete-frame-functions.
+
+   (Fixed, added delete-tty-after-functions, and changed server.el to
+   use it.)
+
+-- Something with (maybe) multi-keyboard support broke function keys
+   and arrows on ttys during X+tty combo sessions.  Debug this.
+
+   (I can't reproduce it, maybe the terminal type was wrong.)
+
+-- Fix input from raw ttys (again).
+
+   (Now it seems to work all right.)
+
+-- During an X-tty combo session, a (message "Hello") from a tty frame
+   goes to the X frame.  Fix this.
+
+   (Done.  There was a safeguard against writing to the initial
+   terminal frame during bootstrap which prevented echo_area_display
+   from working correctly on a tty frame during a combo session.)
+
 ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/lib-src/emacsclient.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/lib-src/emacsclient.c	Mon Jan 05 05:54:35 2004 +0000
@@ -283,14 +283,14 @@
 #endif
 
 SIGTYPE
-window_change_signal (int signalnum)
+pass_signal_to_emacs (int signalnum)
 {
   int old_errno = errno;
 
   if (emacs_pid)
-    kill (emacs_pid, SIGWINCH);
+    kill (emacs_pid, signalnum);
 
-  signal (SIGWINCH, window_change_signal);
+  signal (signalnum, pass_signal_to_emacs);
   errno = old_errno;
 }
 
@@ -298,7 +298,9 @@
 init_signals (void)
 {
   /* Set up signal handlers. */
-  signal (SIGWINCH, window_change_signal);
+  signal (SIGWINCH, pass_signal_to_emacs);
+  signal (SIGINT, pass_signal_to_emacs);
+  signal (SIGQUIT, pass_signal_to_emacs);
 }
 
 
--- a/lisp/faces.el	Sat Jan 03 19:06:35 2004 +0000
+++ b/lisp/faces.el	Mon Jan 05 05:54:35 2004 +0000
@@ -905,7 +905,7 @@
   (let ((valid
          (case attribute
            (:family
-            (if window-system
+            (if (window-system frame)
                 (mapcar #'(lambda (x) (cons (car x) (car x)))
                         (x-font-family-list))
 	      ;; Only one font on TTYs.
@@ -914,7 +914,7 @@
             (mapcar #'(lambda (x) (cons (symbol-name x) x))
                     (internal-lisp-face-attribute-values attribute)))
            ((:underline :overline :strike-through :box)
-            (if window-system
+            (if (window-system frame)
                 (nconc (mapcar #'(lambda (x) (cons (symbol-name x) x))
                                (internal-lisp-face-attribute-values attribute))
                        (mapcar #'(lambda (c) (cons c c))
@@ -927,7 +927,7 @@
            ((:height)
             'integerp)
            (:stipple
-            (and (memq window-system '(x w32 mac))
+            (and (memq (window-system frame) '(x w32 mac))
                  (mapcar #'list
                          (apply #'nconc
                                 (mapcar (lambda (dir)
@@ -1045,7 +1045,7 @@
 	       ;; explicitly in VALID, using color approximation code
 	       ;; in tty-colors.el.
 	       (when (and (memq attribute '(:foreground :background))
-			  (not (memq window-system '(x w32 mac)))
+			  (not (memq (window-system frame) '(x w32 mac)))
 			  (not (member new-value
 				       '("unspecified"
 					 "unspecified-fg" "unspecified-bg"))))
@@ -1298,14 +1298,14 @@
 	    req (car conjunct)
 	    options (cdr conjunct)
 	    match (cond ((eq req 'type)
-			 (or (memq window-system options)
+			 (or (memq (window-system frame) options)
 			     ;; FIXME: This should be revisited to use
 			     ;; display-graphic-p, provided that the
 			     ;; color selection depends on the number
 			     ;; of supported colors, and all defface's
 			     ;; are changed to look at number of colors
 			     ;; instead of (type graphic) etc.
-			     (and (null window-system)
+			     (and (null (window-system frame))
 				  (memq 'tty options))
 			     (and (memq 'motif options)
 				  (featurep 'motif))
@@ -1537,14 +1537,14 @@
 Display-dependent faces are those which have different definitions
 according to the `background-mode' and `display-type' frame parameters."
   (let* ((bg-resource
-	  (and window-system
+	  (and (window-system frame)
 	       (x-get-resource "backgroundMode" "BackgroundMode")))
 	 (bg-color (frame-parameter frame 'background-color))
 	 (bg-mode
 	  (cond (frame-background-mode)
 		(bg-resource
 		 (intern (downcase bg-resource)))
-		((and (null window-system) (null bg-color))
+		((and (null (window-system frame)) (null bg-color))
 		 ;; No way to determine this automatically (?).
 		 'dark)
 		;; Unspecified frame background color can only happen
@@ -1561,7 +1561,7 @@
 		 'light)
 		(t 'dark)))
 	 (display-type
-	  (cond ((null window-system)
+	  (cond ((null (window-system frame))
 		 (if (tty-display-color-p frame) 'color 'mono))
 		((x-display-color-p frame)
 		 'color)
@@ -1696,7 +1696,7 @@
 	(when (not (equal face 'default))
 	  (face-spec-set face (face-user-default-spec face) frame)
 	  (internal-merge-in-global-face face frame)
-	  (when (and (memq window-system '(x w32 mac))
+	  (when (and (memq (window-system frame) '(x w32 mac))
 		     (or (not (boundp 'inhibit-default-face-x-resources))
 			 (not (eq face 'default))))
 	    (make-face-x-resource-internal face frame)))
--- a/lisp/frame.el	Sat Jan 03 19:06:35 2004 +0000
+++ b/lisp/frame.el	Mon Jan 05 05:54:35 2004 +0000
@@ -583,11 +583,12 @@
 emacsclient to sit on the real terminal device, create SIGIO
 signals upon terminal input, and forward SIGWINCH signals to
 us.)"
+  (interactive "fOpen frame on tty device: \nsTerminal type of %s: ")
   (unless device
     (error "Invalid terminal device"))
   (unless type
     (error "Invalid terminal type"))
-  (make-terminal-frame (append (list (cons 'tty device) (cons 'tty-type type)) parameters)))
+  (tty-create-frame-with-faces (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	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/Makefile.in	Mon Jan 05 05:54:35 2004 +0000
@@ -1047,7 +1047,7 @@
 charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \
 	$(config_h)
 coding.o: coding.c coding.h ccl.h buffer.h charset.h intervals.h composite.h window.h $(config_h)
-cm.o: cm.c frame.h cm.h termhooks.h systty.h termchar.h $(config_h)
+cm.o: cm.c frame.h cm.h termhooks.h termchar.h $(config_h)
 cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \
 	msdos.h dispextern.h
 pre-crt0.o: pre-crt0.c
@@ -1055,7 +1055,7 @@
 	CRT0_COMPILE ${srcdir}/ecrt0.c
 dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \
    systime.h
-dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \
+dispnew.o: dispnew.c systime.h commands.h process.h frame.h \
    window.h buffer.h dispextern.h termchar.h termopts.h termhooks.h cm.h \
    disptab.h \
    xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \
@@ -1073,19 +1073,19 @@
 filelock.o: filelock.c buffer.h systime.h epaths.h $(config_h)
 filemode.o: filemode.c  $(config_h)
 frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \
-   blockinput.h systty.h atimer.h systime.h buffer.h charset.h fontset.h \
+   blockinput.h atimer.h systime.h buffer.h charset.h fontset.h \
    msdos.h dosfns.h dispextern.h $(config_h)
 fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \
    keyboard.h termhooks.h $(config_h)
 getloadavg.o: getloadavg.c $(config_h)
-indent.o: indent.c frame.h window.h systty.h indent.h buffer.h $(config_h) termchar.h \
+indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \
    termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \
    keyboard.h
 insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h \
    dispextern.h atimer.h systime.h $(config_h)
 keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h charset.h \
    commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \
-   systty.h systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \
+   systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \
    atimer.h xterm.h puresize.h msdos.h $(config_h)
 keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \
    atimer.h systime.h puresize.h charset.h intervals.h $(config_h)
@@ -1110,7 +1110,7 @@
    keyboard.h $(config_h)
 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 \
+scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.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)
@@ -1120,7 +1120,7 @@
 sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
    process.h dispextern.h termhooks.h termchar.h termopts.h \
    frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h $(config_h)
-term.o: term.c systty.h termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
+term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
    disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h
 termcap.o: termcap.c $(config_h)
 terminfo.o: terminfo.c $(config_h)
@@ -1134,18 +1134,18 @@
    msdos.h $(config_h)
 widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
    $(srcdir)/../lwlib/lwlib.h $(config_h)
-window.o: window.c indent.h commands.h frame.h window.h buffer.h systty.h termchar.h \
+window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \
    termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \
    $(config_h)
 xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \
-   systty.h termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \
+   termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \
    msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h
 xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
    window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \
    termchar.h $(config_h)
 xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
    $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
-   charset.h gtkutil.h systty.h termchar.h $(config_h)
+   charset.h gtkutil.h termchar.h $(config_h)
 xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \
    keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \
    gtkutil.h msdos.h coding.h $(config_h)
@@ -1177,7 +1177,7 @@
 fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \
  frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h
 print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \
-   $(config_h) dispextern.h msdos.h composite.h systty.h termchar.h intervals.h
+   $(config_h) dispextern.h msdos.h composite.h termchar.h intervals.h
 lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h $(config_h) \
  termhooks.h coding.h msdos.h
 
--- a/src/cm.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/cm.c	Mon Jan 05 05:54:35 2004 +0000
@@ -29,7 +29,6 @@
 
 #include "cm.h"
 #include "termhooks.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 
 
--- a/src/dispextern.h	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/dispextern.h	Mon Jan 05 05:54:35 2004 +0000
@@ -1249,7 +1249,7 @@
 	DESCENT = FONT->descent
 	HEIGHT = FONT_HEIGHT (FONT)
 	F_DESCENT = (FRAME_FONT (F)->descent
-		     - F->output_data.x->baseline_offset)
+		     - F->device->output_data.x->baseline_offset)
 	F_HEIGHT = FRAME_LINE_HEIGHT (F)
 */
 
@@ -2748,8 +2748,8 @@
 extern void calculate_costs P_ ((struct frame *));
 extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object));
 extern void tty_setup_colors P_ ((struct tty_display_info *, int));
-extern struct tty_display_info *term_init P_ ((Lisp_Object, char *, char *));
-extern struct tty_display_info *term_dummy_init P_ ((void));
+extern struct display *term_init P_ ((char *, char *));
+extern struct display *initial_term_init P_ ((void));
 extern void fatal P_ ((/* char *, ... */));
 void cursor_to P_ ((int, int));
 extern int tty_capable_p P_ ((struct tty_display_info *, unsigned, unsigned long, unsigned long));
--- a/src/dispnew.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/dispnew.c	Mon Jan 05 05:54:35 2004 +0000
@@ -29,10 +29,8 @@
 #endif
 
 #include "lisp.h"
-#include "systty.h"             /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
-#include "termhooks.h"
 /* cm.h must come after dispextern.h on Windows.  */
 #include "dispextern.h"
 #include "cm.h"
@@ -40,6 +38,7 @@
 #include "charset.h"
 #include "keyboard.h"
 #include "frame.h"
+#include "termhooks.h"
 #include "window.h"
 #include "commands.h"
 #include "disptab.h"
@@ -6634,10 +6633,11 @@
 #endif /* VMS */
 
   {
-    struct tty_display_info *tty;
+    struct display *d;
     
-    tty = term_init (selected_frame, 0, terminal_type);
-    change_frame_size (XFRAME (selected_frame), FrameRows (tty), FrameCols (tty), 0, 0, 1);
+    d = term_init (0, terminal_type);
+    d->display_info.tty->top_frame = selected_frame;
+    change_frame_size (XFRAME (selected_frame), FrameRows (d->display_info.tty), FrameCols (d->display_info.tty), 0, 0, 1);
   }
   
   {
--- a/src/emacs.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/emacs.c	Mon Jan 05 05:54:35 2004 +0000
@@ -54,6 +54,7 @@
 #include "blockinput.h"
 #include "syssignal.h"
 #include "process.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "keyboard.h"
 #include "keymap.h"
--- a/src/frame.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/frame.c	Mon Jan 05 05:54:35 2004 +0000
@@ -42,7 +42,6 @@
 #include "fontset.h"
 #endif
 #include "blockinput.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
@@ -233,6 +232,30 @@
 	  : Qnil);
 }
 
+DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
+       doc: /* The name of the window system that FRAME is displaying through.
+The value is a symbol---for instance, 'x' for X windows.
+The value is nil if Emacs is using a text-only terminal.
+
+FRAME defaults to the currently selected frame.  */)
+  (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object type;
+  if (NILP (frame))
+    frame = selected_frame;
+
+  type = Fframep (frame);
+
+  if (NILP (type))
+    wrong_type_argument (Qframep, frame);
+
+  if (EQ (type, Qt))
+    return Qnil;
+  else
+    return type;
+}      
+
 struct frame *
 make_frame (mini_p)
      int mini_p;
@@ -484,6 +507,7 @@
      char *tty_type;
 {
   register struct frame *f;
+  struct display *display;
   Lisp_Object frame;
   char name[20];
   
@@ -502,6 +526,13 @@
   if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
     Vframe_list = Qnil;
 
+  /* Open the display before creating the new frame, because
+     create_tty_display might throw an error. */
+  if (initialized)
+    display = term_init (tty_name, tty_type);
+  else
+    display = initial_term_init ();
+  
   f = make_frame (1);
 
   XSETFRAME (frame, f);
@@ -540,37 +571,29 @@
 #else
 #ifdef WINDOWSNT
   f->output_method = output_termcap;
-  f->output_data.x = &tty_display; /* XXX */
+  f->output_data.x = &tty_display; /* XXX ??? */
 #else
 #ifdef MAC_OS8
   make_mac_terminal_frame (f);
 #else
   {
-    struct tty_display_info *tty;
     f->output_method = output_termcap;
-
-    f->output_data.tty = (struct tty_output *) xmalloc (sizeof (struct tty_output));
-    bzero (f->output_data.tty, sizeof (struct tty_output));
-
+    f->display = display;
+    f->display->reference_count++;
+    create_tty_output (f);
+    
     FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
     FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
     
-    if (initialized)
-      {
-        /* Note that term_init may signal an error, but then it is its
-           responsibility to make sure this frame is deleted. */
-        f->output_data.tty->display_info = term_init (frame, tty_name, tty_type);
-      }
-    else
-      {
-        /* init_display() will reinitialize the terminal with correct values after dump. */
-        f->output_data.tty->display_info = term_dummy_init ();
-      }
-    FRAME_TTY (f)->reference_count++;
-    f->display_method = FRAME_TTY (f)->display_method;
+    FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+    FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
 #ifdef MULTI_KBOARD
     f->kboard = FRAME_TTY (f)->kboard;
 #endif
+
+    /* Set the top frame to the newly created frame. */
+    FRAME_TTY (f)->top_frame = frame;
   }
   
 #ifdef CANNOT_DUMP
@@ -1397,30 +1420,26 @@
      promise that the display of the frame must be valid until we have
      called the window-system-dependent frame destruction routine.  */
 
-  /* I think this should be done with a hook.  */
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (f))
-    x_destroy_window (f);
-#endif
-
-  if (FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->delete_frame_hook)
+    (*FRAME_DISPLAY (f)->delete_frame_hook) (f);
+  
+  {
+    struct display *display = FRAME_DISPLAY (f);
+
+    f->output_data.nothing = 0; 
+    f->display = 0;             /* Now the frame is dead. */
+
+    /* If needed, delete the device that this frame was on.
+       (This must be done after the frame is killed.) */  
+    display->reference_count--;
+    if (display->reference_count == 0)
     {
-      int delete = 1;
-      struct tty_display_info *tty = FRAME_TTY (f);
-
-      if (! --tty->reference_count)
-        {
-          /* delete_tty would call us recursively if we don't kill the
-             frame now. */
-          xfree (f->output_data.tty);
-          f->output_data.nothing = 0;
-          delete_tty (tty);
-        }
+      if (display->delete_display_hook)
+        (*display->delete_display_hook) (display);
+      else
+        delete_display (display);
     }
-  else
-    {
-      f->output_data.nothing = 0;
-    }
+  }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
      another one.  */
@@ -1535,11 +1554,11 @@
 
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
-  if (!FRAME_TERMCAP_P (f) && mouse_position_hook)
-    (*mouse_position_hook) (&f, -1,
-			    &lispy_dummy, &party_dummy,
-			    &x, &y,
-			    &long_dummy);
+  if (FRAME_DISPLAY (f)->mouse_position_hook)
+    (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, -1,
+                                              &lispy_dummy, &party_dummy,
+                                              &x, &y,
+                                              &long_dummy);
   if (! NILP (x))
     {
       col = XINT (x);
@@ -1578,12 +1597,11 @@
 
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
-  if (FRAME_TERMCAP_P (f)
-      && mouse_position_hook)
-    (*mouse_position_hook) (&f, -1,
-			    &lispy_dummy, &party_dummy,
-			    &x, &y,
-			    &long_dummy);
+  if (FRAME_DISPLAY (f)->mouse_position_hook)
+    (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, -1,
+                                              &lispy_dummy, &party_dummy,
+                                              &x, &y,
+                                              &long_dummy);
 #endif
   XSETFRAME (lispy_dummy, f);
   return Fcons (lispy_dummy, Fcons (x, y));
@@ -1845,17 +1863,19 @@
      (frame)
      Lisp_Object frame;
 {
+  struct frame *f;
   if (NILP (frame))
     frame = selected_frame;
 
   CHECK_LIVE_FRAME (frame);
 
+  f = XFRAME (frame);
+  
   /* Do like the documentation says. */
   Fmake_frame_visible (frame);
 
-  if (FRAME_TERMCAP_P (XFRAME (frame))
-      && frame_raise_lower_hook)
-    (*frame_raise_lower_hook) (XFRAME (frame), 1);
+  if (FRAME_DISPLAY (f)->frame_raise_lower_hook)
+    (*FRAME_DISPLAY (f)->frame_raise_lower_hook) (f, 1);
 
   return Qnil;
 }
@@ -1869,14 +1889,17 @@
      (frame)
      Lisp_Object frame;
 {
+  struct frame *f;
+  
   if (NILP (frame))
     frame = selected_frame;
 
   CHECK_LIVE_FRAME (frame);
 
-  if (FRAME_TERMCAP_P (XFRAME (frame))
-      && frame_raise_lower_hook)
-    (*frame_raise_lower_hook) (XFRAME (frame), 0);
+  f = XFRAME (frame);
+  
+  if (FRAME_DISPLAY (f)->frame_raise_lower_hook)
+    (*FRAME_DISPLAY (f)->frame_raise_lower_hook) (f, 0);
 
   return Qnil;
 }
@@ -1910,6 +1933,8 @@
      (frame, focus_frame)
      Lisp_Object frame, focus_frame;
 {
+  struct frame *f;
+  
   /* Note that we don't check for a live frame here.  It's reasonable
      to redirect the focus of a frame you're about to delete, if you
      know what other frame should receive those keystrokes.  */
@@ -1918,11 +1943,12 @@
   if (! NILP (focus_frame))
     CHECK_LIVE_FRAME (focus_frame);
 
-  XFRAME (frame)->focus_frame = focus_frame;
-
-  if (!FRAME_TERMCAP_P (XFRAME (frame))
-      && frame_rehighlight_hook)
-    (*frame_rehighlight_hook) (XFRAME (frame));
+  f = XFRAME (frame);
+  
+  f->focus_frame = focus_frame;
+
+  if (FRAME_DISPLAY (f)->frame_rehighlight_hook)
+    (*FRAME_DISPLAY (f)->frame_rehighlight_hook) (f);
 
   return Qnil;
 }
@@ -4198,6 +4224,7 @@
   defsubr (&Sactive_minibuffer_window);
   defsubr (&Sframep);
   defsubr (&Sframe_live_p);
+  defsubr (&Swindow_system);
   defsubr (&Smake_terminal_frame);
   defsubr (&Shandle_switch_frame);
   defsubr (&Signore_event);
--- a/src/frame.h	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/frame.h	Mon Jan 05 05:54:35 2004 +0000
@@ -68,7 +68,7 @@
 #define FRAME_FOREGROUND_PIXEL(f) ((f)->foreground_pixel)
 #define FRAME_BACKGROUND_PIXEL(f) ((f)->background_pixel)
 
-struct device;
+struct display;
 
 struct frame
 {
@@ -256,26 +256,24 @@
   /* Canonical Y unit.  Height of a line, in pixels.  */
   int line_height;
 
-  /* The display hooks to use with this frame. */
-  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.  */
+  /* The output method says how the contents of this frame are
+     displayed.  It could be using termcap, or using an X window.
+     This must be the same as the display->type. */
   enum output_method output_method;
 
-  /* A structure of auxiliary data used for displaying the contents.
-     struct tty_output is used for termcap frames;
-     it is defined in term.h.
-     struct x_output is used for X window frames;
-     it is defined in xterm.h.
-     struct w32_output is used for W32 window frames;
-     it is defined in w32term.h.  */
+  /* The display that this frame uses.  If this is NULL, then the
+     frame is deleted. */
+  struct display *display;
+  
+  /* Display-dependent, frame-local auxiliary data used for displaying
+     the contents.  When the frame is deleted, this data is deleted as
+     well. */
   union output_data
   {
-    struct tty_output *tty;
-    struct x_output *x;
-    struct w32_output *w32;
-    struct mac_output *mac;
+    struct tty_output *tty;     /* termchar.h */
+    struct x_output *x;         /* xterm.h */
+    struct w32_output *w32;     /* w32term.h */
+    struct mac_output *mac;     /* macterm.h */
     EMACS_INT nothing;
   }
   output_data;
@@ -291,11 +289,12 @@
   int left_fringe_width, right_fringe_width;
 
 #ifdef MULTI_KBOARD
+  /* XXX Maybe this should be moved to struct display, too. */
   /* A pointer to the kboard structure associated with this frame.
      For termcap frames, it will be the same as
-     output_data.tty->display_info->kboard.
+     display->display_info.tty->kboard.
      For X frames, it will be the same as
-     output_data.x->display_info->kboard.  */
+     display->display_info.x->kboard.  */
   struct kboard *kboard;
 #endif
 
@@ -486,7 +485,7 @@
 #endif
 
 /* Nonzero if frame F is still alive (not deleted).  */
-#define FRAME_LIVE_P(f) ((f)->output_data.nothing != 0)
+#define FRAME_LIVE_P(f) ((f)->display != 0)
 
 /* Nonzero if frame F is a minibuffer-only frame.  */
 #define FRAME_MINIBUF_ONLY_P(f) \
--- a/src/indent.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/indent.c	Mon Jan 05 05:54:35 2004 +0000
@@ -30,7 +30,6 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "disptab.h"
--- a/src/keyboard.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/keyboard.c	Mon Jan 05 05:54:35 2004 +0000
@@ -23,13 +23,12 @@
 #include <signal.h>
 #include <stdio.h>
 #include "lisp.h"
-#include "systty.h" /* This must be included befor termchar.h. */
 #include "termchar.h"
 #include "termopts.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "macros.h"
 #include "keyboard.h"
-#include "frame.h"
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
@@ -2065,7 +2064,10 @@
 start_polling ()
 {
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input)
     {
       /* Turn alarm handling on unconditionally.  It might have
 	 been turned off in process.c.  */
@@ -2099,7 +2101,10 @@
 input_polling_used ()
 {
 #ifdef POLL_FOR_INPUT
-  return read_socket_hook && !interrupt_input;
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  return !interrupt_input;
 #else
   return 0;
 #endif
@@ -2111,7 +2116,10 @@
 stop_polling ()
 {
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input)
     ++poll_suppress_count;
 #endif
 }
@@ -4081,7 +4089,8 @@
 	 If there is no valid info, it does not store anything
 	 so x remains nil.  */
       x = Qnil;
-      (*mouse_position_hook) (&f, 0, &bar_window, &part, &x, &y, &time);
+      if (f && FRAME_DISPLAY (f)->mouse_position_hook) /* XXX Can f or mouse_position_hook be NULL here? */
+        (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, 0, &bar_window, &part, &x, &y, &time);
 
       obj = Qnil;
 
@@ -6516,7 +6525,10 @@
     }
   else
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input && poll_suppress_count == 0)
     {
       SIGMASKTYPE mask;
       mask = sigblock (sigmask (SIGALRM));
@@ -6600,11 +6612,21 @@
   for (i = 0; i < KBD_BUFFER_SIZE; i++)
     EVENT_INIT (buf[i]);
 
-  if (read_socket_hook)
-    /* No need for FIONREAD or fcntl; just say don't wait.  */
-    nread = (*read_socket_hook) (buf, KBD_BUFFER_SIZE, expected);
-
-  if (!nread && tty_list)
+  {
+    struct display *d;
+
+    for (d = display_list; d; d = d->next_display)
+      {
+        if (d->read_socket_hook)
+          /* No need for FIONREAD or fcntl; just say don't wait.  */
+          nread = (*d->read_socket_hook) (buf, KBD_BUFFER_SIZE, expected);
+        
+        if (nread > 0)
+          break;
+      }
+  }
+
+  if (nread <= 0 && tty_list)
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
 	 the kbd_buffer can really hold.  That may prevent loss
@@ -10426,6 +10448,11 @@
      (interrupt, flow, meta, quit)
      Lisp_Object interrupt, flow, meta, quit;
 {
+  /* XXX This function needs to be revised for multi-device support.
+     Currently it compiles fine, but its semantics are wrong.  It sets
+     global parameters (e.g. interrupt_input) based on only the
+     current frame's device. */
+  
   if (!NILP (quit)
       && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
     error ("set-input-mode: QUIT must be an ASCII character");
@@ -10442,7 +10469,7 @@
 
 #ifdef SIGIO
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
-  if (read_socket_hook)
+  if (FRAME_DISPLAY (SELECTED_FRAME ())->read_socket_hook)
     {
       /* When using X, don't give the user a real choice,
 	 because we haven't implemented the mechanisms to support it.  */
--- a/src/keymap.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/keymap.c	Mon Jan 05 05:54:35 2004 +0000
@@ -27,6 +27,7 @@
 #include "buffer.h"
 #include "charset.h"
 #include "keyboard.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "blockinput.h"
 #include "puresize.h"
--- a/src/lread.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/lread.c	Mon Jan 05 05:54:35 2004 +0000
@@ -33,6 +33,7 @@
 #include <epaths.h>
 #include "commands.h"
 #include "keyboard.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "coding.h"
 
--- a/src/print.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/print.c	Mon Jan 05 05:54:35 2004 +0000
@@ -30,7 +30,6 @@
 #include "window.h"
 #include "process.h"
 #include "dispextern.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "intervals.h"
 
--- a/src/process.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/process.c	Mon Jan 05 05:54:35 2004 +0000
@@ -126,11 +126,11 @@
 #include "charset.h"
 #include "coding.h"
 #include "process.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "commands.h"
 #include "keyboard.h"
-#include "frame.h"
 #include "blockinput.h"
 #include "dispextern.h"
 #include "composite.h"
--- a/src/scroll.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/scroll.c	Mon Jan 05 05:54:35 2004 +0000
@@ -23,7 +23,6 @@
 #include <stdio.h>
 #include <string.h>
 #include "lisp.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "dispextern.h"
 #include "keyboard.h"
--- a/src/sysdep.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/sysdep.c	Mon Jan 05 05:54:35 2004 +0000
@@ -272,11 +272,6 @@
   if (noninteractive)
     return;
 
-  /* Discarding input is not safe when the input could contain
-     replies from the X server.  So don't do it.  */
-  if (read_socket_hook)
-    return;
-
 #ifdef VMS
   end_kbd_input ();
   SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
@@ -322,7 +317,7 @@
 void
 stuff_char (char c)
 {
-  if (read_socket_hook)
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
     return;
 
 /* Should perhaps error if in batch mode */
@@ -961,13 +956,17 @@
 }
 
 #ifdef FASYNC		/* F_SETFL does not imply existence of FASYNC */
-/* XXX Uhm, this FASYNC is not used anymore here. */
+/* XXX Uhm, FASYNC is not used anymore here. */
 
 void
 request_sigio ()
 {
+  /* XXX read_socket_hook is not global anymore.  Is blocking SIGIO
+     bad under X? */
+#if 0
   if (read_socket_hook)
     return;
+#endif
 
 #ifdef SIGWINCH
   sigunblock (sigmask (SIGWINCH));
@@ -979,10 +978,14 @@
 
 void
 unrequest_sigio (void)
-{
+{ 
+  /* XXX read_socket_hook is not global anymore.  Is blocking SIGIO
+     bad under X? */
+#if 0
   if (read_socket_hook)
     return;
-
+#endif
+  
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
@@ -1388,15 +1391,18 @@
 #endif /* VMS */
 
 #ifdef BSD_PGRPS
+#if 0
+  /* read_socket_hook is not global anymore.  I think doing this
+     unconditionally will not cause any problems. */
   if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+#endif
     narrow_foreground_group (fileno (TTY_INPUT (tty_out)));
 #endif
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the initialization code below.  */
-  /* XXX This need to be revised for X+tty session support. */
-  if (tty_out->input != stdin || (!read_socket_hook && EQ (Vwindow_system, Qnil)))
+  if (tty_out->input != stdin || EQ (Vwindow_system, Qnil))
 #endif
     {
       if (! tty_out->old_tty)
@@ -1642,7 +1648,7 @@
 #ifndef F_SETOWN_BUG
 #ifdef F_GETOWN		/* F_SETFL does not imply existence of F_GETOWN */
   if (interrupt_input
-      && ! read_socket_hook && EQ (Vwindow_system, Qnil))
+      && (tty_out->input != stdin || EQ (Vwindow_system, Qnil)))
     {
       old_fcntl_owner[fileno (TTY_INPUT (tty_out))] =
         fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
--- a/src/term.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/term.c	Mon Jan 05 05:54:35 2004 +0000
@@ -29,7 +29,6 @@
 #include <sys/file.h>
 
 #include "lisp.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "charset.h"
@@ -72,9 +71,9 @@
 static void tty_show_cursor P_ ((struct tty_display_info *));
 static void tty_hide_cursor P_ ((struct tty_display_info *));
 
-void delete_tty P_ ((struct tty_display_info *));
-static void delete_tty_1 P_ ((struct tty_display_info *));
-
+void delete_tty P_ ((struct display *));
+void create_tty_output P_ ((struct frame *));
+void delete_tty_output P_ ((struct frame *));
 
 #define OUTPUT(tty, a)                                          \
   emacs_tputs ((tty), a,                                        \
@@ -103,8 +102,10 @@
 /* Functions to call after a tty was deleted. */
 Lisp_Object Vdelete_tty_after_functions;
 
-/* Terminal characteristics that higher levels want to look at. */
-
+/* Chain of all displays currently in use. */
+struct display *display_list;
+
+/* Chain of all tty device parameters. */
 struct tty_display_info *tty_list;
 
 /* Nonzero means no need to redraw the entire frame on resuming a
@@ -115,133 +116,6 @@
 
 Lisp_Object Qframe_tty_name, Qframe_tty_type;
 
-/* Hook functions that you can set to snap out the functions in this file.
-   These are all extern'd in termhooks.h  */
-
-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 (*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 (*read_socket_hook) P_ ((struct input_event *, int, int));
-
-void (*frame_up_to_date_hook) P_ ((struct frame *));
-
-/* Return the current position of the mouse.
-
-   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.
-
-   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.
-
-   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
-   row of the character cell the mouse is over.
-
-   Set *time to the time the mouse was at the returned position.
-
-   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 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 (*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));
 
 
 /* Meaning of bits in no_color_video.  Each bit set means that the
@@ -270,10 +144,6 @@
 
 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).  */
 
@@ -323,8 +193,8 @@
 
       Vring_bell_function = function;
     }
-  else if (!FRAME_TERMCAP_P (f))
-    (*ring_bell_hook) ();
+  else if (FRAME_DISPLAY (f)->ring_bell_hook)
+    (*FRAME_DISPLAY (f)->ring_bell_hook) ();
   else {
     struct tty_display_info *tty = FRAME_TTY (f);
     OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell);
@@ -343,10 +213,10 @@
 set_terminal_modes ()
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->set_terminal_modes_hook)
+    (*FRAME_DISPLAY (f)->set_terminal_modes_hook) ();
+  else 
     tty_set_terminal_modes (FRAME_TTY (f));
-  else
-    (*set_terminal_modes_hook) ();
 }
 
 void tty_reset_terminal_modes (struct tty_display_info *tty)
@@ -366,10 +236,10 @@
 reset_terminal_modes ()
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->reset_terminal_modes_hook)
+    (*FRAME_DISPLAY (f)->reset_terminal_modes_hook) ();
+  else
     tty_reset_terminal_modes (FRAME_TTY (f));
-  else if (reset_terminal_modes_hook)
-    (*reset_terminal_modes_hook) ();
 }
 
 void
@@ -377,15 +247,17 @@
      struct frame *f;
 {
   updating_frame = f;
-  if (!FRAME_TERMCAP_P (f))
-    update_begin_hook (f);
+  if (FRAME_DISPLAY (f)->update_begin_hook)
+    (*FRAME_DISPLAY (f)->update_begin_hook) (f);
 }
 
 void
 update_end (f)
      struct frame *f;
 {
-  if (FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->update_end_hook)
+    (*FRAME_DISPLAY (f)->update_end_hook) (f);
+  else if (FRAME_TERMCAP_P (f))
     {
       struct tty_display_info *tty = FRAME_TTY (f);
       if (!XWINDOW (selected_window)->cursor_off_p)
@@ -393,8 +265,6 @@
       turn_off_insert (tty);
       background_highlight (tty);
     }
-  else
-    update_end_hook (f);
 
   updating_frame = NULL;
 }
@@ -404,15 +274,15 @@
      int size;
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->set_terminal_window_hook)
+    (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size);
+  else if (FRAME_TERMCAP_P (f))
     {
       struct tty_display_info *tty = FRAME_TTY (f);
       tty->specified_window = size ? size : FRAME_LINES (f);
       if (FRAME_SCROLL_REGION_OK (f))
 	set_scroll_region (0, tty->specified_window);
     }
-  else
-    set_terminal_window_hook (size);
 }
 
 void
@@ -545,9 +415,9 @@
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
 
-  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
+  if (FRAME_DISPLAY (f)->cursor_to_hook)
     {
-      (*cursor_to_hook) (vpos, hpos);
+      (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
       return;
     }
 
@@ -576,9 +446,9 @@
 {
   struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
   struct tty_display_info *tty;
-  if (! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->raw_cursor_to_hook)
     {
-      (*raw_cursor_to_hook) (row, col);
+      (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col);
       return;
     }
   tty = FRAME_TTY (f);
@@ -603,9 +473,9 @@
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
 
-  if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->clear_to_end_hook)
     {
-      (*clear_to_end_hook) ();
+      (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
       return;
     }
   tty = FRAME_TTY (f);
@@ -632,9 +502,9 @@
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty;
 
-  if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->clear_frame_hook)
     {
-      (*clear_frame_hook) ();
+      (*FRAME_DISPLAY (f)->clear_frame_hook) ();
       return;
     }
   tty = FRAME_TTY (f);
@@ -663,9 +533,9 @@
   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 (FRAME_DISPLAY (f)->clear_end_of_line_hook)
     {
-      (*clear_end_of_line_hook) (first_unused_hpos);
+      (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
       return;
     }
 
@@ -828,9 +698,9 @@
   unsigned char conversion_buffer[1024];
   int conversion_buffer_size = sizeof conversion_buffer;
 
-  if (write_glyphs_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->write_glyphs_hook)
     {
-      (*write_glyphs_hook) (string, len);
+      (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
       return;
     }
 
@@ -935,9 +805,9 @@
 
   f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->insert_glyphs_hook)
     {
-      (*insert_glyphs_hook) (start, len);
+      (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
       return;
     }
 
@@ -1024,9 +894,9 @@
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_display_info *tty = FRAME_TTY (f);
 
-  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->delete_glyphs_hook)
     {
-      (*delete_glyphs_hook) (n);
+      (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
       return;
     }
 
@@ -1061,9 +931,9 @@
      int vpos, n;
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f))
+  if (FRAME_DISPLAY (f)->ins_del_lines_hook)
     {
-      (*ins_del_lines_hook) (vpos, n);
+      (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n);
       return;
     }
   else
@@ -1948,7 +1818,12 @@
      (display)
      Lisp_Object display;
 {
-  struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
+  struct tty_display_info *tty;
+
+  if (! FRAMEP (display))
+    return Qnil;
+  
+  tty = FRAME_TTY (XFRAME (display));
   return tty->TN_max_colors > 0 ? Qt : Qnil;
 }
 
@@ -1959,7 +1834,12 @@
      (display)
      Lisp_Object display;
 {
-  struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
+  struct tty_display_info *tty;
+
+  if (! FRAMEP (display))
+    return Qnil;
+  
+  tty = FRAME_TTY (XFRAME (display));
   return make_number (tty->TN_max_colors);
 }
 
@@ -2102,17 +1982,18 @@
 
 
 
-struct tty_display_info *
-get_named_tty (name)
+static struct display *
+get_named_tty_display (name)
      char *name;
 {
-  struct tty_display_info *tty = tty_list;
-
-  while (tty) {
-    if ((tty->name == 0 && name == 0)
-        || (name && tty->name && !strcmp (tty->name, name)))
-      return tty;
-    tty = tty->next;
+  struct display *d;
+
+  for (d = display_list; d; d = d->next_display) {
+    if (d->type == output_termcap
+        && ((d->display_info.tty->name == 0 && name == 0)
+            || (name && d->display_info.tty->name
+                && !strcmp (d->display_info.tty->name, name))))
+      return d;
   };
 
   return 0;
@@ -2177,11 +2058,13 @@
 			    Initialization
  ***********************************************************************/
 
-struct tty_display_info *
-term_dummy_init (void)
+struct display *
+initial_term_init (void)
 {
-  if (initialized || tty_list)
-    error ("tty already initialized");
+  if (initialized || display_list || tty_list)
+    abort ();
+
+  display_list = create_display ();
 
   tty_list = xmalloc (sizeof (struct tty_display_info));
   bzero (tty_list, sizeof (struct tty_display_info));
@@ -2189,14 +2072,19 @@
   tty_list->input = stdin;
   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));
+#ifdef MULTI_KBOARD
   tty_list->kboard = initial_kboard;
-  return tty_list;
+#endif
+  
+  display_list->type = output_termcap;
+  display_list->display_info.tty = tty_list;
+  
+  return display_list;
 }
 
 
-struct tty_display_info *
-term_init (Lisp_Object frame, char *name, char *terminal_type)
+struct display *
+term_init (char *name, char *terminal_type)
 {
   char *area;
   char **address = &area;
@@ -2204,52 +2092,45 @@
   int buffer_size = 4096;
   register char *p;
   int status;
-  struct frame *f = XFRAME (frame);
   struct tty_display_info *tty;
-
-  tty = get_named_tty (name);
-  if (tty)
+  struct display *display;
+
+  display = get_named_tty_display (name);
+  if (display)
     {
+      tty = display->display_info.tty;
+
       /* Return the previously initialized terminal, except if it is
          the dummy terminal created for the initial frame. */
       if (tty->type)
-        return tty;
+        return display;
 
       /* Free up temporary structures. */
       if (tty->Wcm)
         xfree (tty->Wcm);
-      if (tty->display_method)
-        xfree (tty->display_method);
       if (tty->kboard != initial_kboard)
         abort ();
       tty->kboard = 0;
     }
   else
     {
+      display = create_display ();
       tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
       bzero (tty, sizeof (struct tty_display_info));
       tty->next = tty_list;
       tty_list = tty;
+
+      display->type = output_termcap;
+      display->display_info.tty = tty;
     }
 
   tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
   Wcm_clear (tty);
 
-  /* Each termcap frame has its own display method. */
-  tty->display_method = (struct display_method *) xmalloc (sizeof (struct display_method));
-  bzero (tty->display_method, 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;
-
-  /* Make sure the frame is live; if an error happens, it must be
-     deleted. */
-  f->output_method = output_termcap;
-  if (! f->output_data.tty)
-    abort ();
-  f->output_data.tty->display_info = tty;
+  display->rif = 0; /* ttys don't support window-based redisplay. */
+  display->delete_frame_hook = &delete_tty_output;
+  display->delete_display_hook = &delete_tty;
+  
   if (name)
     {
       int fd;
@@ -2257,7 +2138,7 @@
       fd = emacs_open (name, O_RDWR, 0);
       if (fd < 0)
         {
-          delete_tty (tty);
+          delete_tty (display);
           error ("Could not open file: %s", name);
         }
       file = fdopen (fd, "w+");
@@ -2283,29 +2164,29 @@
 
   area = (char *) xmalloc (2044);
 
-  FrameRows (tty) = FRAME_LINES (f);
-  FrameCols (tty) = FRAME_COLS (f);
-  tty->specified_window = FRAME_LINES (f);
-
-  tty->display_method->delete_in_insert_mode = 1;
+  FrameRows (tty) = FRAME_LINES (f); /* XXX */
+  FrameCols (tty) = FRAME_COLS (f);  /* XXX */
+  tty->specified_window = FRAME_LINES (f); /* XXX */
+
+  tty->display->delete_in_insert_mode = 1;
 
   UseTabs (tty) = 0;
-  FRAME_SCROLL_REGION_OK (f) = 0;
+  display->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.  */
-  FRAME_LINE_INS_DEL_OK (f) = 0;
-  FRAME_CHAR_INS_DEL_OK (f) = 1;
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 1;
 
   baud_rate = 19200;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
   TN_max_colors = 16;  /* Required to be non-zero for tty-display-color-p */
 
-  return tty;
+  return display;
 #else  /* not WINDOWSNT */
 
   Wcm_clear (tty);
@@ -2318,7 +2199,7 @@
       if (name)
         {
           xfree (buffer);
-          delete_tty (tty);
+          delete_tty (display);
           error ("Cannot open terminfo database file");
         }
       else
@@ -2327,7 +2208,7 @@
       if (name)
         {
           xfree (buffer);
-          delete_tty (tty);
+          delete_tty (display);
           error ("Cannot open termcap database file");
         }
       else
@@ -2340,7 +2221,7 @@
       if (name)
         {
           xfree (buffer);
-          delete_tty (tty);
+          delete_tty (display);
           error ("Terminal type %s is not defined", terminal_type);
         }
       else
@@ -2354,7 +2235,7 @@
       if (name)
         {
           xfree (buffer);
-          delete_tty (tty);
+          delete_tty (display);
           error ("Terminal type %s is not defined", terminal_type);
         }
       else
@@ -2478,9 +2359,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");
-  FRAME_MEMORY_BELOW_FRAME (f) = tgetflag ("db");
+  display->memory_below_frame = tgetflag ("db");
   tty->TF_hazeltine = tgetflag ("hz");
-  FRAME_MUST_WRITE_SPACES (f) = tgetflag ("in");
+  display->must_write_spaces = tgetflag ("in");
   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
   tty->TF_insmode_motion = tgetflag ("mi");
   tty->TF_standout_motion = tgetflag ("ms");
@@ -2506,7 +2387,7 @@
     {
       if (initialized)
         {
-          delete_tty (tty);
+          delete_tty (display);
           error ("Screen size %dx%d is too small",
                  FrameCols (tty), FrameRows (tty));
         }
@@ -2518,7 +2399,7 @@
     }
 
 #if 0  /* This is not used anywhere. */
-  tty->display_method->min_padding_speed = tgetnum ("pb");
+  tty->display->min_padding_speed = tgetnum ("pb");
 #endif
 
   TabWidth (tty) = tgetnum ("tw");
@@ -2596,7 +2477,7 @@
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      FRAME_MEMORY_BELOW_FRAME (f) = 1;
+      display->memory_below_frame = 1;
       tty->Wcm->cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
@@ -2623,7 +2504,7 @@
 	    tty->TS_set_window = "\033v%C %C %C %C ";
 	}
       /* Termcap entry often fails to have :in: flag */
-      FRAME_MUST_WRITE_SPACES (f) = 1;
+      display->must_write_spaces = 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);
@@ -2646,7 +2527,7 @@
   if (Wcm_init (tty) == -1)	/* can't do cursor motion */
     if (name)
       {
-        delete_tty (tty);
+        delete_tty (display);
         error ("Terminal type \"%s\" is not powerful enough to run Emacs",
                terminal_type);
       }
@@ -2683,7 +2564,7 @@
     {
       if (name)
         {
-          delete_tty (tty);
+          delete_tty (display);
           error ("The frame size has not been specified");
         }
       else
@@ -2700,36 +2581,35 @@
 
   UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
 
-  FRAME_SCROLL_REGION_OK (f)
+  display->scroll_region_ok
     = (tty->Wcm->cm_abs
        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
-  FRAME_LINE_INS_DEL_OK (f)
+  display->line_ins_del_ok
     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
         && (tty->TS_del_line || tty->TS_del_multi_lines))
-       || (FRAME_SCROLL_REGION_OK (f)
+       || (display->scroll_region_ok
            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
-  FRAME_CHAR_INS_DEL_OK (f)
+  display->char_ins_del_ok
     = ((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));
 
-  FRAME_FAST_CLEAR_END_OF_LINE (f) = tty->TS_clr_line != 0;
+  display->fast_clear_end_of_line = tty->TS_clr_line != 0;
 
   init_baud_rate (fileno (TTY_INPUT (tty)));
-  if (read_socket_hook)		/* Baudrate is somewhat
-                                   meaningless in this case */
+
+  /* XXX This condition sounds bogus. */
+  if (display->read_socket_hook) /* Baudrate is somewhat
+                                             meaningless in this case */
     baud_rate = 9600;
 
-  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;
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 0;
 #endif
 
 #ifdef MULTI_KBOARD
@@ -2748,13 +2628,10 @@
   /* 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);
 
-  return tty;
+  return display;
 #endif /* not WINDOWSNT */
 }
 
@@ -2781,7 +2658,7 @@
   (tty)
      Lisp_Object tty;
 {
-  struct tty_display_info *t;
+  struct display *d;
   char *name = 0;
 
   CHECK_STRING (tty);
@@ -2793,29 +2670,35 @@
       name[SBYTES (tty)] = 0;
     }
 
-  t = get_named_tty (name);
-
-  if (! t)
-    error ("No such tty device: %s", name);
-
-  delete_tty (t);
+  d = get_named_tty_display (name);
+
+  if (! d)
+    error ("No such terminal device: %s", name);
+
+  delete_tty (d);
 }
 
 static int deleting_tty = 0;
 
 void
-delete_tty (struct tty_display_info *tty)
+delete_tty (struct display *display)
 {
+  struct tty_display_info *tty;
   Lisp_Object tail, frame;
   char *tty_name;
   
   if (deleting_tty)
     /* We get a recursive call when we delete the last frame on this
-       tty. */
+       display. */
     return;
 
   deleting_tty = 1;
 
+  if (display->type != output_termcap)
+    abort ();
+
+  tty = display->display_info.tty;
+  
   if (tty == tty_list)
     tty_list = tty->next;
   else
@@ -2842,6 +2725,8 @@
         }
     }
 
+  delete_display (display);
+
   reset_sys_modes (tty);
 
   tty_name = tty->name;
@@ -2865,9 +2750,6 @@
   if (tty->Wcm)
     xfree (tty->Wcm);
 
-  if (tty->display_method)
-    xfree (tty->display_method);
-
 #ifdef MULTI_KBOARD
   if (tty->kboard && --tty->kboard->reference_count > 0)
     abort ();
@@ -2895,6 +2777,34 @@
     }
 }
 
+
+
+/* Initialize the tty-dependent part of frame F.  The frame must
+   already have its display initialized. */
+void
+create_tty_output (struct frame *f)
+{
+  if (! FRAME_TERMCAP_P (f))
+    abort ();
+
+  struct tty_output *t = xmalloc (sizeof (struct tty_output));
+  bzero (t, sizeof (struct tty_output));
+
+  t->display_info = FRAME_DISPLAY (f)->display_info.tty;
+
+  f->output_data.tty = t;
+}
+
+/* Delete the tty-dependent part of frame F. */
+void
+delete_tty_output (struct frame *f)
+{
+  if (! FRAME_TERMCAP_P (f))
+    abort ();
+
+  xfree (f->output_data.tty);
+}
+
 
 
 
@@ -2912,6 +2822,35 @@
     }
 }
 
+
+
+/* Create a new display object and add it to the display list. */
+struct display *
+create_display (void)
+{
+  struct display *dev = (struct display *) xmalloc (sizeof (struct display));
+  
+  bzero (dev, sizeof (struct display));
+  dev->next_display = display_list;
+  display_list = dev;
+
+  return dev;
+}
+
+/* Remove a display from the display list and free its memory. */
+void
+delete_display (struct display *dev)
+{
+  struct display **dp;
+  for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
+    if (! *dp)
+      abort ();
+  *dp = dev->next_display;
+
+  bzero (dev, sizeof (struct display));
+  xfree (dev);
+}
+
 
 
 void
@@ -2951,11 +2890,6 @@
 
   Fprovide (intern ("multi-tty"), Qnil);
 
-  /* Initialize the display method template. */
-  
-  /* Termcap-based displays don't support window-based redisplay. */
-  tty_display_method_template.rif = 0;
-
 }
 
 
--- a/src/termchar.h	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/termchar.h	Mon Jan 05 05:54:35 2004 +0000
@@ -179,10 +179,6 @@
   /* 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;
-
 #ifdef MULTI_KBOARD
   /* The terminal's keyboard object. */
   struct kboard *kboard;
@@ -195,7 +191,7 @@
 
 #define FRAME_TTY(f)                            \
   ((f)->output_method == output_termcap         \
-   ? (f)->output_data.tty->display_info         \
+   ? (f)->display->display_info.tty             \
    : (abort(), (struct tty_display_info *) 0))
 
 #define CURTTY() FRAME_TTY (SELECTED_FRAME())
--- a/src/termhooks.h	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/termhooks.h	Mon Jan 05 05:54:35 2004 +0000
@@ -1,5 +1,4 @@
-/* Hooks by which low level terminal operations
-   can be made to call other routines.
+/* Parameters and display hooks for output devices
    Copyright (C) 1985,86,93,94,2003  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -30,75 +29,6 @@
 #define P_(X) ()
 #endif
 
-/* Device-local parameters. */
-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)
-
-#define FRAME_RIF(f) ((f)->display_method->rif)
-
-/* Text display hooks.  */
-
-extern void (*cursor_to_hook) P_ ((int vpos, int hpos));
-extern void (*raw_cursor_to_hook) P_ ((int, int));
-
-extern void (*clear_to_end_hook) P_ ((void));
-extern void (*clear_frame_hook) P_ ((void));
-extern void (*clear_end_of_line_hook) P_ ((int));
-
-extern void (*ins_del_lines_hook) P_ ((int, int));
-
-extern void (*insert_glyphs_hook) P_ ((struct glyph *s, int n));
-extern void (*write_glyphs_hook) P_ ((struct glyph *s, int n));
-extern void (*delete_glyphs_hook) P_ ((int));
-
-extern void (*ring_bell_hook) P_ ((void));
-
-extern void (*reset_terminal_modes_hook) P_ ((void));
-extern void (*set_terminal_modes_hook) P_ ((void));
-extern void (*update_begin_hook) P_ ((struct frame *));
-extern void (*update_end_hook) P_ ((struct frame *));
-extern void (*set_terminal_window_hook) P_ ((int));
-
-
-
-/* Multi-frame and mouse support hooks.  */
 
 enum scroll_bar_part {
   scroll_bar_above_handle,
@@ -112,125 +42,6 @@
   scroll_bar_move_ratio
 };
 
-/* Return the current position of the mouse.
-
-   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.
-
-   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.
-
-   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
-   row of the character cell the mouse is over.
-
-   Set *time to the time the mouse was at the returned position.
-
-   This should clear mouse_moved until the next motion
-   event arrives.  */
-extern void (*mouse_position_hook) P_ ((struct frame **f, int,
-					Lisp_Object *bar_window,
-					enum scroll_bar_part *part,
-					Lisp_Object *x,
-					Lisp_Object *y,
-					unsigned long *time));
-
-/* The window system handling code should set this if the mouse has
-   moved since the last call to the mouse_position_hook.  Calling that
-   hook should clear this.  */
-extern int mouse_moved;
-
-/* When a frame's focus redirection is changed, this hook tells the
-   window system code to re-decide where to put the highlight.  Under
-   X, this means that Emacs lies about where the focus is.  */
-extern void (*frame_rehighlight_hook) P_ ((struct frame *));
-
-/* 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.  */
-extern void (*frame_raise_lower_hook) P_ ((struct frame *f, int raise));
-
-
-/* Scroll bar hooks.  */
-
-/* The representation of scroll bars is determined by the code which
-   implements them, except for one thing: they must be represented by
-   lisp objects.  This allows us to place references to them in
-   Lisp_Windows without worrying about those references becoming
-   dangling references when the scroll bar is destroyed.
-
-   The window-system-independent portion of Emacs just refers to
-   scroll bars via their windows, and never looks inside the scroll bar
-   representation; it always uses hook functions to do all the
-   scroll bar manipulation it needs.
-
-   The `vertical_scroll_bar' field of a Lisp_Window refers to that
-   window's scroll bar, or is nil if the window doesn't have a
-   scroll bar.
-
-   The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame
-   are free for use by the scroll bar implementation in any way it sees
-   fit.  They are marked by the garbage collector.  */
-
-
-/* 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.  */
-extern 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 judgement.
-
-   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.  */
-extern void (*condemn_scroll_bars_hook) P_ ((struct frame *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.  */
-extern 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.  */
-extern void (*judge_scroll_bars_hook) P_ ((struct frame *FRAME));
-
 
 /* Input queue declarations and hooks.  */
 
@@ -413,13 +224,6 @@
 
 #define EVENT_INIT(event) bzero (&(event), sizeof (struct input_event))
 
-/* Called to read input events.  */
-extern int (*read_socket_hook) P_ ((struct input_event *, int, int));
-
-/* Called when a frame's display becomes entirely up to date.  */
-extern void (*frame_up_to_date_hook) P_ ((struct frame *));
-
-
 /* Bits in the modifiers member of the input_event structure.
    Note that reorder_modifiers assumes that the bits are in canonical
    order.
@@ -471,5 +275,258 @@
 
 #endif /* CONSP */
 
+
+/* Display-local parameters. */
+struct display
+{
+  /* Chain of all displays. */
+  struct display *next_display;
+
+  /* The number of frames that are on this display. */
+  int reference_count;
+  
+  /* The type of the display. */
+  enum output_method type;
+
+  /* Display-type dependent data shared amongst all frames on this display. */
+  union display_info
+  {
+    struct tty_display_info *tty;     /* termchar.h */
+    struct x_display_info *x;         /* xterm.h */
+  } display_info;
+
+
+  /* Terminal characteristics. */
+  /* XXX Are these really used on non-termcap displays? */
+  
+  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 device (0 for tty
+     devices). */
+  struct redisplay_interface *rif;
+
+  /* Frame-based redisplay interface. */
+  
+  /* Text display hooks.  */
+
+  void (*cursor_to_hook) P_ ((int vpos, int hpos));
+  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 (*insert_glyphs_hook) P_ ((struct glyph *s, int n));
+  void (*write_glyphs_hook) P_ ((struct glyph *s, int n));
+  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));
+
+  /* Multi-frame and mouse support hooks.  */
+
+  /* Return the current position of the mouse.
+
+     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.
+  
+     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.
+
+     Otherwise, set *bar_window to Qnil, and *x and *y to the column and
+     row of the character cell the mouse is over.
+
+     Set *time to the time the mouse was at the returned position.
+     
+     This should clear mouse_moved until the next motion
+     event arrives.  */
+  void (*mouse_position_hook) P_ ((struct frame **f, int,
+                                   Lisp_Object *bar_window,
+                                   enum scroll_bar_part *part,
+                                   Lisp_Object *x,
+                                   Lisp_Object *y,
+                                   unsigned long *time));
+
+  /* The window system handling code should set this if the mouse has
+     moved since the last call to the mouse_position_hook.  Calling that
+     hook should clear this.  */
+  int mouse_moved;
+
+  /* When a frame's focus redirection is changed, this hook tells the
+     window system code to re-decide where to put the highlight.  Under
+     X, this means that Emacs lies about where the focus is.  */
+  void (*frame_rehighlight_hook) P_ ((struct frame *));
+
+  /* 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_ ((struct frame *f, int raise));
+
+  
+  /* Scroll bar hooks.  */
+
+  /* The representation of scroll bars is determined by the code which
+     implements them, except for one thing: they must be represented by
+     lisp objects.  This allows us to place references to them in
+     Lisp_Windows without worrying about those references becoming
+     dangling references when the scroll bar is destroyed.
+     
+     The window-system-independent portion of Emacs just refers to
+     scroll bars via their windows, and never looks inside the scroll bar
+     representation; it always uses hook functions to do all the
+     scroll bar manipulation it needs.
+     
+     The `vertical_scroll_bar' field of a Lisp_Window refers to that
+     window's scroll bar, or is nil if the window doesn't have a
+     scroll bar.
+     
+     The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame
+     are free for use by the scroll bar implementation in any way it sees
+     fit.  They are marked by the garbage collector.  */
+  
+  
+  /* 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 judgement.
+     
+     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_ ((struct frame *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_ ((struct frame *FRAME));
+
+
+  /* Called to read input events.  */
+  int (*read_socket_hook) P_ ((struct input_event *, int, int));
+
+  /* Called when a frame's display becomes entirely up to date.  */
+  void (*frame_up_to_date_hook) P_ ((struct frame *));
+
+
+  /* Called to delete the device-specific portions of a frame that is
+     on this display. */
+  void (*delete_frame_hook) P_ ((struct frame *));
+
+  /* Called after the last frame on this display is deleted.
+     If this is NULL, then the generic delete_frame() is called.
+
+     Fdelete_frame ensures that there are no live frames on the
+     display when it calls this hook. */
+  void (*delete_display_hook) P_ ((struct display *));
+
+};
+
+
+/* Chain of all displays currently in use. */
+extern struct display *display_list;
+
+#define FRAME_MUST_WRITE_SPACES(f) ((f)->display->must_write_spaces)
+#define FRAME_FAST_CLEAR_END_OF_LINE(f) ((f)->display->fast_clear_end_of_line)
+#define FRAME_LINE_INS_DEL_OK(f) ((f)->display->line_ins_del_ok)
+#define FRAME_CHAR_INS_DEL_OK(f) ((f)->display->char_ins_del_ok)
+#define FRAME_SCROLL_REGION_OK(f) ((f)->display->scroll_region_ok)
+#define FRAME_SCROLL_REGION_COST(f) ((f)->display->scroll_region_cost)
+#define FRAME_MEMORY_BELOW_FRAME(f) ((f)->display->memory_below_frame)
+
+#define FRAME_RIF(f) ((f)->display->rif)
+
+#define FRAME_DISPLAY(f) ((f)->display)
+
+/* FRAME_WINDOW_P tests whether the frame is a window, and is
+   defined to be the predicate for the window system being used.  */
+
+#ifdef HAVE_X_WINDOWS
+#define FRAME_WINDOW_P(f) FRAME_X_P (f)
+#endif
+#ifdef HAVE_NTGUI
+#define FRAME_WINDOW_P(f) FRAME_W32_P (f)
+#endif
+#ifdef MAC_OS
+#define FRAME_WINDOW_P(f) FRAME_MAC_P (f)
+#endif
+#ifndef FRAME_WINDOW_P
+#define FRAME_WINDOW_P(f) (0)
+#endif
+
+
+extern struct display *create_display P_ ((void));
+extern void delete_display P_ ((struct display *));
+
 /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d
    (do not change this comment) */
--- a/src/window.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/window.c	Mon Jan 05 05:54:35 2004 +0000
@@ -31,7 +31,6 @@
 #include "window.h"
 #include "commands.h"
 #include "indent.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "disptab.h"
 #include "dispextern.h"
--- a/src/xdisp.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xdisp.c	Mon Jan 05 05:54:35 2004 +0000
@@ -173,7 +173,6 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "dispextern.h"
 #include "buffer.h"
@@ -6458,8 +6457,8 @@
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-	(*frame_up_to_date_hook) (f);
+      if (FRAME_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+	(*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -6544,8 +6543,8 @@
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-	(*frame_up_to_date_hook) (f);
+      if (FRAME_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+	(*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -7616,11 +7615,11 @@
 /* The terminal frame is used as the first Emacs frame on the Mac OS.  */
 #ifndef MAC_OS8
 #ifdef HAVE_WINDOW_SYSTEM
-  /* When Emacs starts, selected_frame may be a visible terminal
-     frame, even if we run under a window system.  If we let this
-     through, a message would be displayed on the terminal.  */
-  if (!FRAME_WINDOW_P (XFRAME (selected_frame))
-      && !NILP (Vwindow_system))
+  /* When Emacs starts, selected_frame may be the initial terminal
+     frame.  If we let this through, a message would be displayed on
+     the terminal.  */
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+      && FRAME_TTY (XFRAME (selected_frame))->type == NULL)
     return 0;
 #endif /* HAVE_WINDOW_SYSTEM */
 #endif
@@ -10100,16 +10099,16 @@
 
 	      /* Mark all the scroll bars to be removed; we'll redeem
 		 the ones we want when we redisplay their windows.  */
-	      if (condemn_scroll_bars_hook)
-		condemn_scroll_bars_hook (f);
+	      if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+		FRAME_DISPLAY (f)->condemn_scroll_bars_hook (f);
 
 	      if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
 		redisplay_windows (FRAME_ROOT_WINDOW (f));
 
 	      /* Any scroll bars which redisplay_windows should have
 		 nuked should now go away.  */
-	      if (judge_scroll_bars_hook)
-		judge_scroll_bars_hook (f);
+	      if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+		FRAME_DISPLAY (f)->judge_scroll_bars_hook (f);
 
 	      /* If fonts changed, display again.  */
 	      /* ??? rms: I suspect it is a mistake to jump all the way
@@ -10161,8 +10160,8 @@
 	    {
 	      struct frame *f = updated[i];
 	      mark_window_display_accurate (f->root_window, 1);
-	      if (frame_up_to_date_hook)
-		frame_up_to_date_hook (f);
+	      if (FRAME_DISPLAY (f)->frame_up_to_date_hook)
+		FRAME_DISPLAY (f)->frame_up_to_date_hook (f);
 	    }
 	}
     }
@@ -10251,8 +10250,8 @@
 	  last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
 	  last_arrow_string = Voverlay_arrow_string;
 
-	  if (frame_up_to_date_hook != 0)
-	    frame_up_to_date_hook (sf);
+	  if (FRAME_DISPLAY (sf)->frame_up_to_date_hook != 0)
+	    FRAME_DISPLAY (sf)->frame_up_to_date_hook (sf);
 	}
 
       update_mode_lines = 0;
@@ -11390,7 +11389,9 @@
     start = end = whole = 0;
 
   /* Indicate what this scroll bar ought to be displaying now.  */
-  set_vertical_scroll_bar_hook (w, end - start, whole, start);
+  if (FRAME_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+    (*FRAME_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+      (w, end - start, whole, start);
 }
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
@@ -12091,7 +12092,8 @@
 
       /* Note that we actually used the scroll bar attached to this
 	 window, so it shouldn't be deleted at the end of redisplay.  */
-      redeem_scroll_bar_hook (w);
+      if (FRAME_DISPLAY (f)->redeem_scroll_bar_hook)
+        (*FRAME_DISPLAY (f)->redeem_scroll_bar_hook) (w);
     }
 
   /* Restore current_buffer and value of point in it.  */
--- a/src/xfaces.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xfaces.c	Mon Jan 05 05:54:35 2004 +0000
@@ -200,6 +200,7 @@
 #include "charset.h"
 #include "keyboard.h"
 #include "frame.h"
+#include "termhooks.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
@@ -5407,7 +5408,7 @@
   /* See if the capabilities we selected above are supported, with the
      given colors.  */
   if (test_caps != 0 &&
-      ! tty_capable_p (FRAME_TTY (SELECTED_FRAME ()), test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
+      ! tty_capable_p (FRAME_TTY (f), test_caps, fg_tty_color.pixel, bg_tty_color.pixel))
     return Qnil;
 
 
--- a/src/xfns.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xfns.c	Mon Jan 05 05:54:35 2004 +0000
@@ -48,7 +48,6 @@
 #include "systime.h"
 #include "termhooks.h"
 #include "atimer.h"
-#include "systty.h"
 #include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS
@@ -1762,10 +1761,10 @@
   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
     {
       /* Remove all scroll bars because they have wrong colors.  */
-      if (condemn_scroll_bars_hook)
-	(*condemn_scroll_bars_hook) (f);
-      if (judge_scroll_bars_hook)
-	(*judge_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+	(*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+	(*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
 
       update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
       redraw_frame (f);
@@ -1811,10 +1810,10 @@
   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
     {
       /* Remove all scroll bars because they have wrong colors.  */
-      if (condemn_scroll_bars_hook)
-	(*condemn_scroll_bars_hook) (f);
-      if (judge_scroll_bars_hook)
-	(*judge_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+	(*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+	(*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
 
       update_face_from_frame_parameter (f, Qscroll_bar_background, value);
       redraw_frame (f);
@@ -3245,7 +3244,9 @@
   /* Note that X Windows does support scroll bars.  */
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
 
-  f->display_method = &x_display_method;
+  f->display = dpyinfo->frame_display;
+  f->display->reference_count++;
+
   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));
@@ -9981,7 +9982,8 @@
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
-  f->display_method = &x_display_method;
+  f->display = dpyinfo->frame_display;
+  f->display->reference_count++;
 
   /* By setting the output method, we're essentially saying that
      the frame is live, as per FRAME_LIVE_P.  If we get a signal
--- a/src/xmenu.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xmenu.c	Mon Jan 05 05:54:35 2004 +0000
@@ -39,10 +39,10 @@
 #include <stdio.h>
 
 #include "lisp.h"
-#include "termhooks.h"
 #include "keyboard.h"
 #include "keymap.h"
 #include "frame.h"
+#include "termhooks.h"
 #include "window.h"
 #include "blockinput.h"
 #include "buffer.h"
--- a/src/xselect.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xselect.c	Mon Jan 05 05:54:35 2004 +0000
@@ -302,13 +302,20 @@
      Lisp_Object selection_name, selection_value;
 {
   struct frame *sf = SELECTED_FRAME ();
-  Window selecting_window = FRAME_X_WINDOW (sf);
-  Display *display = FRAME_X_DISPLAY (sf);
+  Window selecting_window;
+  Display *display;
   Time time = last_event_timestamp;
   Atom selection_atom;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+  struct x_display_info *dpyinfo;
   int count;
 
+  if (! FRAME_X_P (sf))
+    return;
+
+  selecting_window = FRAME_X_WINDOW (sf);
+  display = FRAME_X_DISPLAY (sf);
+  dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+  
   CHECK_SYMBOL (selection_name);
   selection_atom = symbol_to_x_atom (dpyinfo, display, selection_name);
 
@@ -572,7 +579,8 @@
 
   FOR_EACH_FRAME (list, frame)
     {
-      if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+      if (FRAME_X_P (XFRAME (frame))
+          && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
 	return frame;
     }
 
@@ -1219,17 +1227,26 @@
      Lisp_Object selection_symbol, target_type;
 {
   struct frame *sf = SELECTED_FRAME ();
-  Window requestor_window = FRAME_X_WINDOW (sf);
-  Display *display = FRAME_X_DISPLAY (sf);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+  Window requestor_window;
+  Display *display;
+  struct x_display_info *dpyinfo;
   Time requestor_time = last_event_timestamp;
-  Atom target_property = dpyinfo->Xatom_EMACS_TMP;
-  Atom selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
+  Atom target_property;
+  Atom selection_atom;
   Atom type_atom;
   int secs, usecs;
   int count;
   Lisp_Object frame;
 
+  if (! FRAME_X_P (sf))
+    return Qnil;
+
+  requestor_window = FRAME_X_WINDOW (sf);
+  display = FRAME_X_DISPLAY (sf);
+  dpyinfo = FRAME_X_DISPLAY_INFO (sf);
+  target_property = dpyinfo->Xatom_EMACS_TMP;
+  selection_atom = symbol_to_x_atom (dpyinfo, display, selection_symbol);
+
   if (CONSP (target_type))
     type_atom = symbol_to_x_atom (dpyinfo, display, XCAR (target_type));
   else
@@ -1989,6 +2006,9 @@
   struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
+  if (! FRAME_X_P (sf))
+    return Qnil;
+
   display = FRAME_X_DISPLAY (sf);
   dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   CHECK_SYMBOL (selection);
@@ -2152,6 +2172,10 @@
   struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
+
+  if (! FRAME_X_P (sf))
+    return Qnil;
+
   display = FRAME_X_DISPLAY (sf);
   dpyinfo = FRAME_X_DISPLAY_INFO (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
@@ -2193,6 +2217,10 @@
   struct frame *sf = SELECTED_FRAME ();
 
   check_x ();
+
+  if (! FRAME_X_P (sf))
+    return Qnil;
+
   display = FRAME_X_DISPLAY (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
 
@@ -2249,8 +2277,12 @@
   Atom props[8];
   Display *display;
   struct frame *sf = SELECTED_FRAME ();
+  
+  check_x ();
 
-  check_x ();
+  if (! FRAME_X_P (sf))
+    return Qnil;
+
   display = FRAME_X_DISPLAY (sf);
   window = RootWindow (display, 0); /* Cut buffers are on screen 0 */
   CHECK_NUMBER (n);
--- a/src/xsmfns.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xsmfns.c	Mon Jan 05 05:54:35 2004 +0000
@@ -48,6 +48,7 @@
 #include "systime.h"
 #include "sysselect.h"
 #include "lisp.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "xterm.h"
--- a/src/xterm.c	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xterm.c	Mon Jan 05 05:54:35 2004 +0000
@@ -54,7 +54,6 @@
 #include <sys/ioctl.h>
 #endif /* ! defined (BSD_SYSTEM) */
 
-#include "systty.h"
 #include "systime.h"
 
 #ifndef INCLUDED_FCNTL
@@ -184,10 +183,6 @@
 
 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.  */
 
@@ -329,6 +324,8 @@
 void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
+struct display *x_create_frame_display P_ ((struct x_display_info *));
+void x_delete_frame_display P_ ((struct display *));
 void x_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
@@ -10232,6 +10229,7 @@
 {
   int connection;
   Display *dpy;
+  struct display *display;
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
 
@@ -10366,6 +10364,8 @@
   dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
   bzero (dpyinfo, sizeof *dpyinfo);
 
+  display = x_create_frame_display (dpyinfo);
+
 #ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
@@ -10716,7 +10716,18 @@
      struct x_display_info *dpyinfo;
 {
   int i;
-
+  
+  {
+    /* Delete the generic struct display for this X display. */
+    struct display *d;
+    for (d = display_list; d; d = d->next_display)
+      if (d->type == output_x_window && d->display_info.x != dpyinfo)
+        {
+          delete_display (d);
+          break;
+        }
+  }
+    
   delete_keyboard_wait_descriptor (dpyinfo->connection);
 
   /* Discard this display from x_display_name_list and x_display_list.
@@ -10846,35 +10857,63 @@
     x_shift_glyphs_for_insert
   };
 
+
+/* This function is called when the last frame on a display is deleted. */
+void
+x_delete_frame_display (struct display *display)
+{
+  /* We don't do anything, the connection to the X server must remain
+     open. */
+}
+
+
+struct display *
+x_create_frame_display (struct x_display_info *dpyinfo)
+{
+  struct display *display;
+  
+  display = create_display ();
+
+  display->type = output_x_window;
+  display->display_info.x = dpyinfo;
+  dpyinfo->frame_display = display;
+  
+  display->clear_frame_hook = x_clear_frame;
+  display->ins_del_lines_hook = x_ins_del_lines;
+  display->delete_glyphs_hook = x_delete_glyphs;
+  display->ring_bell_hook = XTring_bell;
+  display->reset_terminal_modes_hook = XTreset_terminal_modes;
+  display->set_terminal_modes_hook = XTset_terminal_modes;
+  display->update_begin_hook = x_update_begin;
+  display->update_end_hook = x_update_end;
+  display->set_terminal_window_hook = XTset_terminal_window;
+  display->read_socket_hook = XTread_socket;
+  display->frame_up_to_date_hook = XTframe_up_to_date;
+  display->mouse_position_hook = XTmouse_position;
+  display->frame_rehighlight_hook = XTframe_rehighlight;
+  display->frame_raise_lower_hook = XTframe_raise_lower;
+  display->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+  display->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+  display->redeem_scroll_bar_hook = XTredeem_scroll_bar;
+  display->judge_scroll_bars_hook = XTjudge_scroll_bars;
+
+  display->delete_frame_hook = x_destroy_window;
+  display->delete_display_hook = x_delete_frame_display;
+  
+  display->rif = &x_redisplay_interface;
+  display->scroll_region_ok = 1; /* We'll scroll partial frames. */
+  display->char_ins_del_ok = 1;
+  display->line_ins_del_ok = 1;        /* We'll just blt 'em. */
+  display->fast_clear_end_of_line = 1; /* X does this well. */
+  display->memory_below_frame = 0; /* We don't remember what scrolls
+                                        off the bottom. */
+
+  return display;
+}
+
 void
 x_initialize ()
 {
-  clear_frame_hook = x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  delete_glyphs_hook = x_delete_glyphs;
-  ring_bell_hook = XTring_bell;
-  reset_terminal_modes_hook = XTreset_terminal_modes;
-  set_terminal_modes_hook = XTset_terminal_modes;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-  set_terminal_window_hook = XTset_terminal_window;
-  read_socket_hook = XTread_socket;
-  frame_up_to_date_hook = XTframe_up_to_date;
-  mouse_position_hook = XTmouse_position;
-  frame_rehighlight_hook = XTframe_rehighlight;
-  frame_raise_lower_hook = XTframe_raise_lower;
-  set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
-  condemn_scroll_bars_hook = XTcondemn_scroll_bars;
-  redeem_scroll_bar_hook = XTredeem_scroll_bar;
-  judge_scroll_bars_hook = XTjudge_scroll_bars;
-
-  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	Sat Jan 03 19:06:35 2004 +0000
+++ b/src/xterm.h	Mon Jan 05 05:54:35 2004 +0000
@@ -134,9 +134,6 @@
   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.  */
 
@@ -385,6 +382,9 @@
       X_WMTYPE_A,
       X_WMTYPE_B
     } wm_type;
+
+  /* The generic display parameters corresponding to this X display. */
+  struct display *frame_display;
 };
 
 #ifdef HAVE_X_I18N