]> code.delx.au - gnu-emacs/commitdiff
Merged in changes from CVS HEAD
authorKaroly Lorentey <lorentey@elte.hu>
Sat, 10 Apr 2004 23:06:09 +0000 (23:06 +0000)
committerKaroly Lorentey <lorentey@elte.hu>
Sat, 10 Apr 2004 23:06:09 +0000 (23:06 +0000)
Patches applied:

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-193
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-194
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-195
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-196
   Remove RCS keywords

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-197
   Stupid CVS keyword changes

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-198
   Update from CVS

 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-199
   Update from CVS

git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-134

96 files changed:
README.multi-tty [new file with mode: 0644]
etc/ONEWS
etc/TODO
etc/cs-survival.tex
etc/fr-survival.tex
etc/pl-refcard.tex
etc/sk-survival.tex
etc/survival.dvi [new file with mode: 0644]
etc/survival.log [new file with mode: 0644]
etc/termcap.src
info/.gitignore [deleted file]
info/COPYING [deleted file]
info/dir [deleted file]
leim/CXTERM-DIC/4Corner.tit
leim/CXTERM-DIC/CCDOSPY.tit
leim/CXTERM-DIC/Punct.tit
leim/CXTERM-DIC/QJ.tit
leim/CXTERM-DIC/SW.tit
leim/CXTERM-DIC/TONEPY.tit
lib-src/b2m.pl
lib-src/emacsclient.c
lib-src/rcs2log
lib-src/vcdiff
lisp/Makefile.in
lisp/allout.el
lisp/bindings.el
lisp/cus-face.el
lisp/faces.el
lisp/frame.el
lisp/loadup.el
lisp/server.el
lisp/simple.el
lisp/startup.el
lisp/talk.el
lisp/term/x-win.el
lisp/term/xterm.el
lisp/vc-cvs.el
lisp/vc-hooks.el
lisp/vc-rcs.el
lisp/vc-sccs.el
lisp/vc.el
lisp/version.el
lisp/x-dnd.el
lispintro/mkinstalldirs
lispref/mkinstalldirs
man/eshell.texi
man/mh-e.texi
man/pcl-cvs.texi
man/speedbar.texi
man/woman.texi
mkinstalldirs
nt/.arch-inventory [new file with mode: 0644]
src/.gdbinit
src/Makefile.in
src/alloc.c
src/cm.c
src/cm.h
src/config.in
src/dispextern.h
src/dispnew.c
src/emacs.c
src/fontset.c
src/frame.c
src/frame.h
src/fringe.c
src/indent.c
src/intervals.h
src/keyboard.c
src/keyboard.h
src/keymap.c
src/lisp.h
src/lread.c
src/macterm.c
src/macterm.h
src/minibuf.c
src/msdos.c
src/process.c
src/scroll.c
src/sysdep.c
src/syssignal.h
src/term.c
src/termchar.h
src/termhooks.h
src/termopts.h
src/w32term.c
src/w32term.h
src/window.c
src/window.h
src/xdisp.c
src/xfaces.c
src/xfns.c
src/xmenu.c
src/xselect.c
src/xsmfns.c
src/xterm.c
src/xterm.h

diff --git a/README.multi-tty b/README.multi-tty
new file mode 100644 (file)
index 0000000..6410360
--- /dev/null
@@ -0,0 +1,749 @@
+                       -*- coding: utf-8; mode: text; -*-
+GOAL
+----
+
+The goal of this branch is to implement support for opening multiple,
+different tty devices and simultaneous X and tty frames from a single
+Emacs session.
+
+Some use cases:
+Emacs is notoriously slow at startup, so most people use another
+editor or emacsclient for quick editing jobs from the console.
+Unfortunately, emacsclient was very awkward to use, because it did not
+support opening a new Emacs frame on the current virtual console.
+Now, with multi-tty support, it can do that.  (Emacsclient starts up
+faster than vi!)
+
+Some Gnus users (including me) run Gnus in an X frame in its own Emacs
+instance, which they typically leave running for weeks.  It would be
+nice if they could connect to this instance from a remote ssh session
+and check their messages without opening a remote X frame or resorting
+to gnus-slave.
+
+WHO IS DOING IT
+---------------
+
+I'm Károly Lőrentey.  My address: lorentey@elte.hu.
+
+Comments, bug reports, suggestions and patches are welcome!
+
+Retrieving the latest version of the branch:
+
+       tla register-archive lorentey@elte.hu--2004 http://lorentey.web.elte.hu/arch/2004/
+       tla get lorentey@elte.hu--2004/emacs--multi-tty <directory>
+
+(I use a recent arch development snapshot, but any of the released
+versions of arch will do fine, I think.)
+
+If you don't have arch, the branch has a homepage from which you can
+download conventional patches against Emacs CVS HEAD:
+
+       http://lorentey.web.elte.hu/project/emacs.html
+
+If you want to be notified of new revisions, sign up to the
+multi-tty@listbox.elte.hu mailing list by visiting the
+below homepage and following its instructions.
+
+       https://listbox.elte.hu/mailman/listinfo/multi-tty
+
+Please note that the multi-tty mailing list is read-only, and is
+reserved for automatic commit messages.  Discussion about the branch
+and bug reports should be sent directly to me (lorentey@elte.hu), or
+to the emacs-devel@gnu.org mailing list.  (I hope to merge my branch
+into CVS HEAD reasonably soon, so I don't want to set up an elaborate
+development infrastructure for the multi-tty branch.)
+
+STATUS
+------
+
+The branch is now very stable and almost full-featured. I hope the
+major problems were fixed.  (It still needs testing on other
+architectures, though.)  Both multiple tty device support and
+simultaneous X and tty frame support works fine.  Emacsclient has been
+extended to support opening new tty and X frames.  It has been changed
+open new Emacs frames by default.
+
+Please let me know if you find any bugs in this branch.
+
+HOW TO COMPILE AND TEST
+-----------------------
+
+To try out the multi-tty branch, compile and run the multi-tty branch
+with the following commands:
+
+       mkdir +build
+       cd +build
+       ../configure <your favourite options>
+       make bootstrap
+       src/emacs -nw           # You can also try without -nw
+       M-x server-start
+
+and then (from a shell prompt on another terminal) start emacsclient
+with
+       lib-src/emacsclient /optional/file/names...
+or
+       lib-src/emacsclient -t /optional/file/names...
+
+You'll hopefully have two fully working, independent frames on
+separate terminals. The new frame is closed automatically when you
+have finished editing the specified files (C-x #), but delete-frame
+(C-x 5 0) also works.  Of course, you can create frames on more than
+two tty devices.
+
+Creating new frames on the same tty with C-x 5 2 works, and they
+behave the same way as in previous Emacs versions.  If you exit emacs,
+all terminals should be restored to their previous states.
+
+This is work in progress, and probably full of bugs.  You should
+always run emacs from gdb, so that you'll have a live instance to
+debug if something goes wrong.  Please send me your bug reports.
+
+I think the best way to use the new Emacs is to have it running inside
+a disconnected GNU screen session, and always use emacsclient for
+normal work.  This way not a single keystroke of your work will be
+lost if the display device that you are using crashes, or the network
+connection times out, or whatever.  As long as the server that runs
+your Emacs remains up, all your buffers remain exactly as they were
+before the crash, and you can continue working as if nothing had
+happened.  (I had an extremely unstable X server for some time while I
+was developing these patches, and running Emacs this way has saved me
+a number of M-x recover-session invocations.)
+
+(I am thinking about introducing a --daemon option to get rid of the
+above screen dependency.)
+
+Problems:
+
+       * Mac, Windows and DOS support is broken, probably doesn't
+         even compile -- this will be solved later.
+
+       * Only tested on my GNU/Linux box and on Solaris 8.
+
+NEWS
+----
+
+For the NEWS file:
+
+** Support for multiple terminal devices has been added.
+
+*** You can specify a terminal device (`tty' parameter) and a terminal
+    type (`tty-type' parameter) to `make-terminal-frame'.
+
+*** You can test for the presence of multiple terminal support by
+    testing for the `multi-tty' feature.
+
+*** Emacsclient has been extended to support opening a new terminal
+    frame. Its behaviour has been changed to open a new Emacs frame by
+    default.  Use the -c option to get the old behavior of opening
+    files in the currently selected Emacs frame.
+
+*** A make-frame-on-tty function has been added to make it easier to
+    create frames on new terminals.
+
+*** New functions: frame-tty-name, frame-tty-type for accessing
+    terminal parameters, and delete-tty for closing the terminal
+    device.
+
+*** talk.el has been extended for multiple tty support.
+
+
+** Support for simultaneous graphical and terminal frames has been
+   added.
+
+*** The function `make-frame-on-display' now works during a terminal
+    session, and `make-frame-on-tty' works during a graphical session.
+
+*** The `window-system' variable has been made frame-local.
+
+*** The new `initial-window-system' variable contains the
+    `window-system' value for the first frame.
+
+THANKS
+------
+
+The following is an (incomplete) list of people who have contributed
+to the project by testing, bug reports, and suggestions.  Thanks!
+
+Robert J. Chassell <bob at rattlesnake dot com>
+Romain Francoise <romain at orebokech dot com>
+Ami Fischman <ami at fischman dot org>
+Istvan Marko <mi-mtty ar kismala dot com>
+Dan Nicolaescu <dann at ics dot uci dot edu>
+Gergely Nagy <algernon at debian dot org>
+Mark Plaksin <happy at mcplaksin dot org>
+Francisco Borges <borges at let dot rug dot nl>
+
+Richard Stallman was kind enough to review my patches.
+
+CHANGELOG
+---------
+
+See arch logs.
+
+THINGS TO DO
+------------
+
+** Emacs assumes that all terminal frames have the same locale
+   settings as Emacs itself.  This may lead to bogus results in a
+   multi-locale setup. (E.g., while logging in from a remote client
+   with a different locale.)
+
+** The single-keyboard mode of MULTI_KBOARD is extremely confusing
+   sometimes; Emacs does not respond to stimuli from other keyboards.
+   At least a beep or a message would be important, if the single-mode
+   is still required to prevent interference.  (Reported by Dan
+   Nicolaescu.)  (Update: selecting a region with the mouse enables
+   single_kboard under X.  This is very confusing.)
+
+** Change Lisp code not to (getenv "TERM"); use the `tty-type' frame
+   parameter or the frame-tty-type function instead.
+   (M-x tags-search "TERM" helps with this.)
+
+** The terminal customization files in term/*.el tend to change global
+   parameters, which may confuse Emacs with multiple displays.  Change
+   them to tweak only frame-local settings, if possible.
+
+** Dan Nicolaescu suggests that -nw should be added as an alias for -t
+   in emacsclient.  Good idea.  (Alas, implementing this is not
+   trivial, getopt_long does not seem to support two-letter ``short''
+   options.)
+
+** Mark Plaksin suggests that emacsclient should accept the same
+   X-related command-line arguments as Emacs.  Most of the X-related
+   argument-handling is done in Lisp, so this should be quite easy to
+   implement.
+
+** Gergely Nagy suggests that C-x # should only kill the current
+   frame, not any other emacsclient frame that may have the same file
+   opened for editing.  I think I agree with him.
+
+** Make `struct display' accessible to Lisp programs.  Accessor functions:
+
+       (displayp OBJECT):  Returns t if OBJECT is a display.
+
+       (display-list):  Returns list of currently active displays.
+
+       (selected-display):  Returns the display object of the selected frame.
+
+       (frame-display FRAME):  Returns the display object of FRAME.
+
+       (display-frames DISPLAY):  Returns a list of frames on DISPLAY.
+
+       (display-type DISPLAY):  Returns the type of DISPLAY, as a
+               symbol.  (See `framep'.)
+
+       (display-device DISPLAY): Returns the name of the device that
+               DISPLAY uses, as a string.  (E.g: "/dev/pts/16", or
+               ":0.0")
+
+       etc.
+
+   See next issue why this is necessary.
+
+** The following needs to be supported:
+
+       $ emacsclient -t
+               C-z
+       $ bg
+       $ emacsclient -t
+               (This fails now.)
+
+   The cleanest way to solve this is to allow multiple displays on the
+   same terminal device; each new emacsclient process should create
+   its own display.  As displays are currently identified by their
+   device names, this is not possible until struct display becomes
+   accessible as a Lisp-level object.
+
+** Add an elaborate mechanism for display-local variables.  (There are
+   already a few of these; search for `terminal-local' in the Elisp
+   manual.)
+
+** Very strange bug: visible-bell does not work on secondary
+   terminals in xterm and konsole.  The screen does flicker a bit,
+   but it's so quick it isn't noticable.
+
+** Clean up the frame-local variable system.  I think it's ugly and
+   error-prone.  But maybe I just haven't yet fully understood it.
+
+** Move baud_rate to struct display.
+
+** Implement support for starting an interactive Emacs session without
+   an initial frame.  (The user would connect to it and open frames
+   later, with emacsclient.)
+
+** Fix Mac support (I can't do this myself).  Note that the current
+   state of Mac-specific source files in the multi-tty tree are not
+   useful; before starting work on Mac support, revert to pristine,
+   pre-multi-tty versions.
+
+** Fix W32 support (I can't do this myself).  Note that the current
+   state of W32-specific source files in the multi-tty tree are not
+   useful; before starting work on W32 support, revert to pristine,
+   pre-multi-tty versions.
+
+** Fix DOS support (I can't do this myself).  Note that the current
+   state of DOS-specific source files in the multi-tty tree are not
+   useful; before starting work on DOS support, revert to pristine,
+   pre-multi-tty versions.
+
+** 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
+   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.)
+
+** Maybe standard-display-table should be display-local.
+
+DIARY OF CHANGES
+----------------
+
+(ex-TODO items with explanations.)
+
+-- Introduce a new struct for terminal devices.
+
+   (Done, see struct tty_output.  The list of members is not yet
+   complete.)
+
+-- Change the bootstrap procedure to initialize tty_list.
+
+   (Done, but needs review.)
+
+-- Change make-terminal-frame to support specifying another tty.
+
+   (Done, new frame parameters: `tty' and `tty-type'.)
+
+-- Implement support for reading from multiple terminals.
+
+   (Done, read_avail_input tries to read from each terminal, until one
+   succeeds.  MULTI_KBOARD is not used.  Secondary terminals don't send
+   SIGIO!)
+
+   (Update: They do, now.)
+
+   (Update2: After enabling X, they don't.)
+
+-- other-frame should cycle through the frames on the `current'
+   terminal only.
+
+   (Done, by trivially modifiying next_frame and prev_frame.)
+
+-- Support different terminal sizes.
+
+   (Done, no problem.)
+
+-- Make sure terminal resizes are handled gracefully.  (Could be
+   problematic.)
+
+   (Done.  We don't get automatic SIGWINCH for additional ttys,
+   though.)
+
+-- Extend emacsclient to automatically open a new tty when it connects
+   to Emacs.
+
+   (Done.  It's an ugly hack, needs more work.)
+
+-- Redisplay must refresh the topmost frame on *all* terminals, not
+   just the initial terminal.
+
+   (Done, but introduced an ugly redisplay problems.  Ugh.)
+
+-- Fix redisplay problems.
+
+   (Done; it turned out that the entire Wcm structure must be moved
+   inside tty_output.  Why didn't I catch this earlier?)
+
+-- Provide a way for emacsclient to tell Emacs that the tty has been
+   resized.
+
+   (Done, simply forward the SIGWINCH signal.)
+
+-- Each keypress should automatically select the frame corresponding
+   to the terminal that it was coming from.  This means that Emacs
+   must know from which terminal the last keyboard event came from.
+
+   (Done, it was quite simple, the input event system already
+   supported multiple frames.)
+
+-- Fix SIGIO issue with secondary terminals.
+
+   (Done, emacsclient signals Emacs after writing to the proxy pseudo
+   terminal.  Note that this means that multi-tty does not work with
+   raw ttys!)
+
+   (Update: This is bullshit.  There is a read_input_waiting function,
+   extend that somehow.)
+
+   (Update of update: The first update was not right either, extending
+   read_input_waiting was not necessary.  Secondary ttys do seem to
+   send signals on input.)
+
+   (Update^3: Not any more.)
+
+-- Make make-terminal-frame look up the `tty' and `tty-type' frame
+   parameters from the currently selected terminal before the global
+   default.
+
+   (Done.)
+
+-- Put all cached terminal escape sequences into struct tty_output.
+   Currently, they are still stored in global variables, so we don't
+   really support multiple terminal types.
+
+   (Done.  It was not fun.)
+
+-- Implement sane error handling after initialization.  (Currently
+   emacs exits if you specify a bad terminal type.)  The helpful error
+   messages must still be provided when Emacs starts.
+
+   (Done.)
+
+-- Implement terminal deletion, i.e., deleting local frames, closing
+   the tty device and restoring its previous state without exiting
+   Emacs.
+
+   (Done, but at the moment only called when an error happens during
+   initialization.  There is a memory corruption error around this
+   somewhere.)  (Update: now it is fully enabled.)
+
+-- Implement automatic deletion of terminals when the last frame on
+   that terminal is closed.
+
+   (Done.)
+
+-- Restore tty screen after closing the terminal.
+
+   (Done, we do the same as Emacs 21.2 for all terminals.)
+
+-- 'TERM=dumb src/emacs' does not restore the terminal state.
+
+   (Done.)
+
+-- C-g should work on secondary terminals.
+
+   (Done, but the binding is not configurable.)
+
+-- Deal with SIGHUP in Emacs and in emacsclient.  (After this, the
+   server-frames may be removed from server.el.)
+
+   (Done, nothing to do.  It seems that Emacs does not receive SIGHUP
+   from secondary ttys, which is actually a good thing.)  (Update: I
+   think it would be a bad idea to remove server-frames.)
+
+-- Change emacsclient/server.el to support the -t argument better,
+   i.e. automatically close the socket when the frame is closed.
+
+   (Seems to be working OK.)
+
+-- Fix mysterious memory corruption error with tty deletion.  To
+   trigger it, try the following shell command:
+
+       while true; do TERM=no-such-terminal-definition emacsclient -h; done
+
+   Emacs usually dumps core after a few dozen iterations.  (The bug
+   seems to be related to the xfreeing or bzeroing of
+   tty_output.Wcm.  Maybe there are outside references to struct Wcm?
+   Why were these vars collected into a struct before multi-tty
+   support?)
+
+   (Done.  Whew.  It turned out that the problem had nothing to do
+   with hypothetical external references to Wcm, or any other
+   tty_output component; it was simply that delete_tty closed the
+   filehandles of secondary ttys twice, resulting in fclose doubly
+   freeing memory.  Utterly trivial matter.  I love the C's memory
+   management, it puts hair on your chest.)
+
+-- Support raw secondary terminals.  (Note that SIGIO works only on
+   the controlling terminal.) Hint: extend read_input_waiting for
+   multiple ttys and hopefully this will be fixed.
+
+   (Done, it seems to have been working already for some time.  It
+   seems F_SETOWN does work, after all.  Not sure what made it fail
+   earlier, but it seems to be fixed (there were several changes
+   around request_sigio, maybe one of them did it).
+   read_input_waiting is only used in sys_select, don't change
+   it.)  (Update: After adding X support, it's broken again.)
+
+-- Find out why does Emacs abort when it wants to close its
+   controlling tty.  Hint: chan_process[] array.  Hey, maybe
+   noninterrupt-IO would work, too?  Update: no, there is no process
+   for stdin/out.
+
+   (Done.  Added add/delete_keyboard_wait_descriptor to
+   term_init/delete_tty.  The hint was right, in a way.)
+
+-- Issue with SIGIO: it needs to be disabled during redisplay.  See if
+   fcntl kernel behaviour could be emulated by emacsclient.
+
+   (Done.  Simply disabled the SIGIO emulation hack in emacsclient.)
+   (Update: it was added back.)
+
+-- server.el: There are issues with saving files in buffers of closed
+   clients.  Try editing a file with emacsclient -f, and (without
+   saving it) do a delete-frame.  The frame is closed without
+   question, and a surprising confirmation prompt appears in another
+   frame.
+
+   (Done.  delete-frame now asks for confirmation if it still has
+   pending buffers, and modified buffers don't seem to be deleted.)
+
+-- emacsclient.el, server.el: Handle eval or file open errors when
+   doing -t.
+
+   (Done.)
+
+-- Make parts of struct tty_output accessible from Lisp.  The device
+   name and the type is sufficient.
+
+   (Done, see frame-tty-name and frame-tty-type.)
+
+-- Export delete_tty to the Lisp environment, for emacsclient.
+
+   (Done, see delete-tty.)
+
+-- Get rid of the accessor macros in termchar.h, or define macros for
+   all members.
+
+   (Done.)
+
+-- Move device-specific parameters (like costs) commonly used by
+   device backends to a common, device-dependent structure.
+
+   (Done.  See struct display_method in termhooks.h.)
+
+-- Fix X support.
+
+   (Done.  Well, it seems to be working.)
+
+-- Allow simultaneous X and tty frames.  (Handling input could be
+   tricky.  Or maybe not.)
+
+   (Done.  Allowed, that is.  It is currently extremely unstable, to
+   the point of being unusable.  The rif variable causes constant
+   core dumps.  Handling input is indeed tricky.)
+
+-- Rewrite multi-tty input in terms of MULTI_KBOARD.
+
+   (Done.  In fact, there was no need to rewrite anything, I just
+   added a kboard member to tty_display_info, and initialized the
+   frame's kboard from there.)
+
+-- Fix rif issue with X-tty combo sessions.  IMHO the best thing to do
+   is to get rid of that global variable (and use the value value in
+   display_method, which is guaranteed to be correct).
+
+   (Done, did exactly that.  Core dumps during combo sessions became
+   much rarer.  In fact, I have not yet met a single one.)
+
+-- Add multi-tty support to talk.el.
+
+   (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.)
+
+-- If there are no frames on its controlling terminal, Emacs should
+   exit if the uses presses C-c there.
+
+   (Done, as far as possible.  See the SIGTERM comment in
+   interrupt_signal on why this seems to be impossible to solve this
+   in general.)
+
+-- During an X session, Emacs seems to read from stdin.  Also, Emacs
+   fails to start without a controlling tty.
+
+   (Fixed by replacing the troublesome termcap display with a dummy
+   bootstrap display during bootstrap.
+
+-- Do tty output through struct display, like graphical display
+   backends.
+
+   (Done.)
+
+-- 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.
+
+   (Done, broking interactive temacs.)
+
+-- The command `emacsclient -t -e '(delete-frame)'' fails to exit.
+
+   (Fixed.)
+
+-- frame-creation-function should always create a frame that is on the
+   same display as the selected frame.  Maybe frame-creation-function
+   should simply be removed and make-frame changed to do the right
+   thing.
+
+   (Done, with a nice hack.  frame-creation-function is now frame-local.)
+
+-- Fix C-g on raw ttys.
+
+   (Done.  I disabled the interrupt/quit keys on all secondary
+   terminals, so Emacs sees C-g as normal input.  This looks like an
+   overkill, because emacsclient has extra code to pass SIGINT to
+   Emacs, so C-g should remain the interrupt/quit key on emacsclient
+   frames.  See the next entry why implementing this distinction would
+   be a bad idea.)
+
+-- Make sure C-g goes to the right frame with ttys.  This is hard, as
+   SIGINT doesn't have a tty parameter. :-(
+
+   (Done, the previous change fixes this as a pleasant side effect.)
+
+-- I have seen a case when Emacs with multiple ttys fell into a loop
+   eating 100% of CPU time.  Strace showed this loop:
+
+       getpid()                                = 30284
+       kill(30284, SIGIO)                      = 0
+       --- SIGIO (I/O possible) @ 0 (0) ---
+       ioctl(6, FIONREAD, [0])                 = -1 EIO (Input/output error)
+       ioctl(5, FIONREAD, [0])                 = -1 EIO (Input/output error)
+       ioctl(0, FIONREAD, [0])                 = 0
+       sigreturn()                             = ? (mask now [])
+       gettimeofday({1072842297, 747760}, NULL) = 0
+       gettimeofday({1072842297, 747806}, NULL) = 0
+       select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0})
+       select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0})
+       gettimeofday({1072842297, 748245}, NULL) = 0
+
+   I have seen something similar with a single X frame, but have not
+   been able to reproduce it for debugging.
+
+   Update: This may have been caused by checking for nread != 0
+   instead of nread > 0 after calling read_socket_hook in
+   read_avail_input.
+
+   (Fixed.  This was caused by unconditionally including stdin in
+   input_wait_mask in init_process.  The select call in
+   wait_reading_process_input always returned immediately, indicating
+   that there is pending input from stdin, which nobody read.
+
+   Note that the above strace output seems to be an unrelated but
+   similar bug.  I think that is now fixed.)
+
+-- Exiting Emacs while there are emacsclient frames doesn't restore the
+   ttys to their default states.
+
+   (This seems to be fixed by some previous change.)
+
+-- Allow opening an X session after -nw.
+
+   (Done.)
+
+-- Fix color handling during tty+X 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 currently done in lisp (term/tty-colors.el).)
+   (Update: hm, colors seem to work fine if I start emacs with -nw and
+   then create an X frame.  Maybe it's just a small buglet somewhere.)
+
+   (Seems to be fixed.  The problem was in startup.el, it did not
+   initialize tty colors when the initial window system was
+   graphical.)
+
+-- emacs -nw --eval '(y-or-n-p "Foobar")' segfaults.  (Reported by
+   Romain Francoise)
+
+   (Fixed, there was a keyboard initialization problem.)
+
+-- Fix interactive use of temacs.  There are face-related SEGVs, most
+   likely because of changes in realize_default_face, realize_face.
+
+   (Fixed.)
+
+-- Don't exit Emacs when the last X connection fails during a
+   multi-display session.
+
+   (Fixed.)
+
+
+-- Dan Nicolaescu noticed that starting emacsclient on the same
+   terminal device that is the controlling tty of the Emacs process
+   gives unexpected results.
+
+   (Fixed.)
+
+-- Istvan Marko reported that Emacs hang on ttys if it was started
+   from a shell script.
+
+   (Fixed.  There was a bug in the multi-tty version of
+   narrow_foreground_group.  tcsetpgrp blocks if it is called from a
+   process that is not in the same process group as the tty.)
+
+-- 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).  Update: the face problems are caused by
+   bugs in term.el, not in multi-tty.  The lockup is caused by
+   single_kboard mode, and is not easily solvable.  The best thing to
+   do is to simply refuse to create a tty frame of type `eterm'.
+
+   (Fixed, changed emacsclient to check for TERM=eterm.  The face
+   complaints seem to be caused by bugs in term.el; they are not
+   related to multi-tty.)
+
+-- Find out the best way to support suspending Emacs with multiple
+   ttys.  My guess: disable it on the controlling tty, but from other
+   ttys pass it on to emacsclient somehow.  (It is (I hope) trivial to
+   extend emacsclient to handle suspend/resume.  A `kill -STOP' almost
+   works right now.)
+
+   (Done.  I needed to play with signal handling and the server
+   protocol a bit to make emacsclient behave as a normal UNIX program
+   wrt foreground/background process groups.)
+
+-- There is a flicker during the startup of `emacs -nw'; it's as if
+   the terminal is initialized, reset and then initialialized again.
+   Debug this.  (Hint: narrow_foreground_group is called twice during
+   startup.)
+
+   (This is gone.)
+
+-- Robert Chassell has found serious copy-paste bugs with the
+   multi-tty branch.  There seem to be redisplay bugs while copying
+   from X to a terminal frame.  Copying accented characters do not
+   work for me.
+
+   (Patch-124 should fix this, by changing the interprogram-*-function
+   variables to be frame-local, as suggested by Mark Plaksin
+   (thanks!).  I think that the redisplay bugs are in fact not bugs,
+   but delays caused by single_kboard --> perhaps MULTI_KBOARD should
+   be removed.)
+
+
+
+;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
index e92965c89d94805326c9492c5e60c2cc9e2c0c66..9c58bdad072d78bfd0c22bdce2f9ccc737e11f94 100644 (file)
--- a/etc/ONEWS
+++ b/etc/ONEWS
@@ -1029,7 +1029,7 @@ your working file with the latest version from the master.
 *** RCS customization.
 
 There is a new variable vc-consult-headers.  If it is t (the default),
-VC searches for RCS headers in working files (like `$Id: ONEWS,v 1.8 2003/02/04 14:30:40 lektu Exp $') and
+VC searches for RCS headers in working files (like `$Id: ONEWS,v 1.9 2003/09/01 15:44:58 miles Exp $') and
 determines the state of the file from them, not from the master file.
 This is fast and more reliable when you use branches.  (The variable
 was already present in Emacs 19.29, but didn't get mentioned in the
index d6607a94d475fc5b8e00a41ec0d50b4fec733945..1249e57ac982e3e3be9110986ca991ebb0086025 100644 (file)
--- a/etc/TODO
+++ b/etc/TODO
@@ -129,7 +129,10 @@ Other features we would like:
 * Highlight rectangles (`mouse-track-rectangle-p' in XEmacs).  Already in CUA,
   but it's a valuable feature worth making more general.
 
-* Support simultaneous tty and X frames.
+* Support simultaneous tty and X frames.  [For a partial
+  implementation, see tla branch
+  lorentey@elte.hu--2004/emacs--multi-tty--0 at
+  http://lorentey.web.elte.hu/arch/2004]
 
 * Provide MIME support for Rmail using the Gnus MIME library.  [Maybe
   not now feasible, given Gnus maintenance decisions.  fx looked at
index 6cc551e8f001339c7736382cbb0ac99e777d4356..a4384de247badc55df95100d8505de147063ed6d 100644 (file)
@@ -2,8 +2,8 @@
 % Title:  GNU Emacs Survival Card
 % Author: Wlodek Bzyl <matwb@univ.gda.pl>
 %
-% $Revision: 1.2 $
-% $Date: 2003/02/04 14:30:41 $
+% $Revision: 1.3 $
+% $Date: 2003/09/01 15:44:59 $
 %
 %**start of header
 
index 9a0a83541c776bc04b2c39b8d34c1932bcc4eaa6..0ab7e91b9d7e2b89aa1a12beb3bd280c80817c68 100644 (file)
@@ -3,8 +3,8 @@
 % Title:  GNU Emacs Survival Card
 % Author: Wlodek Bzyl <matwb@univ.gda.pl>
 %
-% $Revision: 1.2 $
-% $Date: 2003/02/04 14:30:41 $
+% $Revision: 1.3 $
+% $Date: 2003/09/01 15:44:59 $
 %
 %**start of header
 
index 2763db21230c7a4aa3f294b13222bc56840585e1..78406eca927df49d7f5b5d12301e886dafbe5ce4 100644 (file)
@@ -1,7 +1,7 @@
 %&mex
 %=====================================================================
-% $Revision: 1.3 $
-% $Date: 2003/02/04 14:30:42 $
+% $Revision: 1.4 $
+% $Date: 2003/09/01 15:44:59 $
 %=====================================================================
 % Reference Card for GNU Emacs version 20 on Unix systems was
 % translated into Polish language by W{\l}odek Bzyl (matwb@univ.gda.pl)
index 5ea7f5a500e6564a11b17bab6463bd67da7b3302..acbef76750a4ef3b111b98b2aba3e86f785948fe 100644 (file)
@@ -2,8 +2,8 @@
 % Title:  GNU Emacs Survival Card
 % Author: Wlodek Bzyl <matwb@univ.gda.pl>
 %
-% $Revision: 1.2 $
-% $Date: 2003/02/04 14:30:42 $
+% $Revision: 1.3 $
+% $Date: 2003/09/01 15:44:59 $
 %
 %**start of header
 
diff --git a/etc/survival.dvi b/etc/survival.dvi
new file mode 100644 (file)
index 0000000..dc50ce7
Binary files /dev/null and b/etc/survival.dvi differ
diff --git a/etc/survival.log b/etc/survival.log
new file mode 100644 (file)
index 0000000..f8c7c91
--- /dev/null
@@ -0,0 +1,10 @@
+This is TeX, Version 3.14159 (Web2C 7.3.1) (format=tex 2000.12.11)  12 DEC 2000 10:16
+**survival
+(survival.tex
+\intercolumnskip=\dimen16
+\leftcolumn=\box16
+\defwidth=\dimen17
+\raggedstretch=\dimen18
+\raggedparfill=\skip18
+ [1] [2] )
+Output written on survival.dvi (2 pages, 11216 bytes).
index c982aececf3592abb926feb0f6a8b2c6278376a2..00d09f25dbd470405ebc6635843758f9e06fa86a 100644 (file)
@@ -10,7 +10,7 @@
 #
 #------------------------------------------------------------------------------
 #      Version 10.2.1
-#      $Date: 2002/04/20 07:38:53 $
+#      $Date: 2003/02/04 14:30:42 $
 #      terminfo syntax
 #
 #      Eric S. Raymond         (current maintainer)
diff --git a/info/.gitignore b/info/.gitignore
deleted file mode 100644 (file)
index 463f086..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-emacs
-emacs-[1-9]*
-emacs-mime
-ccmode
-ccmode-[1-9]*
-cl
-cl-[1-9]*
-dired-x
-ediff
-ediff-[1-9]*
-eshell
-forms
-gnus
-gnus-[1-9]*
-info
-message
-mh-e
-mh-e-[1-9]*
-reftex
-reftex-[1-9]*
-sc
-sc-[1-9]*
-vip
-vip-[1-9]*
-viper
-viper-[1-9]*
-widget
-ada-mode
-eudc
-autotype
-efaq
-efaq-[1-9]*
-idlwave
-idlwave-[1-9]*
-ebrowse
-pcl-cvs
-woman
-woman-[1-9]*
-speedbar
-elisp
-elisp-[1-9]*
-calc
-calc-[1-9]*
-eintr
-eintr-[1-9]*
-tramp
-tramp-[1-9]*
-ses
-smtpmail
diff --git a/info/COPYING b/info/COPYING
deleted file mode 100644 (file)
index d60c31a..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/info/dir b/info/dir
deleted file mode 100644 (file)
index 4af6f37..0000000
--- a/info/dir
+++ /dev/null
@@ -1,70 +0,0 @@
--*- Text -*-
-This is the file .../info/dir, which contains the topmost node of the
-Info hierarchy.  The first time you invoke Info you start off
-looking at that node, which is (dir)Top.
-\1f
-File: dir      Node: Top       This is the top of the INFO tree
-
-The Info Directory
-******************
-
-  The Info Directory is the top-level menu of major Info topics.
-  Type "d" in Info to return to the Info Directory.  Type "q" to exit Info.
-  Type "?" for a list of Info commands, or "h" to visit an Info tutorial.
-  Type "m" to choose a menu item--for instance,
-    "mEmacs<Return>" visits the Emacs manual.
-  In Emacs Info, you can click mouse button 2 on a menu item
-  or cross reference to follow it to its target.
-
-* Menu: Each line that starts with a * is a topic you can select with "m".
-  Every third topic has a red *.
-
-* Info: (info).                How to use the documentation browsing system.
-
-Emacs
-* Emacs: (emacs).      The extensible self-documenting text editor.
-* Emacs FAQ: (efaq).   Frequently Asked Questions about Emacs.
-* Emacs Lisp Introduction: (eintr).
-                       A simple introduction to Emacs Lisp programming.
-* Elisp: (elisp).      The Emacs Lisp Reference Manual.
-
-* CL: (cl).            Partial Common Lisp support for Emacs Lisp.
-* Dired-X: (dired-x).   Dired Extra Features.
-* Ediff: (ediff).      A visual interface for comparing and merging programs.
-* PCL-CVS: (pcl-cvs).  Emacs front-end to CVS.
-* Speedbar: (speedbar).        File/Tag summarizing utility.
-
-* Ada mode: (ada-mode). Emacs mode for editing Ada code.
-* CC mode: (ccmode).   Emacs mode for editing C, C++, Objective-C,
-                         Java, Pike, and IDL code.
-* Ebrowse: (ebrowse).  A C++ class browser for Emacs.
-* IDLWAVE: (idlwave).  Major mode and shell for IDL and WAVE/CL files.
-
-* Gnus: (gnus).                The news reader Gnus.
-* Message: (message).  Mail and news composition mode that goes with Gnus.
-* MH-E: (mh-e).                Emacs interface to the MH mail system.
-* MIME: (emacs-mime).   Emacs MIME de/composition library.
-* SC: (sc).            Supercite lets you cite parts of messages you're
-                         replying to, in flexible ways.
-* SMTP: (smtpmail).     Emacs library for sending mail via SMTP.
-
-* Autotype: (autotype). Convenient features for text that you enter frequently
-                          in Emacs.
-* Calc: (calc).        Advanced desk calculator and mathematical tool.
-* Eshell: (eshell).    A command shell implemented in Emacs Lisp.
-* EUDC: (eudc).                An Emacs client for directory servers (LDAP, PH).
-* Forms: (forms).      Emacs package for editing data bases
-                         by filling in forms.
-* RefTeX: (reftex).    Emacs support for LaTeX cross-references and citations.
-* SES: (ses).           Simple Emacs Spreadsheet
-* Tramp: (tramp).      Transparent Remote (file) Access, Multiple Protocol.
-                          Edit remote files via a remote shell (rsh,
-                          ssh, telnet).
-* Widget: (widget).     The "widget" package used by the Emacs Customization
-                          facility.
-* WoMan: (woman).       Browse UN*X Manual Pages "Wo (without) Man".
-
-* VIPER: (viper).       The newest Emacs VI-emulation mode.
-                          (also, A VI Plan for Emacs Rescue
-                           or the VI PERil.)
-* VIP: (vip).          An older VI-emulation for Emacs.
index 4c4a7a40531f8f784732a86fc49db73661a14978..127948bf7d24cf700129981982e481003601d0a8 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: 4Corner.tit,v 1.2 2001/03/06 13:29:34 handa Exp $
+# $Id: 4Corner.tit,v 1.3 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 2
index 7de50bc6972f60983a0c9c99b2113b0b8ce6be5b..d9367bd7b683811ebf261a71d2eff31f80c35a06 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: CCDOSPY.tit,v 1.1 1999/10/08 20:06:27 fx Exp $
+# $Id: CCDOSPY.tit,v 1.2 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 1
index 5ed6ca8a895ea743919d8458446653377765167e..d38b458db01e3c1ad2f6a68d19cb590716bdc90e 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Punct.tit,v 1.1 1999/10/08 20:06:50 fx Exp $
+# $Id: Punct.tit,v 1.2 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 1
index 70f94e8e7e1f056c5784e90a0573c65162c9df05..58f6c6594da660fae86930e8a0ab3f8185e54c1e 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: QJ.tit,v 1.1 1999/10/08 20:06:51 fx Exp $
+# $Id: QJ.tit,v 1.2 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 1
index 25e03c69f14d99f66e4226273f622baaa6ab003b..f3526daf1bc575a383b18f3caa945b68ea4cd5d7 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: SW.tit,v 1.1 1999/10/08 20:06:53 fx Exp $
+# $Id: SW.tit,v 1.2 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 1
index a6de2c0d9990bce19a2a916c3789a6b1805d381e..b854e82ebd6d68b817067e0d2ad7eb4ba997393e 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: TONEPY.tit,v 1.1 1999/10/08 20:06:56 fx Exp $
+# $Id: TONEPY.tit,v 1.2 2003/09/01 15:44:59 miles Exp $
 # HANZI input table for cxterm
 # To be used by cxterm, convert me to .cit format first
 # .cit version 1
index 38eb96e076ff679d9ffac16615edfb52586f46b5..ce547e0dd816e3af5d83479a0ab0ea91b31dc76e 100644 (file)
@@ -30,7 +30,7 @@ use Mail::Address;
 use Date::Parse;
 
 my($whoami) = basename $0;
-my($version) = '$Revision: 1.5 $';
+my($version) = '$Revision: 1.6 $';
 my($usage) = "Usage: $whoami [--help] [--version] [--[no]full-headers] [Babyl-file]
 \tBy default, full headers are printed.\n";
 
index c8b2596198f7772587fca579c2a5c33f825ac755..79642cbe47e30d100d3ecefb513518ab12726233 100644 (file)
@@ -41,6 +41,10 @@ Boston, MA 02111-1307, USA.  */
 # include <pwd.h>
 #endif /* not VMS */
 
+#include <signal.h>
+#include <errno.h>
+
+\f
 char *getenv (), *getwd ();
 char *getcwd ();
 
@@ -54,15 +58,27 @@ char *getcwd ();
 /* Name used to invoke this program.  */
 char *progname;
 
+/* The first argument to main. */
+int main_argc;
+
+/* The second argument to main. */
+char **main_argv;
+
 /* Nonzero means don't wait for a response from Emacs.  --no-wait.  */
 int nowait = 0;
 
 /* Nonzero means args are expressions to be evaluated.  --eval.  */
 int eval = 0;
 
+/* Nonzero means open a new graphical frame. */
+int window_system = 0;
+
 /* The display on which Emacs should work.  --display.  */
 char *display = NULL;
 
+/* Nonzero means open a new Emacs frame on the current terminal. */
+int tty = 0;
+
 /* If non-NULL, the name of an editor to fallback to if the server
    is not running.  --alternate-editor.   */
 const char * alternate_editor = NULL;
@@ -78,6 +94,8 @@ struct option longopts[] =
   { "eval",    no_argument,       NULL, 'e' },
   { "help",    no_argument,       NULL, 'H' },
   { "version", no_argument,       NULL, 'V' },
+  { "tty",     no_argument,       NULL, 't' },
+  { "current-frame", no_argument,  NULL, 'c' },
   { "alternate-editor", required_argument, NULL, 'a' },
   { "socket-name",     required_argument, NULL, 's' },
   { "display", required_argument, NULL, 'd' },
@@ -93,11 +111,19 @@ decode_options (argc, argv)
      char **argv;
 {
   alternate_editor = getenv ("ALTERNATE_EDITOR");
+  display = getenv ("DISPLAY");
+  if (display && strlen (display) == 0)
+    display = NULL;
+
+  if (display)
+    window_system = 1;
+  else
+    tty = 1;
 
   while (1)
     {
       int opt = getopt_long (argc, argv,
-                            "VHnea:s:d:", longopts, 0);
+                            "VHnea:s:d:tc", longopts, 0);
 
       if (opt == EOF)
        break;
@@ -134,6 +160,16 @@ decode_options (argc, argv)
          exit (0);
          break;
 
+        case 't':
+          tty = 1;
+          window_system = 0;
+          break;
+
+        case 'c':
+          window_system = 0;
+          tty = 0;
+          break;
+
        case 'H':
          print_help_and_exit ();
          break;
@@ -144,6 +180,11 @@ decode_options (argc, argv)
          break;
        }
     }
+
+  if (tty) {
+    nowait = 0;
+    display = 0;
+  }
 }
 
 void
@@ -157,6 +198,8 @@ Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
 The following OPTIONS are accepted:\n\
 -V, --version           Just print a version info and return\n\
 -H, --help              Print this usage information message\n\
+-t, --tty               Open a new Emacs frame on the current terminal\n\
+-c, --current-frame    Do not create a new frame; use the current Emacs frame\n\
 -n, --no-wait           Don't wait for the server to return\n\
 -e, --eval              Evaluate the FILE arguments as ELisp expressions\n\
 -d, --display=DISPLAY   Visit the file in the given display\n\
@@ -169,19 +212,21 @@ Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
   exit (0);
 }
 
-/* In NAME, insert a & before each &, each space, each newline, and
+/* In STR, insert a & before each &, each space, each newline, and
    any initial -.  Change spaces to underscores, too, so that the
-   return value never contains a space.  */
+   return value never contains a space.
+
+   Does not change the string.  Outputs the result to STREAM.  */
 
 void
-quote_file_name (name, stream)
-     char *name;
+quote_argument (str, stream)
+     char *str;
      FILE *stream;
 {
-  char *copy = (char *) malloc (strlen (name) * 2 + 1);
+  char *copy = (char *) malloc (strlen (str) * 2 + 1);
   char *p, *q;
 
-  p = name;
+  p = str;
   q = copy;
   while (*p)
     {
@@ -199,7 +244,7 @@ quote_file_name (name, stream)
        }
       else
        {
-         if (*p == '&' || (*p == '-' && p == name))
+         if (*p == '&' || (*p == '-' && p == str))
            *q++ = '&';
          *q++ = *p++;
        }
@@ -211,6 +256,41 @@ quote_file_name (name, stream)
   free (copy);
 }
 
+
+/* The inverse of quote_argument.  Removes quoting in string STR by
+   modifying the string in place.   Returns STR. */
+
+char *
+unquote_argument (str)
+     char *str;
+{
+  char *p, *q;
+
+  if (! str)
+    return str;
+
+  p = str;
+  q = str;
+  while (*p)
+    {
+      if (*p == '&')
+        {
+          p++;
+          if (*p == '&')
+            *p = '&';
+          else if (*p == '_')
+            *p = ' ';
+          else if (*p == 'n')
+            *p = '\n';
+          else if (*p == '-')
+            *p = '-';
+        }
+      *q++ = *p++;
+    }
+  *q = 0;
+  return str;
+}
+
 /* Like malloc but get fatal error if memory is exhausted.  */
 
 long *
@@ -231,14 +311,12 @@ xmalloc (size)
   defined-- exit with an errorcode.
 */
 void
-fail (argc, argv)
-     int argc;
-     char **argv;
+fail (void)
 {
   if (alternate_editor)
     {
       int i = optind - 1;
-      execvp (alternate_editor, argv + i);
+      execvp (alternate_editor, main_argv + i);
       return;
     }
   else
@@ -247,6 +325,101 @@ fail (argc, argv)
     }
 }
 
+/* The process id of Emacs. */
+int emacs_pid;
+
+/* File handles for communicating with Emacs. */
+FILE *out, *in;
+
+/* A signal handler that passes the signal to the Emacs process.
+   Useful for SIGWINCH.  */
+
+SIGTYPE
+pass_signal_to_emacs (int signalnum)
+{
+  int old_errno = errno;
+
+  if (emacs_pid)
+    kill (emacs_pid, signalnum);
+
+  signal (signalnum, pass_signal_to_emacs);
+  errno = old_errno;
+}
+
+/* Signal handler for SIGCONT; notify the Emacs process that it can
+   now resume our tty frame.  */
+
+SIGTYPE
+handle_sigcont (int signalnum)
+{
+  int old_errno = errno;
+
+  if (tcgetpgrp (1) == getpgrp ())
+    {
+      /* We are in the foreground. */
+      fprintf (out, "-resume \n");
+      fflush (out);
+      fsync (fileno (out));
+    }
+  else
+    {
+      /* We are in the background; cancel the continue. */
+      kill (getpid (), SIGSTOP);
+    }
+  errno = old_errno;
+}
+
+/* Signal handler for SIGTSTP; notify the Emacs process that we are
+   going to sleep.  Normally the suspend is initiated by Emacs via
+   server-handle-suspend-tty, but if the server gets out of sync with
+   reality, we may get a SIGTSTP on C-z.  Handling this signal and
+   notifying Emacs about it should get things under control again. */
+
+SIGTYPE
+handle_sigtstp (int signalnum)
+{
+  int old_errno = errno;
+  sigset_t set;
+  
+  if (out)
+    {
+      fprintf (out, "-suspend \n");
+      fflush (out);
+      fsync (fileno (out));
+    }
+
+  /* Unblock this signal and call the default handler by temprarily
+     changing the handler and resignalling. */
+  sigprocmask (SIG_BLOCK, NULL, &set);
+  sigdelset (&set, signalnum);
+  signal (signalnum, SIG_DFL);
+  kill (getpid (), signalnum);
+  sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
+  signal (signalnum, handle_sigtstp);
+
+  errno = old_errno;
+}
+
+/* Set up signal handlers before opening a frame on the current tty.  */
+
+void
+init_signals (void)
+{
+  /* Set up signal handlers. */
+  signal (SIGWINCH, pass_signal_to_emacs);
+
+  /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of
+     deciding which terminal the signal came from.  C-g is now a
+     normal input event on secondary terminals.  */
+#if 0
+  signal (SIGINT, pass_signal_to_emacs);
+  signal (SIGQUIT, pass_signal_to_emacs);
+#endif
+
+  signal (SIGCONT, handle_sigcont);
+  signal (SIGTSTP, handle_sigtstp);
+  signal (SIGTTOU, handle_sigtstp);
+}
 
 \f
 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
@@ -260,7 +433,7 @@ main (argc, argv)
           argv[0]);
   fprintf (stderr, "on systems with Berkeley sockets.\n");
 
-  fail (argc, argv);
+  fail ();
 }
 
 #else /* HAVE_SOCKETS */
@@ -294,23 +467,41 @@ socket_status (socket_name)
   return 0;
 }
 
+/* Returns 1 if PREFIX is a prefix of STRING. */
+static int
+strprefix (char *prefix, char *string)
+{
+  int i;
+  if (! prefix)
+    return 1;
+
+  if (!string)
+    return 0;
+
+  for (i = 0; prefix[i]; i++)
+    if (!string[i] || string[i] != prefix[i])
+      return 0;
+  return 1;
+}
+
 int
 main (argc, argv)
      int argc;
      char **argv;
 {
   int s, i, needlf = 0;
-  FILE *out, *in;
   struct sockaddr_un server;
   char *cwd, *str;
   char string[BUFSIZ];
 
+  main_argc = argc;
+  main_argv = argv;
   progname = argv[0];
 
   /* Process options.  */
   decode_options (argc, argv);
 
-  if ((argc - optind < 1) && !eval)
+  if ((argc - optind < 1) && !eval && !tty && !window_system)
     {
       fprintf (stderr, "%s: file name or argument required\n", progname);
       fprintf (stderr, "Try `%s --help' for more information\n", progname);
@@ -325,7 +516,7 @@ main (argc, argv)
     {
       fprintf (stderr, "%s: ", argv[0]);
       perror ("socket");
-      fail (argc, argv);
+      fail ();
     }
 
   server.sun_family = AF_UNIX;
@@ -333,30 +524,31 @@ main (argc, argv)
   {
     int sock_status = 0;
     int default_sock = !socket_name;
-    int saved_errno;
-    char *server_name = "server";
-
-    if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
-      { /* socket_name is a file name component.  */
-       server_name = socket_name;
-       socket_name = NULL;
-       default_sock = 1;       /* Try both UIDs.  */
-      }
+    int saved_errno = 0;
+
+     char *server_name = "server";
+
+     if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
+       { /* socket_name is a file name component.  */
+       server_name = socket_name;
+       socket_name = NULL;
+       default_sock = 1;       /* Try both UIDs.  */
+       }
 
-    if (default_sock)
+     if (default_sock)
       {
-       socket_name = alloca (100 + strlen (server_name));
-       sprintf (socket_name, "/tmp/emacs%d/%s",
-                (int) geteuid (), server_name);
+       socket_name = alloca (100 + strlen (server_name));
+       sprintf (socket_name, "/tmp/emacs%d/%s",
+                (int) geteuid (), server_name);
       }
 
     if (strlen (socket_name) < sizeof (server.sun_path))
       strcpy (server.sun_path, socket_name);
     else
       {
-       fprintf (stderr, "%s: socket-name %s too long",
-                argv[0], socket_name);
-       exit (1);
+        fprintf (stderr, "%s: socket-name %s too long",
+                 argv[0], socket_name);
+        fail ();
       }
 
     /* See if the socket exists, and if it's owned by us. */
@@ -395,7 +587,7 @@ main (argc, argv)
                  }
 
                sock_status = socket_status (server.sun_path);
-               saved_errno = errno;
+                saved_errno = errno;
              }
            else
              errno = saved_errno;
@@ -410,7 +602,7 @@ main (argc, argv)
         if (0 != geteuid ())
           {
             fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
-            fail (argc, argv);
+            fail ();
           }
         break;
 
@@ -418,13 +610,13 @@ main (argc, argv)
         /* `stat' failed */
         if (saved_errno == ENOENT)
           fprintf (stderr,
-                   "%s: can't find socket; have you started the server?\n\
+                   "%s: Can't find socket; have you started the server?\n\
 To start the server in Emacs, type \"M-x server-start\".\n",
                    argv[0]);
         else
-          fprintf (stderr, "%s: can't stat %s: %s\n",
+          fprintf (stderr, "%s: Can't stat %s: %s\n",
                    argv[0], server.sun_path, strerror (saved_errno));
-        fail (argc, argv);
+        fail ();
         break;
        }
   }
@@ -434,7 +626,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
     {
       fprintf (stderr, "%s: ", argv[0]);
       perror ("connect");
-      fail (argc, argv);
+      fail ();
     }
 
   /* We use the stream OUT to send our command to the server.  */
@@ -442,7 +634,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
     {
       fprintf (stderr, "%s: ", argv[0]);
       perror ("fdopen");
-      fail (argc, argv);
+      fail ();
     }
 
   /* We use the stream IN to read the response.
@@ -454,7 +646,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
     {
       fprintf (stderr, "%s: ", argv[0]);
       perror ("fdopen");
-      fail (argc, argv);
+      fail ();
     }
 
 #ifdef HAVE_GETCWD
@@ -472,83 +664,187 @@ To start the server in Emacs, type \"M-x server-start\".\n",
 #else
       fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
 #endif
-      fail (argc, argv);
+      fail ();
     }
 
+  /* First of all, send our version number for verification. */
+  fprintf (out, "-version %s ", VERSION);
+
   if (nowait)
     fprintf (out, "-nowait ");
 
-  if (eval)
-    fprintf (out, "-eval ");
-
   if (display)
     {
       fprintf (out, "-display ");
-      quote_file_name (display, out);
+      quote_argument (display, out);
       fprintf (out, " ");
     }
 
+  if (tty)
+    {
+      char *tty_name = ttyname (fileno (stdin));
+      char *type = getenv ("TERM");
+
+      if (! tty_name)
+        {
+          fprintf (stderr, "%s: could not get terminal name\n", progname);
+          fail ();
+        }
+
+      if (! type)
+        {
+          fprintf (stderr, "%s: please set the TERM variable to your terminal type\n",
+                   progname);
+          fail ();
+        }
+
+      if (! strcmp (type, "eterm"))
+        {
+          /* This causes nasty, MULTI_KBOARD-related input lockouts. */
+          fprintf (stderr, "%s: opening a frame in an Emacs term buffer"
+                   " is not supported\n", progname);
+          fail ();
+        }
+
+      init_signals ();
+
+      fprintf (out, "-tty ");
+      quote_argument (tty_name, out);
+      fprintf (out, " ");
+      quote_argument (type, out);
+      fprintf (out, " ");
+    }
+
+  if (window_system)
+    fprintf (out, "-window-system ");
+
   if ((argc - optind > 0))
     {
       for (i = optind; i < argc; i++)
        {
+          int relative = 0;
+
          if (eval)
-           ; /* Don't prepend any cwd or anything like that.  */
-         else if (*argv[i] == '+')
-           {
+            {
+              /* Don't prepend any cwd or anything like that.  */
+              fprintf (out, "-eval ");
+              quote_argument (argv[i], out);
+              fprintf (out, " ");
+              continue;
+            }
+
+          if (*argv[i] == '+')
+            {
              char *p = argv[i] + 1;
              while (isdigit ((unsigned char) *p) || *p == ':') p++;
-             if (*p != 0)
-               {
-                 quote_file_name (cwd, out);
-                 fprintf (out, "/");
-               }
-           }
-         else if (*argv[i] != '/')
-           {
-             quote_file_name (cwd, out);
-             fprintf (out, "/");
-           }
-
-         quote_file_name (argv[i], out);
-         fprintf (out, " ");
-       }
+             if (*p == 0)
+                {
+                  fprintf (out, "-position ");
+                  quote_argument (argv[i], out);
+                  fprintf (out, " ");
+                  continue;
+                }
+              else
+                relative = 1;
+            }
+          else if (*argv[i] != '/')
+            relative = 1;
+
+          fprintf (out, "-file ");
+          if (relative)
+            {
+              quote_argument (cwd, out);
+              fprintf (out, "/");
+            }
+          quote_argument (argv[i], out);
+          fprintf (out, " ");
+        }
     }
   else
     {
-      while ((str = fgets (string, BUFSIZ, stdin)))
-       {
-         quote_file_name (str, out);
-       }
-      fprintf (out, " ");
+      if (!tty && !window_system)
+        {
+          while ((str = fgets (string, BUFSIZ, stdin)))
+            {
+              if (eval)
+                fprintf (out, "-eval ");
+              else
+                fprintf (out, "-file ");
+              quote_argument (str, out);
+            }
+          fprintf (out, " ");
+        }
     }
-  
+
   fprintf (out, "\n");
   fflush (out);
+  fsync (fileno (out));
 
   /* Maybe wait for an answer.   */
   if (nowait)
-    return 0;
+    {
+      return 0;
+    }
 
-  if (!eval)
+  if (!eval && !tty)
     {
       printf ("Waiting for Emacs...");
       needlf = 2;
     }
   fflush (stdout);
+  fsync (1);
 
   /* Now, wait for an answer and print any messages.  */
   while ((str = fgets (string, BUFSIZ, in)))
     {
-      if (needlf == 2)
-       printf ("\n");
-      printf ("%s", str);
-      needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+      char *p = str + strlen (str) - 1;
+      while (p > str && *p == '\n')
+        *p-- = 0;
+
+      if (strprefix ("-good-version ", str))
+        {
+          /* OK, we got the green light. */
+        }
+      else if (strprefix ("-emacs-pid ", str))
+        {
+          emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
+        }
+      else if (strprefix ("-print ", str))
+        {
+          str = unquote_argument (str + strlen ("-print "));
+          if (needlf)
+            printf ("\n");
+          printf ("%s", str);
+          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+        }
+      else if (strprefix ("-error ", str))
+        {
+          str = unquote_argument (str + strlen ("-error "));
+          if (needlf)
+            printf ("\n");
+          printf ("*ERROR*: %s", str);
+          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+        }
+      else if (strprefix ("-suspend ", str))
+        {
+          if (needlf)
+            printf ("\n");
+          needlf = 0;
+          kill (0, SIGSTOP);
+        }
+      else
+        {
+          if (needlf)
+            printf ("\n");
+          printf ("*ERROR*: Unknown message: %s", str);
+          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+        }
     }
 
   if (needlf)
     printf ("\n");
   fflush (stdout);
+  fsync (1);
 
   return 0;
 }
index b7466b6c13498bf900c355aece3fe621891dc535..658a30c789bff00b3dd880dd95cd2119605ac670 100755 (executable)
@@ -29,7 +29,7 @@ Options:
 
 Report bugs to <bug-gnu-emacs@gnu.org>.'
 
-Id='$Id: rcs2log,v 1.52 2003/12/27 08:18:08 uid65632 Exp $'
+Id='$Id: rcs2log,v 1.53 2004/02/15 07:41:58 uid65632 Exp $'
 
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002, 2003,
 # 2004 Free Software Foundation, Inc.
index 32c4e5ba89e2926347fd5f7b4b92b5ac7b05c497..9e52a7f4c30c4ee2d8cf530773ba2eeb10992036 100755 (executable)
@@ -23,7 +23,7 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 #
-#      $Id: vcdiff,v 1.7 2001/02/20 12:36:28 gerd Exp $
+#      $Id: vcdiff,v 1.8 2003/09/01 15:45:03 miles Exp $
 #
 
 DIFF="diff"
index 9efd587a199d45e997aef36d9202fa62b5dc040f..137a00d802d213667c93912fa83b13452f12e64c 100644 (file)
@@ -128,7 +128,8 @@ COMPILE_FIRST = \
        $(lisp)/emacs-lisp/bytecomp.el \
        $(lisp)/subr.el \
        $(lisp)/progmodes/cc-mode.el \
-       $(lisp)/progmodes/cc-vars.el
+       $(lisp)/progmodes/cc-vars.el \
+       $(lisp)/vc-arch.el
 
 # The actual Emacs command run in the targets below.
 
index 3fa04449e16af596421e9dca9be0d06a83e5940a..79d19dc36e67fb261eef7ebd4b0d65175ab99930 100644 (file)
@@ -507,7 +507,7 @@ behavior."
 ;;;_  : Version
 ;;;_   = allout-version
 (defvar allout-version
-  (let ((rcs-rev "$Revision: 1.47 $"))
+  (let ((rcs-rev "$Revision: 1.48 $"))
     (condition-case err
        (save-match-data
          (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
index 1f86f3b6fcb67e4bff99d63ae4b6d2b859152dae..280ca0288425621c692a52dbd07bdbc5aa41a1aa 100644 (file)
@@ -214,7 +214,7 @@ Major modes that edit things other than ordinary files may change this
 
 (make-variable-buffer-local 'mode-line-buffer-identification)
 
-(defvar mode-line-frame-identification '("-%F  ")
+(defvar mode-line-frame-identification '(window-system "  " "-%F  ")
   "Mode-line control to describe the current frame.")
 
 (defvar mode-line-process nil "\
index 1ff07c4c361e2f1261b0fb74e7f3877005b9a34c..b5716da161af0872ed31e24abcc4b59ce99a6551 100644 (file)
@@ -41,6 +41,7 @@
        ;; If the user has already created the face, respect that.
        (let ((value (or (get face 'saved-face) spec))
              (frames (frame-list))
+             (have-window-system (memq initial-window-system '(x w32)))
              frame)
          ;; Create global face.
          (make-empty-face face)
          (while frames
            (setq frame (car frames)
                  frames (cdr frames))
-           (face-spec-set face value frame)))
-       ;; When making a face after frames already exist
-       (if (memq window-system '(x w32))
-           (make-face-x-resource-internal face))))
+           (face-spec-set face value frame)
+           (when (memq (window-system frame) '(x w32))
+             (setq have-window-system t)))
+         ;; When making a face after frames already exist
+         (if have-window-system
+             (make-face-x-resource-internal face)))))
     ;; Don't record SPEC until we see it causes no errors.
     (put face 'face-defface-spec spec)
     (when (and doc (null (face-documentation face)))
index 2480c6777dc54df3f0ed4cf3a77a3c2e2b5c6906..47dab153dbaf673b1607a905b897c6c8d9c305b3 100644 (file)
@@ -905,7 +905,7 @@ an integer value."
   (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 @@ an integer value."
             (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 @@ an integer value."
            ((: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 @@ of a global face.  Value is the new attribute value."
               ;; 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 @@ If FRAME is nil, the current FRAME is used."
            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))
@@ -1539,22 +1539,32 @@ this won't have the expected effect."
 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))
+        (tty-type (frame-parameter frame 'tty-type))
         (bg-mode
          (cond (frame-background-mode)
                (bg-resource
                 (intern (downcase bg-resource)))
-               ((and (null window-system) (null bg-color))
-                ;; No way to determine this automatically (?).
-                'dark)
-               ;; Unspecified frame background color can only happen
-               ;; on tty's.
-               ((member bg-color '(unspecified "unspecified-bg"))
-                'dark)
+               ((and (null (window-system frame))
+                     ;; Unspecified frame background color can only
+                     ;; happen on tty's.
+                     (member bg-color '(nil unspecified "unspecified-bg")))
+                ;; There is no way to determine the background mode
+                ;; automatically, so we make a guess based on the
+                ;; terminal type.
+                (if (and tty-type
+                         (string-match "^\\(xterm\\|rxvt\\|dtterm\\|eterm\\)"
+                                       tty-type))
+                    'light
+                  'dark))
                ((equal bg-color "unspecified-fg") ; inverted colors
-                'light)
+                (if (and tty-type
+                         (string-match "^\\(xterm\\|rxvt\\|dtterm\\|eterm\\)"
+                                       tty-type))
+                    'dark
+                  'light))
                ((>= (apply '+ (x-color-values bg-color frame))
                    ;; Just looking at the screen, colors whose
                    ;; values add up to .6 of the white total
@@ -1563,7 +1573,7 @@ according to the `background-mode' and `display-type' frame parameters."
                 '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)
@@ -1660,7 +1670,7 @@ Value is the new frame created."
   (setq parameters (x-handle-named-frame-geometry parameters))
   (let ((visibility-spec (assq 'visibility parameters))
        (frame-list (frame-list))
-       (frame (x-create-frame (cons '(visibility . nil) parameters)))
+       (frame (x-create-frame `((visibility . nil) . ,parameters)))
        success)
     (unwind-protect
        (progn
@@ -1670,6 +1680,11 @@ Value is the new frame created."
          (if (or (null frame-list) (null visibility-spec))
              (make-frame-visible frame)
            (modify-frame-parameters frame (list visibility-spec)))
+         ;; Arrange for the kill and yank functions to set and check the clipboard.
+         (modify-frame-parameters
+          frame '((interprogram-cut-function . x-select-text)))
+         (modify-frame-parameters
+          frame '((interprogram-paste-function . x-cut-buffer-or-selection-value)))
          (setq success t))
       (unless success
        (delete-frame frame)))
@@ -1698,7 +1713,7 @@ Initialize colors of certain faces from frame parameters."
        (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)))
@@ -1746,15 +1761,33 @@ Parameters not specified by PARAMETERS are taken from
 `default-frame-alist'.  If either PARAMETERS or `default-frame-alist'
 contains a `reverse' parameter, handle that.  Value is the new frame
 created."
-  (let ((frame (make-terminal-frame parameters))
+  (let ((old-frame (selected-frame))
+       (frame (make-terminal-frame parameters))
        success)
     (unwind-protect
        (progn
+         (select-frame frame)
          (tty-handle-reverse-video frame (frame-parameters frame))
          (frame-set-background-mode frame)
          (face-set-after-frame-default frame)
+         ;; Load library for our terminal type.
+         ;; User init file can set term-file-prefix to nil to prevent this.
+         (unless (null term-file-prefix)
+           (let ((term (cdr (assq 'tty-type parameters)))
+                 hyphend)
+             (while (and term
+                         (not (load (concat term-file-prefix term) t t)))
+               ;; Strip off last hyphen and what follows, then try again
+               (setq term
+                     (if (setq hyphend (string-match "[-_][^-_]+$" term))
+                         (substring term 0 hyphend)
+                       nil)))))
+         ;; Make sure the kill and yank functions do not touch the X clipboard.
+         (modify-frame-parameters frame '((interprogram-cut-function . nil)))
+         (modify-frame-parameters frame '((interprogram-paste-function . nil)))
          (setq success t))
       (unless success
+       (select-frame old-frame)
        (delete-frame frame)))
     frame))
 
index a470fbc0f97c43498e706c8a7f98aa1c273a678d..54bccd93970ff78a5fea4b92f34a757f92fbe3a3 100644 (file)
 
 ;;; Code:
 
-(defvar frame-creation-function nil
-  "Window-system dependent function to call to create a new frame.
-The window system startup file should set this to its frame creation
-function, which should take an alist of parameters as its argument.")
+(defvar frame-creation-function-alist
+  (list (cons nil
+             (if (fboundp 'tty-create-frame-with-faces)
+                 'tty-create-frame-with-faces
+               (function
+                (lambda (parameters)
+                  (error "Can't create multiple frames without a window system"))))))
+  "Alist of window-system dependent functions to call to create a new frame.
+The window system startup file should add its frame creation
+function to this list, which should take an alist of parameters
+as its argument.")
 
 ;; The initial value given here used to ask for a minibuffer.
 ;; But that's not necessary, because the default is to have one.
@@ -186,7 +193,9 @@ Pass it BUFFER as first arg, and (cdr ARGS) gives the rest of the args."
 (defun frame-initialize ()
   "Create an initial frame if necessary."
   ;; Are we actually running under a window system at all?
-  (if (and window-system (not noninteractive) (not (eq window-system 'pc)))
+  (if (and initial-window-system
+          (not noninteractive)
+          (not (eq initial-window-system 'pc)))
       (progn
        ;; Turn on special-display processing only if there's a window system.
        (setq special-display-function 'special-display-popup-frame)
@@ -203,6 +212,9 @@ Pass it BUFFER as first arg, and (cdr ARGS) gives the rest of the args."
                  (setq frame-initial-frame-alist
                        (cons '(horizontal-scroll-bars . t)
                              frame-initial-frame-alist)))
+             (setq frame-initial-frame-alist
+                   (cons (cons 'window-system initial-window-system)
+                         frame-initial-frame-alist))
              (setq default-minibuffer-frame
                    (setq frame-initial-frame
                          (make-frame frame-initial-frame-alist)))
@@ -215,18 +227,7 @@ Pass it BUFFER as first arg, and (cdr ARGS) gives the rest of the args."
        ;; At this point, we know that we have a frame open, so we
        ;; can delete the terminal frame.
        (delete-frame terminal-frame)
-       (setq terminal-frame nil))
-
-    ;; No, we're not running a window system.  Use make-terminal-frame if
-    ;; we support that feature, otherwise arrange to cause errors.
-    (or (eq window-system 'pc)
-       (setq frame-creation-function
-             (if (fboundp 'tty-create-frame-with-faces)
-                 'tty-create-frame-with-faces
-               (function
-                (lambda (parameters)
-                  (error
-                   "Can't create multiple frames without a window system"))))))))
+       (setq terminal-frame nil))))
 
 (defvar frame-notice-user-settings t
   "Non-nil means function `frame-notice-user-settings' wasn't run yet.")
@@ -276,7 +277,7 @@ React to settings of `default-frame-alist', `initial-frame-alist' there."
        ;; Can't modify the minibuffer parameter, so don't try.
        (setq parms (delq (assq 'minibuffer parms) parms))
        (modify-frame-parameters nil
-                                (if (null window-system)
+                                (if (null initial-window-system)
                                     (append initial-frame-alist
                                             default-frame-alist
                                             parms
@@ -285,7 +286,7 @@ React to settings of `default-frame-alist', `initial-frame-alist' there."
                                   ;; default-frame-alist were already
                                   ;; applied in pc-win.el.
                                   parms))
-       (if (null window-system) ;; MS-DOS does this differently in pc-win.el
+       (if (null initial-window-system) ;; MS-DOS does this differently in pc-win.el
            (let ((newparms (frame-parameters))
                  (frame (selected-frame)))
              (tty-handle-reverse-video frame newparms)
@@ -569,7 +570,20 @@ The optional second argument PARAMETERS specifies additional frame parameters."
   (interactive "sMake frame on display: ")
   (or (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" display)
       (error "Invalid display, not HOST:SERVER or HOST:SERVER.SCREEN"))
-  (make-frame (cons (cons 'display display) parameters)))
+  (unless x-initialized
+    (setq x-display-name display)
+    (x-initialize-window-system))
+  (make-frame `((window-system . x) (display . ,display) . ,parameters)))
+
+(defun make-frame-on-tty (device type &optional parameters)
+  "Make a frame on terminal DEVICE which is of type TYPE (e.g., \"xterm\").
+The optional third argument PARAMETERS specifies additional frame parameters."
+  (interactive "fOpen frame on tty device: \nsTerminal type of %s: ")
+  (unless device
+    (error "Invalid terminal device"))
+  (unless type
+    (error "Invalid terminal type"))
+  (make-frame `((window-system . nil) (tty . ,device) (tty-type . ,type) . ,parameters)))
 
 (defun make-frame-command ()
   "Make a new frame, and select it if the terminal displays only one frame."
@@ -609,12 +623,22 @@ You cannot specify either `width' or `height', you must use neither or both.
  (minibuffer . only)   The frame should contain only a minibuffer.
  (minibuffer . WINDOW) The frame should use WINDOW as its minibuffer window.
 
-Before the frame is created (via `frame-creation-function'), functions on the
+ (window-system . nil) The frame should be displayed on a terminal device.
+ (window-system . x)   The frame should be displayed in an X window.
+
+Before the frame is created (via `frame-creation-function-alist'), functions on the
 hook `before-make-frame-hook' are run.  After the frame is created, functions
 on `after-make-frame-functions' are run with one arg, the newly created frame."
   (interactive)
-  (run-hooks 'before-make-frame-hook)
-  (let ((frame (funcall frame-creation-function parameters)))
+  (let* ((w (if (assq 'window-system parameters)
+               (cdr (assq 'window-system parameters))
+             window-system))
+        (frame-creation-function (cdr (assq w frame-creation-function-alist)))
+        frame)
+    (unless frame-creation-function
+      (error "Don't know how to create a frame on window system %s" w))
+    (run-hooks 'before-make-frame-hook)
+    (setq frame (funcall frame-creation-function parameters))
     (run-hook-with-args 'after-make-frame-functions frame)
     frame))
 
@@ -687,9 +711,9 @@ automatically."
     (select-frame frame)
     (raise-frame frame)
     ;; Ensure, if possible, that frame gets input focus.
-    (cond ((eq window-system 'x)
+    (cond ((eq (window-system frame) 'x)
           (x-focus-frame frame))
-         ((eq window-system 'w32)
+         ((eq (window-system frame) 'w32)
           (w32-focus-frame frame)))
     (cond (focus-follows-mouse
           (set-mouse-position (selected-frame) (1- (frame-width)) 0))))
@@ -726,6 +750,22 @@ Otherwise, that variable should be nil."
       (iconify-frame)
     (make-frame-visible)))
 
+(defun suspend-frame ()
+  "Do whatever is right to suspend the current frame.
+Calls `suspend-emacs' if invoked from the controlling terminal,
+`suspend-tty' from a secondary terminal, and
+`iconify-or-deiconify-frame' from an X frame."
+  (interactive)
+  (let ((type (framep (selected-frame))))
+    (cond
+     ((eq type 'x) (iconify-or-deiconify-frame))
+     ((eq type t)
+      (if (frame-tty-name)
+         (suspend-tty)
+       (suspend-emacs)))
+     (t (suspend-emacs)))))
+
+
 (defun make-frame-names-alist ()
   (let* ((current-frame (selected-frame))
         (falist
@@ -759,9 +799,9 @@ If there is no frame by that name, signal an error."
     (raise-frame frame)
     (select-frame frame)
     ;; Ensure, if possible, that frame gets input focus.
-    (cond ((eq window-system 'x)
+    (cond ((eq (window-system frame) 'x)
           (x-focus-frame frame))
-         ((eq window-system 'w32)
+         ((eq (window-system frame) 'w32)
           (w32-focus-frame frame)))
     (when focus-follows-mouse
       (set-mouse-position frame (1- (frame-width frame)) 0))))
@@ -1118,7 +1158,7 @@ the question is inapplicable to a certain kind of display."
      ((eq frame-type 'pc)
       16)
      (t
-      (tty-display-color-cells)))))
+      (tty-display-color-cells display)))))
 
 (defun display-visual-class (&optional display)
   "Returns the visual class of DISPLAY.
@@ -1350,6 +1390,8 @@ Use Custom to set this variable to get the display updated."
 (define-key ctl-x-5-map "0" 'delete-frame)
 (define-key ctl-x-5-map "o" 'other-frame)
 
+(substitute-key-definition 'suspend-emacs 'suspend-frame global-map)
+
 (provide 'frame)
 
 ;;; arch-tag: 82979c70-b8f2-4306-b2ad-ddbd6b328b56
index bd90fb7c53aa741f3add893d29075da09fdc947f..82f6b1d664178ad73446bd71c6931781953e6d48 100644 (file)
@@ -67,6 +67,8 @@
 (setq load-source-file-function 'load-with-code-conversion)
 (load "files")
 
+(load "startup")
+
 (load "cus-face")
 (load "faces")  ; after here, `defface' may be used.
 
 (message "%s" (garbage-collect))
 (load "menu-bar")
 (load "paths.el")  ;Don't get confused if someone compiled paths by mistake.
-(load "startup")
 (load "emacs-lisp/lisp")
 (load "textmodes/page")
 (load "register")
       (load "emacs-lisp/float-sup")))
 (message "%s" (garbage-collect))
 
+;; Load auxiliary settings for X displays if we support them.
+(when (fboundp 'x-create-frame)
+  (load "mouse")
+  (load "international/fontset")
+  (load "x-dnd")
+  (load "term/x-win"))
+
+(message "%s" (garbage-collect))
+
 (load "vc-hooks")
 (load "ediff-hook")
 (message "%s" (garbage-collect))
index fe2fc0f59f470d1d1731dea7b5763468608fa2f4..2d0a32415afb6df1dc05bd0bbd64c8d98426a231 100644 (file)
@@ -106,6 +106,24 @@ Each element is (CLIENTID BUFFERS...) where CLIENTID is a string
 that can be given to the server process to identify a client.
 When a buffer is marked as \"done\", it is removed from this list.")
 
+(defvar server-ttys nil
+  "List of current terminal devices used by the server.
+Each element is (CLIENTID TTY) where CLIENTID is a string
+that can be given to the server process to identify a client.
+TTY is the name of the tty device.
+
+When all frames on the device are deleted, the server quits the
+connection to the client, and vice versa.")
+
+(defvar server-frames nil
+  "List of current window-system frames used by the server.
+Each element is (CLIENTID FRAME) where CLIENTID is a string
+that can be given to the server process to identify a client.
+FRAME is the frame that was opened by the client.
+
+When the frame is deleted, the server closes the connection to
+the client, and vice versa.")
+
 (defvar server-buffer-clients nil
   "List of client ids for clients requesting editing of current buffer.")
 (make-variable-buffer-local 'server-buffer-clients)
@@ -170,10 +188,18 @@ are done with it in the server.")
       (with-current-buffer "*server*"
        (goto-char (point-max))
        (insert (current-time-string)
-               (if client (format " %s:" client) " ")
+               (if client (format " %s: " client) " ")
                string)
        (or (bolp) (newline)))))
 
+(defun server-tty-live-p (tty)
+  "Return non-nil if the tty device named TTY has a live frame."
+  (let (result)
+    (dolist (frame (frame-list) result)
+      (when (and (eq (frame-live-p frame) t)
+                (equal (frame-tty-name frame) tty))
+       (setq result t)))))
+
 (defun server-sentinel (proc msg)
   (let ((client (assq proc server-clients)))
     ;; Remove PROC from the list of clients.
@@ -188,9 +214,54 @@ are done with it in the server.")
                     (or (and server-kill-new-buffers
                              (not server-existing-buffer))
                         (server-temp-file-p)))
-           (kill-buffer (current-buffer)))))))
+           (kill-buffer (current-buffer)))))
+      (let ((tty (assq (car client) server-ttys)))
+       (when tty
+         (setq server-ttys (delq tty server-ttys))
+         (when (server-tty-live-p (cadr tty))
+           (delete-tty (cadr tty)))))))
   (server-log (format "Status changed to %s" (process-status proc)) proc))
 
+(defun server-handle-delete-tty (tty)
+  "Delete the client connection when the emacsclient terminal device is closed."
+  (dolist (entry server-ttys)
+    (let ((proc (nth 0 entry))
+         (term (nth 1 entry)))
+      (when (equal term tty)
+       (let ((client (assq proc server-clients)))
+         (server-log (format "server-handle-delete-tty, tty %s" tty) (car client))
+         (setq server-ttys (delq entry server-ttys))
+         (delete-process (car client))
+         (when (assq proc server-clients)
+           ;; This seems to be necessary to handle
+           ;; `emacsclient -t -e '(delete-frame)'' correctly.
+           (setq server-clients (delq client server-clients))))))))
+
+(defun server-handle-suspend-tty (tty)
+  "Notify the emacsclient process to suspend itself when its tty device is suspended."
+  (dolist (entry server-ttys)
+    (let ((proc (nth 0 entry))
+         (term (nth 1 entry)))
+      (when (equal term tty)
+       (let ((process (car (assq proc server-clients))))
+         (server-log (format "server-handle-suspend-tty, tty %s" tty) process)
+         (process-send-string process "-suspend \n"))))))
+
+(defun server-handle-delete-frame (frame)
+  "Delete the client connection when the emacsclient frame is deleted."
+  (dolist (entry server-frames)
+    (let ((proc (nth 0 entry))
+         (f (nth 1 entry)))
+      (when (equal frame f)
+       (let ((client (assq proc server-clients)))
+         (server-log (format "server-handle-delete-frame, frame %s" frame) (car client))
+         (setq server-frames (delq entry server-frames))
+         (delete-process (car client))
+         (when (assq proc server-clients)
+           ;; This seems to be necessary to handle
+           ;; `emacsclient -t -e '(delete-frame)'' correctly.
+           (setq server-clients (delq client server-clients))))))))
+
 (defun server-select-display (display)
   ;; If the current frame is on `display' we're all set.
   (unless (equal (frame-parameter (selected-frame) 'display) display)
@@ -202,14 +273,14 @@ are done with it in the server.")
     ;; and select it.
     (unless (equal (frame-parameter (selected-frame) 'display) display)
       (select-frame
-       (make-frame-on-display
-       display
+       (make-frame-on-display display)))))
        ;; This frame is only there in place of an actual "current display"
        ;; setting, so we want it to be as unobtrusive as possible.  That's
        ;; what the invisibility is for.  The minibuffer setting is so that
        ;; we don't end up displaying a buffer in it (which noone would
        ;; notice).
-       '((visibility . nil) (minibuffer . only)))))))
+        ;; XXX I have found this behaviour to be surprising and annoying. -- Lorentey
+       ;; '((visibility . nil) (minibuffer . only)))))))
 
 (defun server-unquote-arg (arg)
   (replace-regexp-in-string
@@ -221,6 +292,19 @@ are done with it in the server.")
            (t " ")))
    arg t t))
 
+(defun server-quote-arg (arg)
+  "In NAME, insert a & before each &, each space, each newline, and -.
+Change spaces to underscores, too, so that the return value never
+contains a space."
+  (replace-regexp-in-string
+   "[-&\n ]" (lambda (s)
+              (case (aref s 0)
+                (?& "&&")
+                (?- "&-")
+                (?\n "&n")
+                (?\s "&_")))
+   arg t t))
+
 (defun server-ensure-safe-dir (dir)
   "Make sure DIR is a directory with no race-condition issues.
 Creates the directory if necessary and makes sure:
@@ -260,10 +344,18 @@ Prefix arg means just kill any existing server communications subprocess."
   (while server-clients
     (let ((buffer (nth 1 (car server-clients))))
       (server-buffer-done buffer)))
+  ;; Delete any remaining opened frames of the previous server.
+  (while server-ttys
+    (let ((tty (cadar server-ttys)))
+      (setq server-ttys (cdr server-ttys))
+      (when (server-tty-live-p tty) (delete-tty tty))))
   (unless leave-dead
     (if server-process
        (server-log (message "Restarting server")))
     (letf (((default-file-modes) ?\700))
+      (add-to-list 'delete-tty-after-functions 'server-handle-delete-tty)
+      (add-to-list 'suspend-tty-functions 'server-handle-suspend-tty)
+      (add-to-list 'delete-frame-functions 'server-handle-delete-frame)
       (setq server-process
            (make-network-process
             :name "server" :family 'local :server t :noquery t
@@ -295,84 +387,186 @@ PROC is the server process.  Format of STRING is \"PATH PATH PATH... \\n\"."
     (when prev
       (setq string (concat prev string))
       (process-put proc 'previous-string nil)))
-  ;; If the input is multiple lines,
-  ;; process each line individually.
-  (while (string-match "\n" string)
-    (let ((request (substring string 0 (match-beginning 0)))
-         (coding-system (and default-enable-multibyte-characters
-                             (or file-name-coding-system
-                                 default-file-name-coding-system)))
-         client nowait eval
-         (files nil)
-         (lineno 1)
-         (tmp-frame nil) ; Sometimes used to embody the selected display.
-         (columnno 0))
-      ;; Remove this line from STRING.
-      (setq string (substring string (match-end 0)))
-      (setq client (cons proc nil))
-      (while (string-match "[^ ]* " request)
-       (let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
-         (setq request (substring request (match-end 0)))
-         (cond
-          ((equal "-nowait" arg) (setq nowait t))
-          ((equal "-eval" arg) (setq eval t))
-          ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
-           (let ((display (server-unquote-arg (match-string 1 request))))
-             (setq request (substring request (match-end 0)))
-             (condition-case err
-                 (setq tmp-frame (server-select-display display))
-               (error (process-send-string proc (nth 1 err))
-                      (setq request "")))))
-          ;; ARG is a line number option.
-          ((string-match "\\`\\+[0-9]+\\'" arg)
-           (setq lineno (string-to-int (substring arg 1))))
-          ;; ARG is line number:column option.
-          ((string-match "\\`+\\([0-9]+\\):\\([0-9]+\\)\\'" arg)
-           (setq lineno (string-to-int (match-string 1 arg))
-                 columnno (string-to-int (match-string 2 arg))))
-          (t
-           ;; Undo the quoting that emacsclient does
-           ;; for certain special characters.
-           (setq arg (server-unquote-arg arg))
-           ;; Now decode the file name if necessary.
-           (if coding-system
-               (setq arg (decode-coding-string arg coding-system)))
-           (if eval
-               (let ((v (eval (car (read-from-string arg)))))
-                 (when v
-                   (with-temp-buffer
-                     (let ((standard-output (current-buffer)))
-                       (pp v)
-                       (process-send-region proc (point-min) (point-max))))))
-             ;; ARG is a file name.
-             ;; Collapse multiple slashes to single slashes.
-             (setq arg (command-line-normalize-file-name arg))
-             (push (list arg lineno columnno) files))
-           (setq lineno 1)
-           (setq columnno 0)))))
-      (when files
-       (run-hooks 'pre-command-hook)
-       (server-visit-files files client nowait)
-       (run-hooks 'post-command-hook))
-      ;; CLIENT is now a list (CLIENTNUM BUFFERS...)
-      (if (null (cdr client))
-         ;; This client is empty; get rid of it immediately.
-         (progn
-           (delete-process proc)
-           (server-log "Close empty client" proc))
-       ;; We visited some buffer for this client.
-       (or nowait (push client server-clients))
-       (unless (or isearch-mode (minibufferp))
-         (server-switch-buffer (nth 1 client))
-         (run-hooks 'server-switch-hook)
-         (unless nowait
-           (message (substitute-command-keys
-                     "When done with a buffer, type \\[server-edit]")))))
-      ;; Avoid preserving the connection after the last real frame is deleted.
-      (if tmp-frame (delete-frame tmp-frame))))
-  ;; Save for later any partial line that remains.
-  (when (> (length string) 0)
-    (process-put proc 'previous-string string)))
+  (condition-case err
+      (progn
+       ;; If the input is multiple lines,
+       ;; process each line individually.
+       (while (string-match "\n" string)
+         (let ((request (substring string 0 (match-beginning 0)))
+               (coding-system (and default-enable-multibyte-characters
+                                   (or file-name-coding-system
+                                       default-file-name-coding-system)))
+               client nowait newframe display version-checked
+               dontkill       ; t if the client should not be killed.
+               registered ; t if the client is already added to server-clients.
+               (files nil)
+               (lineno 1)
+               (columnno 0))
+           ;; Remove this line from STRING.
+           (setq string (substring string (match-end 0)))
+           (setq client (cons proc nil))
+           (while (string-match "[^ ]* " request)
+             (let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
+               (setq request (substring request (match-end 0)))
+               (cond
+                ;; Check version numbers.
+                ((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request))
+                 (let* ((client-version (match-string 1 request))
+                        (truncated-emacs-version (substring emacs-version 0 (length client-version))))
+                   (setq request (substring request (match-end 0)))
+                   (if (equal client-version truncated-emacs-version)
+                       (progn
+                         (process-send-string proc "-good-version \n")
+                         (setq version-checked t))
+                     (error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version)))))
+
+                ((equal "-nowait" arg) (setq nowait t))
+
+                ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
+                 (setq display (match-string 1 request)
+                       request (substring request (match-end 0))))
+
+                ;; Open a new X frame.
+                ((equal "-window-system" arg)
+                 (unless version-checked
+                   (error "Protocol error; make sure to use the correct version of emacsclient"))
+                 (let ((frame (make-frame-on-display
+                               (or display
+                                   (frame-parameter nil 'display)
+                                   (getenv "DISPLAY")
+                                   (error "Please specify display")))))
+                   (push (list proc frame) server-frames)
+                   (select-frame frame)
+                   ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
+                   (push client server-clients)
+                   (setq registered t
+                         newframe t
+                         dontkill t)))
+
+                ;; Resume a suspended tty frame.
+                ((equal "-resume" arg)
+                 (let ((tty (cadr (assq (car client) server-ttys))))
+                   (setq dontkill t)
+                   (when tty (resume-tty tty))))
+
+                ;; Suspend the client's frame.  (In case we get out of
+                ;; sync, and a C-z sends a SIGTSTP to emacsclient.)
+                ((equal "-suspend" arg)
+                 (let ((tty (cadr (assq (car client) server-ttys))))
+                   (setq dontkill t)
+                   (when tty (suspend-tty tty))))
+
+                ;; Noop; useful for debugging emacsclient.
+                ((and (equal "-ignore" arg) (string-match "\\([^ ]*\\) " request))
+                 (setq dontkill t
+                       request (substring request (match-end 0))))
+
+                ;; Open a new tty frame at the client.  ARG is the name of the pseudo tty.
+                ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
+                 (let ((tty (server-unquote-arg (match-string 1 request)))
+                       (type (server-unquote-arg (match-string 2 request))))
+                   (setq request (substring request (match-end 0)))
+                   (unless version-checked
+                     (error "Protocol error; make sure to use the correct version of emacsclient"))
+                   (let ((frame (make-frame-on-tty tty type)))
+                     (push (list (car client) (frame-tty-name frame)) server-ttys)
+                     (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
+                     (select-frame frame)
+                     ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
+                     (push client server-clients)
+                     (setq registered t
+                           dontkill t
+                           newframe t))))
+
+                ;; ARG is a line number option.
+                ((and (equal "-position" arg) (string-match "\\(\\+[0-9]+\\) " request))
+                 (setq request (substring request (match-end 0))
+                       lineno (string-to-int (substring (match-string 1 request) 1))))
+
+                ;; ARG is line number:column option.
+                ((and (equal "-position" arg) (string-match "\\+\\([0-9]+\\):\\([0-9]+\\) " request))
+                 (setq request (substring request (match-end 0))
+                       lineno (string-to-int (match-string 1 request))
+                       columnno (string-to-int (match-string 2 request))))
+
+                ;; ARG is a file to load.
+                ((and (equal "-file" arg) (string-match "\\([^ ]+\\) " request))
+                 (let ((file (server-unquote-arg (match-string 1 request))))
+                   (setq request (substring request (match-end 0)))
+                   (if coding-system
+                       (setq file (decode-coding-string file coding-system)))
+                   (setq file (command-line-normalize-file-name file))
+                   (push (list file lineno columnno) files))
+                 (setq lineno 1
+                       columnno 0))
+
+                ;; ARG is a Lisp expression.
+                ((and (equal "-eval" arg) (string-match "\\([^ ]+\\) " request))
+                 (let ((expr (server-unquote-arg (match-string 1 request))))
+                   (setq request (substring request (match-end 0)))
+                   (if coding-system
+                       (setq expr (decode-coding-string expr coding-system)))
+                   (let ((v (eval (car (read-from-string expr)))))
+                     (when (and (not newframe) v)
+                       (with-temp-buffer
+                         (let ((standard-output (current-buffer)))
+                           (pp v)
+                           (process-send-string proc "-print ")
+                           (process-send-string
+                            proc (server-quote-arg
+                                  (buffer-substring-no-properties (point-min)
+                                                                  (point-max))))
+                           (process-send-string proc "\n")))))
+                   (setq lineno 1
+                         columnno 0)))
+
+                ;; Unknown command.
+                (t (error "Unknown command: %s" arg)))))
+
+           (when files
+             (run-hooks 'pre-command-hook)
+             (server-visit-files files client nowait)
+             (run-hooks 'post-command-hook))
+
+           ;; CLIENT is now a list (CLIENTNUM BUFFERS...)
+
+           ;; Delete the client if necessary.
+           (cond
+            ;; Client requested nowait; return immediately.
+            (nowait
+             (delete-process proc)
+             (server-log "Close nowait client" proc))
+            ;; This client is empty; get rid of it immediately.
+            ((and (not dontkill) (null (cdr client)))
+             (delete-process proc)
+             (server-log "Close empty client" proc))
+            ((not registered)
+             (push client server-clients)))
+
+           ;; We visited some buffer for this client.
+           (cond
+            ((or isearch-mode (minibufferp))
+             nil)
+            ((and newframe (null (cdr client)))
+             (message (substitute-command-keys
+                       "When done with this frame, type \\[delete-frame]")))
+            ((not (null (cdr client)))
+             (server-switch-buffer (nth 1 client))
+             (run-hooks 'server-switch-hook)
+             (unless nowait
+               (message (substitute-command-keys
+                         "When done with a buffer, type \\[server-edit]")))))))
+
+       ;; Save for later any partial line that remains.
+       (when (> (length string) 0)
+         (process-put proc 'previous-string string)))
+    ;; condition-case
+    (error (ignore-errors
+            (process-send-string
+             proc (concat "-error " (server-quote-arg (error-message-string err))))
+            (setq string "")
+            (server-log (error-message-string err) proc)
+            (delete-process proc)))))
 
 (defun server-goto-line-column (file-line-col)
   (goto-line (nth 1 file-line-col))
@@ -446,9 +640,17 @@ FOR-KILLING if non-nil indicates that we are called from `kill-buffer'."
        ;; If client now has no pending buffers,
        ;; tell it that it is done, and forget it entirely.
        (unless (cdr client)
-         (delete-process (car client))
-         (server-log "Close" (car client))
-         (setq server-clients (delq client server-clients))))
+         (let ((tty (cadr (assq (car client) server-ttys)))
+               (frame (cadr (assq (car client) server-frames))))
+           (cond
+            ;; Be careful, if we delete the process before the
+            ;; tty, then the terminal modes will not be restored
+            ;; correctly.
+            (tty (delete-tty tty))
+            (frame (delete-frame frame))
+            (t (delete-process (car client))
+               (server-log "Close" (car client))
+               (setq server-clients (delq client server-clients)))))))
       (setq old-clients (cdr old-clients)))
     (if (and (bufferp buffer) (buffer-name buffer))
        ;; We may or may not kill this buffer;
@@ -515,6 +717,11 @@ specifically for the clients and did not exist before their request for it."
 ;; using whatever is on disk in that file. -- rms.
 (defun server-kill-buffer-query-function ()
   (or (not server-buffer-clients)
+      (let ((res t))
+       (dolist (proc server-buffer-clients res)
+         (setq proc (assq proc server-clients))
+         (when (and proc (eq (process-status (car proc)) 'open))
+           (setq res nil))))
       (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
                           (buffer-name (current-buffer))))))
 
@@ -576,7 +783,8 @@ Arg NEXT-BUFFER is a suggestion; if it is a live buffer, use it."
   ;; since we've already effectively done that.
   (if (null next-buffer)
       (if server-clients
-         (server-switch-buffer (nth 1 (car server-clients)) killed-one)
+         (let ((buffer (nth 1 (car server-clients))))
+           (and buffer (server-switch-buffer buffer killed-one)))
        (unless (or killed-one (window-dedicated-p (selected-window)))
          (switch-to-buffer (other-buffer))
          (message "No server buffers remain to edit")))
index 6bc89ae175046442343371fe2068ce3a0d4b064b..13cb63af240c082a5219fef8944825483e2072e4 100644 (file)
@@ -1788,6 +1788,8 @@ the text which should be made available.
 The second, optional, argument PUSH, has the same meaning as the
 similar argument to `x-set-cut-buffer', which see.")
 
+(make-variable-frame-local 'interprogram-cut-function)
+
 (defvar interprogram-paste-function nil
   "Function to call to get text cut from other programs.
 
@@ -1808,6 +1810,8 @@ most recent string, the function should return nil.  If it is
 difficult to tell whether Emacs or some other program provided the
 current string, it is probably good enough to return nil if the string
 is equal (according to `string=') to the last text Emacs provided.")
+
+(make-variable-frame-local 'interprogram-paste-function)
 \f
 
 
index 77bb6e76732048a74bb4d9901f9c4067c75de2c9..10ac0b9e54bd25071a1960be7038163edc187109 100644 (file)
 (defvar command-line-processed nil
   "Non-nil once command line has been processed.")
 
+(defvar window-system initial-window-system
+  "Name of window system the selected frame is displaying through.
+The value is a symbol--for instance, `x' for X windows.
+The value is nil if the selected frame is on a text-only-terminal.")
+
+(make-variable-frame-local 'window-system)
+
 (defgroup initialization nil
   "Emacs start-up procedure"
   :group 'internal)
@@ -420,37 +427,19 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
        ;; for instance due to a dense colormap.
        (when (or frame-initial-frame
                  ;; If frame-initial-frame has no meaning, do this anyway.
-                 (not (and window-system
+                 (not (and initial-window-system
                            (not noninteractive)
-                           (not (eq window-system 'pc)))))
+                           (not (eq initial-window-system 'pc)))))
          ;; Modify the initial frame based on what .emacs puts into
          ;; ...-frame-alist.
          (if (fboundp 'frame-notice-user-settings)
              (frame-notice-user-settings))
+         ;; Set the faces for the initial background mode even if
+         ;; frame-notice-user-settings didn't (such as on a tty).
+         ;; frame-set-background-mode is idempotent, so it won't
+         ;; cause any harm if it's already been done.
          (if (fboundp 'frame-set-background-mode)
-             ;; Set the faces for the initial background mode even if
-             ;; frame-notice-user-settings didn't (such as on a tty).
-             ;; frame-set-background-mode is idempotent, so it won't
-             ;; cause any harm if it's already been done.
-             (let ((frame-background-mode frame-background-mode)
-                   (frame (selected-frame))
-                   term)
-               (when (and (null window-system)
-                          ;; Don't override a possibly customized value.
-                          (null frame-background-mode)
-                          ;; Don't override user specifications.
-                          (null (frame-parameter frame 'reverse))
-                          (let ((bg (frame-parameter frame 'background-color)))
-                            (or (null bg)
-                                (member bg '(unspecified "unspecified-bg")))))
-                 (setq term (getenv "TERM"))
-                 ;; Some files in lisp/term do a better job with the
-                 ;; background mode, but we leave this here anyway, in
-                 ;; case they remove those files.
-                 (if (string-match "^\\(xterm\\|rxvt\\|dtterm\\|eterm\\)"
-                                   term)
-                     (setq frame-background-mode 'light)))
-               (frame-set-background-mode (selected-frame)))))
+             (frame-set-background-mode (selected-frame))))
 
        ;; Now we know the user's default font, so add it to the menu.
        (if (fboundp 'font-menu-add-default)
@@ -491,6 +480,20 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
 (defvar tool-bar-originally-present nil
   "Non-nil if tool-bars are present before user and site init files are read.")
 
+(defvar handle-args-function-alist '((nil . tty-handle-args))
+  "Functions for processing window-system dependent command-line arguments.
+Window system startup files should add their own function to this
+alist, which should parse the command line arguments.  Those
+pertaining to the window system should be processed and removed
+from the returned command line.")
+
+(defvar window-system-initialization-alist '((nil . ignore))
+  "Alist of window-system initialization functions.
+Window-system startup files should add their own initialization
+function to this list.  The function should take no arguments,
+and initialize the window system environment to prepare for
+opening the first frame (e.g. open a connection to the server).")
+
 ;; Handle the X-like command-line arguments "-fg", "-bg", "-name", etc.
 (defun tty-handle-args (args)
   (let (rest)
@@ -608,16 +611,22 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     (setq eol-mnemonic-dos  "(DOS)"
           eol-mnemonic-mac  "(Mac)")))
 
-  ;; Read window system's init file if using a window system.
+  ;; Make sure window system's init file was loaded in loadup.el if using a window system.
   (condition-case error
-      (if (and window-system (not noninteractive))
-         (load (concat term-file-prefix
-                       (symbol-name window-system)
-                       "-win")
-               ;; Every window system should have a startup file;
-               ;; barf if we can't find it.
-               nil t))
-    ;; If we can't read it, print the error message and exit.
+    (unless noninteractive
+      (if (and initial-window-system
+              (not (featurep
+                    (intern (concat (symbol-name initial-window-system) "-win")))))
+         (error "Unsupported window system `%s'" initial-window-system))
+      ;; Process window-system specific command line parameters.
+      (setq command-line-args
+           (funcall (or (cdr (assq initial-window-system handle-args-function-alist))
+                        (error "Unsupported window system `%s'" initial-window-system))
+                    command-line-args))
+      ;; Initialize the window system. (Open connection, etc.)
+      (funcall (or (cdr (assq initial-window-system window-system-initialization-alist))
+                  (error "Unsupported window system `%s'" initial-window-system))))
+    ;; If there was an error, print the error message and exit.
     (error
      (princ
       (if (eq (car error) 'error)
@@ -633,13 +642,9 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
                              (cdr error) ", "))))
       'external-debugging-output)
      (terpri 'external-debugging-output)
-     (setq window-system nil)
+     (setq initial-window-system nil)
      (kill-emacs)))
 
-  ;; Windowed displays do this inside their *-win.el.
-  (unless (or (display-graphic-p) noninteractive)
-    (setq command-line-args (tty-handle-args command-line-args)))
-
   (set-locale-environment nil)
 
   ;; Convert the arguments to Emacs internal representation.
@@ -716,7 +721,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
 
   ;; If frame was created with a menu bar, set menu-bar-mode on.
   (unless (or noninteractive
-              (and (memq window-system '(x w32))
+              (and (memq initial-window-system '(x w32))
                    (<= (frame-parameter nil 'menu-bar-lines) 0)))
     (menu-bar-mode 1))
 
@@ -726,10 +731,10 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
               (<= (frame-parameter nil 'tool-bar-lines) 0))
     (tool-bar-mode 1))
 
-  ;; Can't do this init in defcustom because window-system isn't set.
+  ;; Can't do this init in defcustom because initial-window-system isn't set.
   (unless (or noninteractive
               (eq system-type 'ms-dos)
-              (not (memq window-system '(x w32))))
+              (not (memq initial-window-system '(x w32))))
     (setq-default blink-cursor t)
     (blink-cursor-mode 1))
 
@@ -737,13 +742,13 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
     ;; DOS/Windows systems have a PC-type keyboard which has both
     ;; <delete> and <backspace> keys.
     (when (or (memq system-type '(ms-dos windows-nt))
-             (and (memq window-system '(x))
+             (and (memq initial-window-system '(x))
                   (fboundp 'x-backspace-delete-keys-p)
                   (x-backspace-delete-keys-p))
              ;; If the terminal Emacs is running on has erase char
              ;; set to ^H, use the Backspace key for deleting
              ;; backward and, and the Delete key for deleting forward.
-             (and (null window-system)
+             (and (null initial-window-system)
                   (eq tty-erase-char 8)))
       (setq-default normal-erase-is-backspace t)
       (normal-erase-is-backspace-mode 1)))
@@ -756,11 +761,10 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
 
   ;; Register default TTY colors for the case the terminal hasn't a
   ;; terminal init file.
-  (unless (memq window-system '(x w32))
-    ;; We do this regardles of whether the terminal supports colors
-    ;; or not, since they can switch that support on or off in
-    ;; mid-session by setting the tty-color-mode frame parameter.
-    (tty-register-default-colors))
+  ;; We do this regardles of whether the terminal supports colors
+  ;; or not, since they can switch that support on or off in
+  ;; mid-session by setting the tty-color-mode frame parameter.
+  (tty-register-default-colors)
 
   ;; Record whether the tool-bar is present before the user and site
   ;; init files are processed.  frame-notice-user-settings uses this
@@ -954,7 +958,7 @@ or `CVS', and any subdirectory that contains a file named `.nosearch'."
   ;; Load library for our terminal type.
   ;; User init file can set term-file-prefix to nil to prevent this.
   (unless (or noninteractive
-              window-system
+              initial-window-system
               (null term-file-prefix))
     (let ((term (getenv "TERM"))
           hyphend)
index bbe9c949ddeea74d0884c2872d76d2c5336ecb10..6d542b0f99bc6832ea1818296f7c0c9084823191 100644 (file)
@@ -45,6 +45,20 @@ Each element has the form (DISPLAY FRAME BUFFER).")
   ;; Add the new buffers to all talk frames.
   (talk-update-buffers))
 
+;;;###autoload
+(defun talk ()
+  "Connect to the Emacs talk group from the current X display or tty frame."
+  (interactive)
+  (let ((type (frame-live-p (selected-frame))))
+    (if (eq type t)
+       ;; Termcap frame
+       (talk-add-tty-frame (selected-frame))
+      (if (eq type 'x)
+         ;; X frame
+         (talk-add-display (frame-parameter (selected-frame) 'display))
+       (error "Could not determine frame type"))))
+  (talk-update-buffers))
+
 (defun talk-add-display (display)
   (let* ((elt (assoc display talk-display-alist))
         (name (concat "*talk-" display "*"))
@@ -56,6 +70,21 @@ Each element has the form (DISPLAY FRAME BUFFER).")
     (setq talk-display-alist
          (cons (list display frame buffer) (delq elt talk-display-alist)))))
 
+(defun talk-add-tty-frame (frame)
+  (let* ((elt (assoc (frame-tty-name frame) talk-display-alist))
+        (name (concat "*talk-" (frame-tty-name frame) "*"))
+        buffer)
+    (if (not (and elt (buffer-name (get-buffer (setq buffer (nth 2 elt))))))
+       (setq buffer (get-buffer-create name)))
+    (add-to-list 'delete-tty-after-functions 'talk-handle-delete-tty)
+    (setq talk-display-alist
+         (cons (list (frame-tty-name frame) frame buffer) (delq elt talk-display-alist)))))
+
+(defun talk-handle-delete-tty (tty)
+  (let ((elt (assoc tty talk-display-alist)))
+    (setq talk-display-alist (delq elt talk-display-alist))
+    (talk-update-buffers)))
+
 (defun talk-disconnect ()
   "Disconnect this display from the Emacs talk group."
   (interactive)
index 4b419a57a978210287fed0d48a5466661d51e448..cd26352a96232ea7feaf06c7d09807bedbec0f6a 100644 (file)
 
 ;;; Commentary:
 
-;; X-win.el:  this file is loaded from ../lisp/startup.el when it recognizes
-;; that X windows are to be used.  Command line switches are parsed and those
-;; pertaining to X are processed and removed from the command line.  The
-;; X display is opened and hooks are set for popping up the initial window.
+;; X-win.el: this file defines functions to initialize the X window
+;; system and process X-specific command line parameters before
+;; creating the first X frame.
+
+;; Note that contrary to previous Emacs versions, the act of loading
+;; this file should not have the side effect of initializing the
+;; window system or processing command line arguments (this file is
+;; now loaded in loadup.el).  See the variables
+;; `handle-args-function-alist' and
+;; `window-system-initialization-alist' for more details.
 
 ;; startup.el will then examine startup files, and eventually call the hooks
 ;; which create the first window(s).
@@ -66,7 +72,7 @@
 ;; An alist of X options and the function which handles them.  See
 ;; ../startup.el.
 
-(if (not (eq window-system 'x))
+(if (not (fboundp 'x-create-frame))
     (error "%s: Loading x-win.el but not compiled for X" (invocation-name)))
 
 (require 'frame)
@@ -1160,9 +1166,6 @@ XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp")
 \f
 ;;;; Function keys
 
-(substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
-                          global-map)
-
 ;; Map certain keypad keys into ASCII characters
 ;; that people usually expect.
 (define-key function-key-map [backspace] [127])
@@ -2237,7 +2240,7 @@ order until succeed.")
     (if text
        (remove-text-properties 0 (length text) '(foreign-selection nil) text))
     text))
-      
+
 ;;; Return the value of the current X selection.
 ;;; Consult the selection, and the cut buffer.  Treat empty strings
 ;;; as if they were unset.
@@ -2328,146 +2331,149 @@ order until succeed.")
     (or clip-text primary-text cut-text)
     ))
 
-\f
-;;; Do the actual X Windows setup here; the above code just defines
-;;; functions and variables that we use now.
-
-(setq command-line-args (x-handle-args command-line-args))
-
-;;; Make sure we have a valid resource name.
-(or (stringp x-resource-name)
-    (let (i)
-      (setq x-resource-name (invocation-name))
-
-      ;; Change any . or * characters in x-resource-name to hyphens,
-      ;; so as not to choke when we use it in X resource queries.
-      (while (setq i (string-match "[.*]" x-resource-name))
-       (aset x-resource-name i ?-))))
-
-(x-open-connection (or x-display-name
-                      (setq x-display-name (getenv "DISPLAY")))
-                  x-command-line-resources
-                  ;; Exit Emacs with fatal error if this fails.
-                  t)
-
-(setq frame-creation-function 'x-create-frame-with-faces)
-
-(setq x-cut-buffer-max (min (- (/ (x-server-max-request-size) 2) 100)
-                           x-cut-buffer-max))
-
-;; Setup the default fontset.
-(setup-default-fontset)
-
-;; Create the standard fontset.
-(create-fontset-from-fontset-spec standard-fontset-spec t)
-
-;; Create fontset specified in X resources "Fontset-N" (N is 0, 1, ...).
-(create-fontset-from-x-resource)
-
-;; Try to create a fontset from a font specification which comes
-;; from initial-frame-alist, default-frame-alist, or X resource.
-;; A font specification in command line argument (i.e. -fn XXXX)
-;; should be already in default-frame-alist as a `font'
-;; parameter.  However, any font specifications in site-start
-;; library, user's init file (.emacs), and default.el are not
-;; yet handled here.
-
-(let ((font (or (cdr (assq 'font initial-frame-alist))
-               (cdr (assq 'font default-frame-alist))
-               (x-get-resource "font" "Font")))
-      xlfd-fields resolved-name)
-  (if (and font
-          (not (query-fontset font))
-          (setq resolved-name (x-resolve-font-name font))
-          (setq xlfd-fields (x-decompose-font-name font)))
-      (if (string= "fontset" (aref xlfd-fields xlfd-regexp-registry-subnum))
-         (new-fontset font (x-complement-fontset-spec xlfd-fields nil))
-       ;; Create a fontset from FONT.  The fontset name is
-       ;; generated from FONT.
-       (create-fontset-from-ascii-font font resolved-name "startup"))))
-
-;; Apply a geometry resource to the initial frame.  Put it at the end
-;; of the alist, so that anything specified on the command line takes
-;; precedence.
-(let* ((res-geometry (x-get-resource "geometry" "Geometry"))
-       parsed)
-  (if res-geometry
-      (progn
-       (setq parsed (x-parse-geometry res-geometry))
-       ;; If the resource specifies a position,
-       ;; call the position and size "user-specified".
-       (if (or (assq 'top parsed) (assq 'left parsed))
-           (setq parsed (cons '(user-position . t)
-                              (cons '(user-size . t) parsed))))
-       ;; All geometry parms apply to the initial frame.
-       (setq initial-frame-alist (append initial-frame-alist parsed))
-       ;; The size parms apply to all frames.
-       (if (assq 'height parsed)
-           (setq default-frame-alist
-                 (cons (cons 'height (cdr (assq 'height parsed)))
-                       default-frame-alist)))
-       (if (assq 'width parsed)
-           (setq default-frame-alist
-                 (cons (cons 'width (cdr (assq 'width parsed)))
-                       default-frame-alist))))))
-
-;; Check the reverseVideo resource.
-(let ((case-fold-search t))
-  (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
-    (if (and rv
-            (string-match "^\\(true\\|yes\\|on\\)$" rv))
-       (setq default-frame-alist
-             (cons '(reverse . t) default-frame-alist)))))
+(defun x-clipboard-yank ()
+  "Insert the clipboard contents, or the last stretch of killed text."
+  (interactive)
+  (let ((clipboard-text (x-get-selection 'CLIPBOARD))
+       (x-select-enable-clipboard t))
+    (if (and clipboard-text (> (length clipboard-text) 0))
+       (kill-new clipboard-text))
+    (yank)))
 
-;; Set x-selection-timeout, measured in milliseconds.
-(let ((res-selection-timeout
-       (x-get-resource "selectionTimeout" "SelectionTimeout")))
-  (setq x-selection-timeout 20000)
-  (if res-selection-timeout
-      (setq x-selection-timeout (string-to-number res-selection-timeout))))
+\f
+;;; Window system initialization.
 
 (defun x-win-suspend-error ()
   (error "Suspending an Emacs running under X makes no sense"))
-(add-hook 'suspend-hook 'x-win-suspend-error)
 
-;;; Arrange for the kill and yank functions to set and check the clipboard.
-(setq interprogram-cut-function 'x-select-text)
-(setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
+(defvar x-initialized nil
+  "Non-nil if the X window system has been initialized.")
+
+(defun x-initialize-window-system ()
+  "Initialize Emacs for X frames and open the first connection to an X server."
+  ;; Make sure we have a valid resource name.
+  (or (stringp x-resource-name)
+      (let (i)
+       (setq x-resource-name (invocation-name))
+
+       ;; Change any . or * characters in x-resource-name to hyphens,
+       ;; so as not to choke when we use it in X resource queries.
+       (while (setq i (string-match "[.*]" x-resource-name))
+         (aset x-resource-name i ?-))))
+
+  (x-open-connection (or x-display-name
+                        (setq x-display-name (getenv "DISPLAY")))
+                    x-command-line-resources
+                    ;; Exit Emacs with fatal error if this fails and we
+                    ;; are the initial display.
+                    (eq initial-window-system 'x))
+
+  (setq x-cut-buffer-max (min (- (/ (x-server-max-request-size) 2) 100)
+                             x-cut-buffer-max))
+
+  ;; Setup the default fontset.
+  (setup-default-fontset)
+
+  ;; Create the standard fontset.
+  (create-fontset-from-fontset-spec standard-fontset-spec t)
+
+  ;; Create fontset specified in X resources "Fontset-N" (N is 0, 1, ...).
+  (create-fontset-from-x-resource)
+
+  ;; Try to create a fontset from a font specification which comes
+  ;; from initial-frame-alist, default-frame-alist, or X resource.
+  ;; A font specification in command line argument (i.e. -fn XXXX)
+  ;; should be already in default-frame-alist as a `font'
+  ;; parameter.  However, any font specifications in site-start
+  ;; library, user's init file (.emacs), and default.el are not
+  ;; yet handled here.
+
+  (let ((font (or (cdr (assq 'font initial-frame-alist))
+                 (cdr (assq 'font default-frame-alist))
+                 (x-get-resource "font" "Font")))
+       xlfd-fields resolved-name)
+    (if (and font
+            (not (query-fontset font))
+            (setq resolved-name (x-resolve-font-name font))
+            (setq xlfd-fields (x-decompose-font-name font)))
+       (if (string= "fontset" (aref xlfd-fields xlfd-regexp-registry-subnum))
+           (new-fontset font (x-complement-fontset-spec xlfd-fields nil))
+         ;; Create a fontset from FONT.  The fontset name is
+         ;; generated from FONT.
+         (create-fontset-from-ascii-font font resolved-name "startup"))))
+
+  ;; Apply a geometry resource to the initial frame.  Put it at the end
+  ;; of the alist, so that anything specified on the command line takes
+  ;; precedence.
+  (let* ((res-geometry (x-get-resource "geometry" "Geometry"))
+        parsed)
+    (if res-geometry
+       (progn
+         (setq parsed (x-parse-geometry res-geometry))
+         ;; If the resource specifies a position,
+         ;; call the position and size "user-specified".
+         (if (or (assq 'top parsed) (assq 'left parsed))
+             (setq parsed (cons '(user-position . t)
+                                (cons '(user-size . t) parsed))))
+         ;; All geometry parms apply to the initial frame.
+         (setq initial-frame-alist (append initial-frame-alist parsed))
+         ;; The size parms apply to all frames.
+         (if (assq 'height parsed)
+             (setq default-frame-alist
+                   (cons (cons 'height (cdr (assq 'height parsed)))
+                         default-frame-alist)))
+         (if (assq 'width parsed)
+             (setq default-frame-alist
+                   (cons (cons 'width (cdr (assq 'width parsed)))
+                         default-frame-alist))))))
+
+  ;; Check the reverseVideo resource.
+  (let ((case-fold-search t))
+    (let ((rv (x-get-resource "reverseVideo" "ReverseVideo")))
+      (if (and rv
+              (string-match "^\\(true\\|yes\\|on\\)$" rv))
+         (setq default-frame-alist
+               (cons '(reverse . t) default-frame-alist)))))
 
-;;; Turn off window-splitting optimization; X is usually fast enough
-;;; that this is only annoying.
-(setq split-window-keep-point t)
+  ;; Set x-selection-timeout, measured in milliseconds.
+  (let ((res-selection-timeout
+        (x-get-resource "selectionTimeout" "SelectionTimeout")))
+    (setq x-selection-timeout 20000)
+    (if res-selection-timeout
+       (setq x-selection-timeout (string-to-number res-selection-timeout))))
 
-;; Don't show the frame name; that's redundant with X.
-(setq-default mode-line-frame-identification "  ")
+  ;; Don't let Emacs suspend under X.
+  (add-hook 'suspend-hook 'x-win-suspend-error)
 
-;; Motif direct handling of f10 wasn't working right,
-;; So temporarily we've turned it off in lwlib-Xm.c
-;; and turned the Emacs f10 back on.
-;; ;; Motif normally handles f10 itself, so don't try to handle it a second time.
-;; (if (featurep 'motif)
-;;     (global-set-key [f10] 'ignore))
+  ;; Turn off window-splitting optimization; X is usually fast enough
+  ;; that this is only annoying.
+  (setq split-window-keep-point t)
 
-;; Turn on support for mouse wheels.
-(mouse-wheel-mode 1)
+  ;; Motif direct handling of f10 wasn't working right,
+  ;; So temporarily we've turned it off in lwlib-Xm.c
+  ;; and turned the Emacs f10 back on.
+  ;; ;; Motif normally handles f10 itself, so don't try to handle it a second time.
+  ;; (if (featurep 'motif)
+  ;;     (global-set-key [f10] 'ignore))
 
+  ;; Turn on support for mouse wheels.
+  (mouse-wheel-mode 1)
 
-;; Enable CLIPBOARD copy/paste through menu bar commands.
-(menu-bar-enable-clipboard)
+  ;; Enable CLIPBOARD copy/paste through menu bar commands.
+  (menu-bar-enable-clipboard)
 
-;; Override Paste so it looks at CLIPBOARD first.
-(defun x-clipboard-yank ()
-  "Insert the clipboard contents, or the last stretch of killed text."
-  (interactive)
-  (let ((clipboard-text (x-get-selection 'CLIPBOARD))
-       (x-select-enable-clipboard t))
-    (if (and clipboard-text (> (length clipboard-text) 0))
-       (kill-new clipboard-text))
-    (yank)))
+  ;; Override Paste so it looks at CLIPBOARD first.
+  (define-key menu-bar-edit-menu [paste]
+    (cons "Paste" (cons "Paste text from clipboard or kill ring"
+                       'x-clipboard-yank)))
+
+  (setq x-initialized t))
+
+(add-to-list 'handle-args-function-alist '(x . x-handle-args))
+(add-to-list 'frame-creation-function-alist '(x . x-create-frame-with-faces))
+(add-to-list 'window-system-initialization-alist '(x . x-initialize-window-system))
 
-(define-key menu-bar-edit-menu [paste]
-  (cons "Paste" (cons "Paste text from clipboard or kill ring"
-                     'x-clipboard-yank)))
+(provide 'x-win)
 
 ;; Initiate drag and drop
 (add-hook 'after-make-frame-functions 'x-dnd-init-frame)
index d66646876b1b691e755d69714fba803fa9c567bd..5c387cb4148911e80c7dfcc7e4323476d8943bd9 100644 (file)
@@ -123,7 +123,7 @@ for the currently selected frame.  The first 16 colors are taken from
 `xterm-standard-colors', which see, while the rest are computed assuming
 either the 88- or 256-color standard color scheme supported by latest
 versions of xterm."
-  (let* ((ncolors (display-color-cells))
+  (let* ((ncolors (display-color-cells (selected-frame)))
         (colors xterm-standard-colors)
         (color (car colors)))
     (if (> ncolors 0)
index 0c1e6bc17455d86ec01fd0f5778bbabaf76714eb..338300b371850f350781123b784d3b6c48db907c 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author:      FSF (see vc.el for full credits)
 ;; Maintainer:  Andre Spiegel <spiegel@gnu.org>
 
-;; $Id: vc-cvs.el,v 1.67 2004/01/20 17:41:18 uid65624 Exp $
+;; $Id: vc-cvs.el,v 1.68 2004/03/21 15:45:31 spiegel Exp $
 
 ;; This file is part of GNU Emacs.
 
index f08c5fc1dfa8533a0d0bada53c16a173200e0c4e..904a8f0ccd25d084b7aff902e73d8f86c0a1a203 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author:     FSF (see vc.el for full credits)
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
 
-;; $Id: vc-hooks.el,v 1.164 2004/03/26 06:06:39 spiegel Exp $
+;; $Id: vc-hooks.el,v 1.165 2004/03/28 17:38:03 monnier Exp $
 
 ;; This file is part of GNU Emacs.
 
index 02dc093ed5a86276ac1eafbfbc4056c82a72cfac..a730522ef059e5d71350d63c1a7075b53dfbc1b0 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author:     FSF (see vc.el for full credits)
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
 
-;; $Id: vc-rcs.el,v 1.38 2003/09/01 15:45:17 miles Exp $
+;; $Id: vc-rcs.el,v 1.39 2004/03/21 15:46:23 spiegel Exp $
 
 ;; This file is part of GNU Emacs.
 
index 1649349e0bd56e63acc15e83d7627cf61b00bb96..1e626b5709e801eb47fc91b0831ef66d773aa693 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author:     FSF (see vc.el for full credits)
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
 
-;; $Id: vc-sccs.el,v 1.24 2003/09/01 15:45:17 miles Exp $
+;; $Id: vc-sccs.el,v 1.25 2004/03/21 15:49:55 spiegel Exp $
 
 ;; This file is part of GNU Emacs.
 
index 5ef33045b328b2924ea4b087965e173b4fee6594..9e1f36f93ceea21e5a45438cff2345dc0fa5b13e 100644 (file)
@@ -7,7 +7,7 @@
 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
 ;; Keywords: tools
 
-;; $Id: vc.el,v 1.373 2004/03/26 16:17:12 monnier Exp $
+;; $Id: vc.el,v 1.374 2004/03/28 22:00:19 monnier Exp $
 
 ;; This file is part of GNU Emacs.
 
index 42dbb3f9c2565e7a22e9d0a18ebf436f77207d99..6c99d8de1d64d5f4b92efc8f21f1bee5acfee55a 100644 (file)
@@ -55,8 +55,8 @@ to the system configuration; look at `system-configuration' instead."
   (interactive "P")
   (let ((version-string
          (format (if (not (interactive-p))
-                    "GNU Emacs %s (%s%s%s)\n of %s on %s"
-                  "GNU Emacs %s (%s%s%s) of %s on %s")
+                    "GNU Emacs %s (%s%s%s%s)\n of %s on %s"
+                  "GNU Emacs %s (%s%s%s%s) of %s on %s")
                  emacs-version
                 system-configuration
                 (cond ((featurep 'motif)
@@ -70,6 +70,7 @@ to the system configuration; look at `system-configuration' instead."
                     (format ", %s scroll bars"
                             (capitalize (symbol-name x-toolkit-scroll-bars)))
                   "")
+                (if (featurep 'multi-tty) ", multi-tty" "")
                 (format-time-string "%Y-%m-%d" emacs-build-time)
                  emacs-build-system)))
     (if here
index cdb0a63ace616f042e1634a38f0e78cfad2ed9c3..41e9e3e78b2a886eb4d255ccf9a70aac2d7069c0 100644 (file)
@@ -142,8 +142,9 @@ any protocol specific data.")
 
 (defun x-dnd-init-frame (&optional frame)
   "Setup drag and drop for FRAME (i.e. create appropriate properties)."
-  (x-dnd-init-xdnd-for-frame frame)
-  (x-dnd-init-motif-for-frame frame))
+  (when (eq 'x (window-system frame))
+    (x-dnd-init-xdnd-for-frame frame)
+    (x-dnd-init-motif-for-frame frame)))
 
 (defun x-dnd-get-state-cons-for-frame (frame-or-window)
   "Return the entry in x-dnd-current-state for a frame or window."
index a01481be4367766ce36f7f062d32cb1166e3d481..62aef7a556ff0f36ed56e9a79c1075fa2566b2cc 100644 (file)
@@ -4,7 +4,7 @@
 # Created: 1993-05-16
 # Public domain
 
-# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
+# $Id: mkinstalldirs,v 1.1 2001/11/24 08:45:51 eliz Exp $
 
 errstatus=0
 
index a01481be4367766ce36f7f062d32cb1166e3d481..5df7a14a9f491cd89a781638c393689d507d6dd1 100755 (executable)
@@ -4,7 +4,7 @@
 # Created: 1993-05-16
 # Public domain
 
-# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
+# $Id: mkinstalldirs,v 1.1 2000/07/28 12:48:04 gerd Exp $
 
 errstatus=0
 
index f5b179b6b7e2195a75fe0747e0eccdd04d300a8a..ca30f70c0b00b370ee031ae4ea45f4fec157a767 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo  @c -*-texinfo-*-
-@c "@(#)$Name:  $:$Id: eshell.texi,v 1.19 2003/09/01 15:45:45 miles Exp $"
+@c "@(#)$Name:  $:$Id: eshell.texi,v 1.20 2003/11/26 17:12:11 ttn Exp $"
 @c %**start of header
 @setfilename ../info/eshell
 @settitle Eshell: The Emacs Shell
index efecc1d927deeaa59011753cc4b43a0eb04c8a59..07a8078295900875acb85517fce435b5757dd001 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo   @c -*-texinfo-*-
-@c $Id: mh-e.texi,v 1.14 2003/02/04 14:53:28 lektu Exp $
+@c $Id: mh-e.texi,v 1.15 2003/09/01 15:45:46 miles Exp $
 @c %**start of header
 @setfilename ../info/mh-e
 @settitle mh-e
index d557f2a109512021b1c287a216316bdfc22ce502..44b05b9b16dd7a480dc1639db9799239a5312943 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo  @c -*-texinfo-*-
-@c "@(#)$Name:  $:$Id: pcl-cvs.texi,v 1.22 2003/09/29 13:44:26 ttn Exp $"
+@c "@(#)$Name:  $:$Id: pcl-cvs.texi,v 1.23 2003/09/30 20:40:50 rms Exp $"
 @c %**start of header
 @setfilename ../info/pcl-cvs
 @settitle PCL-CVS --- Emacs Front-End to CVS
index 54084b2a430e186eb55a85edcfb2dc109db5c778..4fa51cff389f3816ff69be220d3d6b0bc3850927 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo   @c -*-texinfo-*-
-@c $Id: speedbar.texi,v 1.12 2003/09/01 15:45:46 miles Exp $
+@c $Id: speedbar.texi,v 1.13 2003/10/08 22:02:52 nickrob Exp $
 
 @setfilename ../info/speedbar
 @settitle Speedbar: File/Tag summarizing utility
index 1262d3d5fecb8a0abdd13407e0fcf70be73a5a29..63515780d15c292670e5d86202c40d0aeb62ce67 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo   @c -*-texinfo-*-
-@c $Id: woman.texi,v 1.15 2003/09/30 20:42:15 rms Exp $
+@c $Id: woman.texi,v 1.16 2003/11/02 07:01:19 eliz Exp $
 @c %**start of header
 @setfilename ../info/woman
 @settitle WoMan: Browse Unix Manual Pages ``W.O. (without) Man''
index ef5a91716a6c85268fca978dba2cfe17996504b2..c1f98d2c7f293139da353779428dd948a08441ab 100755 (executable)
@@ -4,7 +4,7 @@
 # Created: 1993-05-16
 # Public domain
 
-# $Id: mkinstalldirs,v 1.1 2001/02/02 13:04:53 gerd Exp $
+# $Id: mkinstalldirs,v 1.2 2001/02/02 13:09:26 gerd Exp $
 
 errstatus=0
 
diff --git a/nt/.arch-inventory b/nt/.arch-inventory
new file mode 100644 (file)
index 0000000..a2db727
--- /dev/null
@@ -0,0 +1,3 @@
+source ^subdirs\.el$
+
+# arch-tag: 01b87183-9d94-4b6b-93cb-fece25c4eec9
index 80ad1e249adde790eb6f9d8f0a35ba65dc010490..1b141a42064ecd8723956882bafe84b522388391 100644 (file)
@@ -437,7 +437,7 @@ set print sevenbit-strings
 
 show environment DISPLAY
 show environment TERM
-set args -geometry 80x40+0+0
+#set args -geometry 80x40+0+0
 
 # Don't let abort actually run, as it will make
 # stdio stop working and therefore the `pr' command above as well.
index 678e4f89f44266a87d5e84c0b7b7728eff77d3fb..618d8de1f968bbc8938eca87c0cd8b3e9b6ad8f4 100644 (file)
@@ -875,7 +875,9 @@ SOME_MACHINE_LISP = ${dotdot}/lisp/mouse.elc \
   ${dotdot}/lisp/w32-fns.elc ${dotdot}/lisp/dos-w32.elc \
   ${dotdot}/lisp/disp-table.elc ${dotdot}/lisp/dos-vars.elc \
   ${dotdot}/lisp/international/ccl.elc \
-  ${dotdot}/lisp/international/codepage.elc
+  ${dotdot}/lisp/international/codepage.elc \
+  ${dotdot}/lisp/mouse.elc ${dotdot}/lisp/international/fontset.elc \
+  ${dotdot}/lisp/x-dnd.elc ${dotdot}/lisp/term/x-win.elc
 
 /* Construct full set of libraries to be linked.
    Note that SunOS needs -lm to come before -lc; otherwise, you get
@@ -1049,7 +1051,7 @@ ccl.o: ccl.c ccl.h charset.h coding.h $(config_h)
 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 cm.h termhooks.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
@@ -1057,7 +1059,7 @@ ecrt0.o: ecrt0.c $(config_h)
        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 \
@@ -1079,7 +1081,7 @@ frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \
    msdos.h dosfns.h dispextern.h $(config_h)
 fringe.o: fringe.c dispextern.h frame.h window.h buffer.h $(config_h)
 fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \
-   keyboard.h $(config_h)
+   keyboard.h termhooks.h $(config_h)
 getloadavg.o: getloadavg.c $(config_h)
 image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \
    systime.h xterm.h w32term.h w32gui.h macterm.h macgui.h $(config_h)
@@ -1090,7 +1092,7 @@ 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)
@@ -1104,7 +1106,7 @@ vm-limit.o: vm-limit.c mem-limits.h $(config_h)
 marker.o: marker.c buffer.h charset.h $(config_h)
 md5.o: md5.c md5.h $(config_h)
 minibuf.o: minibuf.c syntax.h dispextern.h frame.h window.h keyboard.h \
-   buffer.h commands.h charset.h msdos.h $(config_h)
+   buffer.h commands.h charset.h msdos.h termhooks.h $(config_h)
 mktime.o: mktime.c $(config_h)
 msdos.o: msdos.c msdos.h dosfns.h systime.h termhooks.h dispextern.h frame.h \
    termopts.h termchar.h charset.h coding.h ccl.h disptab.h window.h \
@@ -1116,7 +1118,7 @@ process.o: process.c process.h buffer.h window.h termhooks.h termopts.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 termchar.h dispextern.h frame.h msdos.h keyboard.h \
-   $(config_h)
+   termhooks.h $(config_h)
 search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
    blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h)
 strftime.o: strftime.c $(config_h)
@@ -1124,7 +1126,7 @@ syntax.o: syntax.c syntax.h buffer.h commands.h category.h charset.h \
    composite.h $(config_h)
 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  $(config_h)
+   frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h $(config_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)
@@ -1146,10 +1148,11 @@ xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h co
    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 $(config_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 $(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)
@@ -1181,7 +1184,7 @@ floatfns.o: floatfns.c $(config_h)
 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
+   $(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
 
index 7be54aa1ae0acc2218b7b528d6724ce7a108c837..723d664cbe0fbffec15f83858d2f33cc0f15f639 100644 (file)
@@ -256,6 +256,7 @@ EMACS_INT gcs_done;         /* accumulated GCs  */
 
 static void mark_buffer P_ ((Lisp_Object));
 extern void mark_kboards P_ ((void));
+extern void mark_ttys P_ ((void));
 static void gc_sweep P_ ((void));
 static void mark_glyph_matrix P_ ((struct glyph_matrix *));
 static void mark_face_cache P_ ((struct face_cache *));
@@ -4463,6 +4464,7 @@ returns nil, because real GC can't be done.  */)
        mark_object (backlist->args[i]);
     }
   mark_kboards ();
+  mark_ttys ();
 
   /* Look thru every buffer's undo list
      for elements that update markers that were not marked,
index dcff5048460d15cfa23d0cbf5745bbe5df78b1e0..9f9cc0e0a34621b58e2c3909c322ac1899d87f48 100644 (file)
--- a/src/cm.c
+++ b/src/cm.c
@@ -22,8 +22,13 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include <stdio.h>
+
+#include "lisp.h"
+#include "frame.h"
 #include "cm.h"
 #include "termhooks.h"
+#include "termchar.h"
+
 
 /* For now, don't try to include termcap.h.  On some systems,
    configure finds a non-standard termcap.h that the main build
@@ -52,13 +57,16 @@ evalcost (c)
   return c;
 }
 
+/* The terminal to use for low-level output. */
+struct tty_display_info *current_tty;
+
 int
 cmputc (c)
      char c;
 {
-  if (termscript)
-    fputc (c & 0177, termscript);
-  putchar (c & 0177);
+  if (current_tty->termscript)
+    putc (c & 0177, current_tty->termscript);
+  putc (c & 0177, current_tty->output);
   return c;
 }
 
@@ -71,9 +79,9 @@ cmputc (c)
  */
 
 static
-at (row, col) {
-    curY = row;
-    curX = col;
+at (tty, row, col) {
+  curY (tty) = row;
+  curX (tty)  = col;
 }
 
 /*
@@ -81,8 +89,8 @@ at (row, col) {
  */
 
 static
-addcol (n) {
-    curX += n;
+addcol (tty, n) {
+  curX (tty) += n;
 
     /*
      * If cursor hit edge of screen, what happened?
@@ -92,21 +100,21 @@ addcol (n) {
      * of the last line.
      */
 
-    if (curX == Wcm.cm_cols) {
+  if (curX (tty) == tty->Wcm->cm_cols) {
        /*
         * Well, if magicwrap, still there, past the edge of the
         * screen (!).  If autowrap, on the col 0 of the next line.
         * Otherwise on last column.
         */
 
-       if (Wcm.cm_magicwrap)
+       if (tty->Wcm->cm_magicwrap)
            ;                   /* "limbo" */
-       else if (Wcm.cm_autowrap) {
-           curX = 0;
-           curY++;             /* Beware end of screen! */
+       else if (tty->Wcm->cm_autowrap) {
+          curX (tty) = 0;
+          curY (tty) ++;               /* Beware end of screen! */
        }
        else
-           curX--;
+          curX (tty)--;
     }
 }
 #endif
@@ -122,20 +130,20 @@ addcol (n) {
  * after we reach the last column; this takes us to a known state.
  */
 void
-cmcheckmagic ()
+cmcheckmagic (struct tty_display_info *tty)
 {
-  if (curX == FrameCols)
+  if (curX (tty) == FrameCols (tty))
     {
-      if (!MagicWrap || curY >= FrameRows - 1)
+      if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
        abort ();
-      if (termscript)
-       putc ('\r', termscript);
-      putchar ('\r');
-      if (termscript)
-       putc ('\n', termscript);
-      putchar ('\n');
-      curX = 0;
-      curY++;
+      if (tty->termscript)
+       putc ('\r', tty->termscript);
+      putc ('\r', tty->output);
+      if (tty->termscript)
+       putc ('\n', tty->termscript);
+      putc ('\n', tty->output);
+      curX (tty) = 0;
+      curY (tty)++;
     }
 }
 
@@ -147,21 +155,21 @@ cmcheckmagic ()
  */
 
 void
-cmcostinit ()
+cmcostinit (struct tty_display_info *tty)
 {
     char *p;
 
 #define        COST(x,e)       (x ? (cost = 0, tputs (x, 1, e), cost) : BIG)
 #define CMCOST(x,e)    ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e)))
 
-    Wcm.cc_up =                COST (Wcm.cm_up, evalcost);
-    Wcm.cc_down =      COST (Wcm.cm_down, evalcost);
-    Wcm.cc_left =      COST (Wcm.cm_left, evalcost);
-    Wcm.cc_right =     COST (Wcm.cm_right, evalcost);
-    Wcm.cc_home =      COST (Wcm.cm_home, evalcost);
-    Wcm.cc_cr =                COST (Wcm.cm_cr, evalcost);
-    Wcm.cc_ll =                COST (Wcm.cm_ll, evalcost);
-    Wcm.cc_tab =       Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG;
+    tty->Wcm->cc_up =   COST (tty->Wcm->cm_up, evalcost);
+    tty->Wcm->cc_down =         COST (tty->Wcm->cm_down, evalcost);
+    tty->Wcm->cc_left =         COST (tty->Wcm->cm_left, evalcost);
+    tty->Wcm->cc_right = COST (tty->Wcm->cm_right, evalcost);
+    tty->Wcm->cc_home =         COST (tty->Wcm->cm_home, evalcost);
+    tty->Wcm->cc_cr =   COST (tty->Wcm->cm_cr, evalcost);
+    tty->Wcm->cc_ll =   COST (tty->Wcm->cm_ll, evalcost);
+    tty->Wcm->cc_tab =  tty->Wcm->cm_tabwidth ? COST (tty->Wcm->cm_tab, evalcost) : BIG;
 
     /*
      * These last three are actually minimum costs.  When (if) they are
@@ -172,9 +180,9 @@ cmcostinit ()
      * cursor motion seem to take straight numeric values.  --ACT)
      */
 
-    Wcm.cc_abs =  CMCOST (Wcm.cm_abs, evalcost);
-    Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost);
-    Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost);
+    tty->Wcm->cc_abs =  CMCOST (tty->Wcm->cm_abs, evalcost);
+    tty->Wcm->cc_habs = CMCOST (tty->Wcm->cm_habs, evalcost);
+    tty->Wcm->cc_vabs = CMCOST (tty->Wcm->cm_vabs, evalcost);
 
 #undef CMCOST
 #undef COST
@@ -187,8 +195,8 @@ cmcostinit ()
  */
 
 static int
-calccost (srcy, srcx, dsty, dstx, doit)
-     int srcy, srcx, dsty, dstx, doit;
+calccost (struct tty_display_info *tty,
+          int srcy, int srcx, int dsty, int dstx, int doit)
 {
     register int    deltay,
                     deltax,
@@ -205,16 +213,16 @@ calccost (srcy, srcx, dsty, dstx, doit)
        don't believe the cursor position: give up here
        and force use of absolute positioning.  */
 
-    if (curX == Wcm.cm_cols)
+    if (curX (tty) == tty->Wcm->cm_cols)
       goto fail;
 
     totalcost = 0;
     if ((deltay = dsty - srcy) == 0)
        goto x;
     if (deltay < 0)
-       p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay;
+       p = tty->Wcm->cm_up, c = tty->Wcm->cc_up, deltay = -deltay;
     else
-       p = Wcm.cm_down, c = Wcm.cc_down;
+       p = tty->Wcm->cm_down, c = tty->Wcm->cc_down;
     if (c == BIG) {            /* caint get thar from here */
        if (doit)
            printf ("OOPS");
@@ -223,16 +231,16 @@ calccost (srcy, srcx, dsty, dstx, doit)
     totalcost = c * deltay;
     if (doit)
        while (--deltay >= 0)
-           tputs (p, 1, cmputc);
+          emacs_tputs (tty, p, 1, cmputc);
 x:
     if ((deltax = dstx - srcx) == 0)
        goto done;
     if (deltax < 0) {
-       p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+       p = tty->Wcm->cm_left, c = tty->Wcm->cc_left, deltax = -deltax;
        goto dodelta;           /* skip all the tab junk */
     }
     /* Tabs (the toughie) */
-    if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs)
+    if (tty->Wcm->cc_tab >= BIG || !tty->Wcm->cm_usetabs)
        goto olddelta;          /* forget it! */
 
     /*
@@ -243,12 +251,12 @@ x:
      * we will put into tabx (for ntabs) and tab2x (for n2tabs)).
      */
 
-    ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth;
+    ntabs = (deltax + srcx % tty->Wcm->cm_tabwidth) / tty->Wcm->cm_tabwidth;
     n2tabs = ntabs + 1;
-    tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
-    tab2x = tabx + Wcm.cm_tabwidth;
+    tabx = (srcx / tty->Wcm->cm_tabwidth + ntabs) * tty->Wcm->cm_tabwidth;
+    tab2x = tabx + tty->Wcm->cm_tabwidth;
 
-    if (tab2x >= Wcm.cm_cols)  /* too far (past edge) */
+    if (tab2x >= tty->Wcm->cm_cols)    /* too far (past edge) */
        n2tabs = 0;
 
     /*
@@ -256,12 +264,12 @@ x:
      * for using n2tabs, then pick the minimum.
      */
 
-                  /* cost for ntabs     +    cost for right motion */
-    tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right
+                  /* cost for ntabs           +    cost for right motion */
+    tabcost = ntabs ? ntabs * tty->Wcm->cc_tab + (dstx - tabx) * tty->Wcm->cc_right
                    : BIG;
 
-                  /* cost for n2tabs    +    cost for left motion */
-    c = n2tabs  ?    n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left
+                  /* cost for n2tabs          +    cost for left motion */
+    c = n2tabs  ?    n2tabs * tty->Wcm->cc_tab + (tab2x - dstx) * tty->Wcm->cc_left
                : BIG;
 
     if (c < tabcost)           /* then cheaper to overshoot & back up */
@@ -274,11 +282,11 @@ x:
      * See if tabcost is less than just moving right
      */
 
-    if (tabcost < (deltax * Wcm.cc_right)) {
+    if (tabcost < (deltax * tty->Wcm->cc_right)) {
        totalcost += tabcost;   /* use the tabs */
        if (doit)
            while (--ntabs >= 0)
-               tputs (Wcm.cm_tab, 1, cmputc);
+              emacs_tputs (tty, tty->Wcm->cm_tab, 1, cmputc);
        srcx = tabx;
     }
 
@@ -291,9 +299,9 @@ newdelta:
        goto done;
 olddelta:
     if (deltax > 0)
-       p = Wcm.cm_right, c = Wcm.cc_right;
+       p = tty->Wcm->cm_right, c = tty->Wcm->cc_right;
     else
-       p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
+       p = tty->Wcm->cm_left, c = tty->Wcm->cc_left, deltax = -deltax;
 
 dodelta:
     if (c == BIG) {            /* caint get thar from here */
@@ -305,7 +313,7 @@ fail:
     totalcost += c * deltax;
     if (doit)
        while (--deltax >= 0)
-           tputs (p, 1, cmputc);
+          emacs_tputs (tty, p, 1, cmputc);
 done:
     return totalcost;
 }
@@ -323,7 +331,8 @@ losecursor ()
 #define        USECR   3
 
 void
-cmgoto (row, col)
+cmgoto (tty, row, col)
+     struct tty_display_info *tty;
      int row, col;
 {
     int     homecost,
@@ -336,47 +345,47 @@ cmgoto (row, col)
            *dcm;
 
   /* First the degenerate case */
-  if (row == curY && col == curX) /* already there */
+    if (row == curY (tty) && col == curX (tty)) /* already there */
     return;
 
-  if (curY >= 0 && curX >= 0)
+    if (curY (tty) >= 0 && curX (tty) >= 0)
     {
       /* We may have quick ways to go to the upper-left, bottom-left,
        * start-of-line, or start-of-next-line.  Or it might be best to
        * start where we are.  Examine the options, and pick the cheapest.
        */
 
-      relcost = calccost (curY, curX, row, col, 0);
+      relcost = calccost (tty, curY (tty), curX (tty), row, col, 0);
       use = USEREL;
-      if ((homecost = Wcm.cc_home) < BIG)
-         homecost += calccost (0, 0, row, col, 0);
+      if ((homecost = tty->Wcm->cc_home) < BIG)
+          homecost += calccost (tty, 0, 0, row, col, 0);
       if (homecost < relcost)
-         relcost = homecost, use = USEHOME;
-      if ((llcost = Wcm.cc_ll) < BIG)
-         llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
+          relcost = homecost, use = USEHOME;
+      if ((llcost = tty->Wcm->cc_ll) < BIG)
+          llcost += calccost (tty, tty->Wcm->cm_rows - 1, 0, row, col, 0);
       if (llcost < relcost)
-         relcost = llcost, use = USELL;
-      if ((crcost = Wcm.cc_cr) < BIG) {
-         if (Wcm.cm_autolf)
-             if (curY + 1 >= Wcm.cm_rows)
-                 crcost = BIG;
+          relcost = llcost, use = USELL;
+      if ((crcost = tty->Wcm->cc_cr) < BIG) {
+         if (tty->Wcm->cm_autolf)
+            if (curY (tty) + 1 >= tty->Wcm->cm_rows)
+                crcost = BIG;
              else
-                 crcost += calccost (curY + 1, 0, row, col, 0);
+                crcost += calccost (tty, curY (tty) + 1, 0, row, col, 0);
          else
-             crcost += calccost (curY, 0, row, col, 0);
+            crcost += calccost (tty, curY (tty), 0, row, col, 0);
       }
       if (crcost < relcost)
          relcost = crcost, use = USECR;
-      directcost = Wcm.cc_abs, dcm = Wcm.cm_abs;
-      if (row == curY && Wcm.cc_habs < BIG)
-         directcost = Wcm.cc_habs, dcm = Wcm.cm_habs;
-      else if (col == curX && Wcm.cc_vabs < BIG)
-         directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs;
+      directcost = tty->Wcm->cc_abs, dcm = tty->Wcm->cm_abs;
+      if (row == curY (tty) && tty->Wcm->cc_habs < BIG)
+         directcost = tty->Wcm->cc_habs, dcm = tty->Wcm->cm_habs;
+      else if (col == curX (tty) && tty->Wcm->cc_vabs < BIG)
+         directcost = tty->Wcm->cc_vabs, dcm = tty->Wcm->cm_vabs;
     }
   else
     {
       directcost = 0, relcost = 100000;
-      dcm = Wcm.cm_abs;
+      dcm = tty->Wcm->cm_abs;
     }
 
   /*
@@ -387,13 +396,14 @@ cmgoto (row, col)
     {
       /* compute REAL direct cost */
       cost = 0;
-      p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
-                              tgoto (dcm, col, row);
-      tputs (p, 1, evalcost);
+      p = (dcm == tty->Wcm->cm_habs
+           ? tgoto (dcm, row, col)
+           : tgoto (dcm, col, row));
+      emacs_tputs (tty, p, 1, evalcost);
       if (cost <= relcost)
        {       /* really is cheaper */
-         tputs (p, 1, cmputc);
-         curY = row, curX = col;
+         emacs_tputs (tty, p, 1, cmputc);
+         curY (tty) = row, curX (tty) = col;
          return;
        }
     }
@@ -401,25 +411,25 @@ cmgoto (row, col)
   switch (use)
     {
     case USEHOME:
-      tputs (Wcm.cm_home, 1, cmputc);
-      curY = 0, curX = 0;
+      emacs_tputs (tty, tty->Wcm->cm_home, 1, cmputc);
+      curY (tty) = 0, curX (tty) = 0;
       break;
 
     case USELL:
-      tputs (Wcm.cm_ll, 1, cmputc);
-      curY = Wcm.cm_rows - 1, curX = 0;
+      emacs_tputs (tty, tty->Wcm->cm_ll, 1, cmputc);
+      curY (tty) = tty->Wcm->cm_rows - 1, curX (tty) = 0;
       break;
 
     case USECR:
-      tputs (Wcm.cm_cr, 1, cmputc);
-      if (Wcm.cm_autolf)
-       curY++;
-      curX = 0;
+      emacs_tputs (tty, tty->Wcm->cm_cr, 1, cmputc);
+      if (tty->Wcm->cm_autolf)
+       curY (tty)++;
+      curX (tty) = 0;
       break;
     }
 
-  (void) calccost (curY, curX, row, col, 1);
-  curY = row, curX = col;
+  (void) calccost (tty, curY (tty), curX (tty), row, col, 1);
+  curY (tty) = row, curX (tty) = col;
 }
 
 /* Clear out all terminal info.
@@ -427,9 +437,9 @@ cmgoto (row, col)
  */
 
 void
-Wcm_clear ()
+Wcm_clear (struct tty_display_info *tty)
 {
-  bzero (&Wcm, sizeof Wcm);
+  bzero (tty->Wcm, sizeof (struct cm));
   UP = 0;
   BC = 0;
 }
@@ -442,21 +452,21 @@ Wcm_clear ()
  */
 
 int
-Wcm_init ()
+Wcm_init (struct tty_display_info *tty)
 {
 #if 0
-  if (Wcm.cm_abs && !Wcm.cm_ds)
+  if (tty->Wcm->cm_abs && !tty->Wcm->cm_ds)
     return 0;
 #endif
-  if (Wcm.cm_abs)
+  if (tty->Wcm->cm_abs)
     return 0;
   /* Require up and left, and, if no absolute, down and right */
-  if (!Wcm.cm_up || !Wcm.cm_left)
+  if (!tty->Wcm->cm_up || !tty->Wcm->cm_left)
     return - 1;
-  if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
+  if (!tty->Wcm->cm_abs && (!tty->Wcm->cm_down || !tty->Wcm->cm_right))
     return - 1;
   /* Check that we know the size of the screen.... */
-  if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
+  if (tty->Wcm->cm_rows <= 0 || tty->Wcm->cm_cols <= 0)
     return - 2;
   return 0;
 }
index 5500c5ce58ee5eed477efd4bdf5bafeb3b37e40d..1b6c9522bbe2e4f6a116f8ed57790a922523f302 100644 (file)
--- a/src/cm.h
+++ b/src/cm.h
@@ -98,76 +98,78 @@ struct cm
     int cc_vabs;
   };
 
-extern struct cm Wcm;          /* Terminal capabilities */
 extern char PC;                        /* Pad character */
 
 /* Shorthand */
 #ifndef NoCMShortHand
-#define curY           Wcm.cm_curY
-#define curX           Wcm.cm_curX
-#define Up             Wcm.cm_up
-#define Down           Wcm.cm_down
-#define Left           Wcm.cm_left
-#define Right          Wcm.cm_right
-#define Tab            Wcm.cm_tab
-#define BackTab                Wcm.cm_backtab
-#define TabWidth       Wcm.cm_tabwidth
-#define CR             Wcm.cm_cr
-#define Home           Wcm.cm_home
-#define LastLine       Wcm.cm_ll
-#define AbsPosition    Wcm.cm_abs
-#define ColPosition    Wcm.cm_habs
-#define RowPosition    Wcm.cm_vabs
-#define MultiUp                Wcm.cm_multiup
-#define MultiDown      Wcm.cm_multidown
-#define MultiLeft      Wcm.cm_multileft
-#define MultiRight     Wcm.cm_multiright
-#define AutoWrap       Wcm.cm_autowrap
-#define MagicWrap      Wcm.cm_magicwrap
-#define UseTabs                Wcm.cm_usetabs
-#define FrameRows      Wcm.cm_rows
-#define FrameCols      Wcm.cm_cols
-
-#define UpCost         Wcm.cc_up
-#define DownCost       Wcm.cc_down
-#define LeftCost       Wcm.cc_left
-#define RightCost      Wcm.cc_right
-#define HomeCost       Wcm.cc_home
-#define CRCost         Wcm.cc_cr
-#define LastLineCost   Wcm.cc_ll
-#define TabCost                Wcm.cc_tab
-#define BackTabCost    Wcm.cc_backtab
-#define AbsPositionCost        Wcm.cc_abs
-#define ColPositionCost        Wcm.cc_habs
-#define RowPositionCost        Wcm.cc_vabs
-#define MultiUpCost    Wcm.cc_multiup
-#define MultiDownCost  Wcm.cc_multidown
-#define MultiLeftCost  Wcm.cc_multileft
-#define MultiRightCost Wcm.cc_multiright
+#define curY(tty)              (tty)->Wcm->cm_curY
+#define curX(tty)              (tty)->Wcm->cm_curX
+#define Up(tty)                        (tty)->Wcm->cm_up
+#define Down(tty)              (tty)->Wcm->cm_down
+#define Left(tty)              (tty)->Wcm->cm_left
+#define Right(tty)             (tty)->Wcm->cm_right
+#define Tab(tty)               (tty)->Wcm->cm_tab
+#define BackTab(tty)           (tty)->Wcm->cm_backtab
+#define TabWidth(tty)          (tty)->Wcm->cm_tabwidth
+#define CR(tty)                        (tty)->Wcm->cm_cr
+#define Home(tty)              (tty)->Wcm->cm_home
+#define LastLine(tty)          (tty)->Wcm->cm_ll
+#define AbsPosition(tty)       (tty)->Wcm->cm_abs
+#define ColPosition(tty)       (tty)->Wcm->cm_habs
+#define RowPosition(tty)       (tty)->Wcm->cm_vabs
+#define MultiUp(tty)           (tty)->Wcm->cm_multiup
+#define MultiDown(tty)         (tty)->Wcm->cm_multidown
+#define MultiLeft(tty)         (tty)->Wcm->cm_multileft
+#define MultiRight(tty)                (tty)->Wcm->cm_multiright
+#define AutoWrap(tty)          (tty)->Wcm->cm_autowrap
+#define MagicWrap(tty)         (tty)->Wcm->cm_magicwrap
+#define UseTabs(tty)           (tty)->Wcm->cm_usetabs
+#define FrameRows(tty)         (tty)->Wcm->cm_rows
+#define FrameCols(tty)         (tty)->Wcm->cm_cols
+
+#define UpCost(tty)            (tty)->Wcm->cc_up
+#define DownCost(tty)          (tty)->Wcm->cc_down
+#define LeftCost(tty)          (tty)->Wcm->cc_left
+#define RightCost(tty)         (tty)->Wcm->cc_right
+#define HomeCost(tty)          (tty)->Wcm->cc_home
+#define CRCost(tty)            (tty)->Wcm->cc_cr
+#define LastLineCost(tty)      (tty)->Wcm->cc_ll
+#define TabCost(tty)           (tty)->Wcm->cc_tab
+#define BackTabCost(tty)       (tty)->Wcm->cc_backtab
+#define AbsPositionCost(tty)   (tty)->Wcm->cc_abs
+#define ColPositionCost(tty)   (tty)->Wcm->cc_habs
+#define RowPositionCost(tty)   (tty)->Wcm->cc_vabs
+#define MultiUpCost(tty)       (tty)->Wcm->cc_multiup
+#define MultiDownCost(tty)     (tty)->Wcm->cc_multidown
+#define MultiLeftCost(tty)     (tty)->Wcm->cc_multileft
+#define MultiRightCost(tty)    (tty)->Wcm->cc_multiright
 #endif
 
-#define cmat(row,col)  (curY = (row), curX = (col))
-#define cmplus(n)                                      \
-  {                                                    \
-    if ((curX += (n)) >= FrameCols && !MagicWrap)      \
-      {                                                        \
-       if (Wcm.cm_losewrap) losecursor ();             \
-       else if (AutoWrap) curX = 0, curY++;            \
-       else curX--;                                    \
-      }                                                        \
+#define cmat(tty,row,col)      (curY(tty) = (row), curX(tty) = (col))
+#define cmplus(tty,n)                                              \
+  {                                                                 \
+    if ((curX (tty) += (n)) >= FrameCols (tty) && !MagicWrap (tty)) \
+      {                                                             \
+       if ((tty)->Wcm->cm_losewrap) losecursor (tty);              \
+       else if (AutoWrap (tty)) curX (tty) = 0, curY (tty)++;      \
+       else curX (tty)--;                                          \
+      }                                                             \
   }
 
-#define losecursor()   (curX = -1, curY = -1)
+#define losecursor(tty)         (curX(tty) = -1, curY(tty) = -1)
 
 extern int cost;
 extern int evalcost ();
 
-extern void cmcheckmagic ();
-extern int cmputc ();
-extern void cmcostinit ();
-extern void cmgoto ();
-extern void Wcm_clear ();
-extern int Wcm_init ();
+#define emacs_tputs(tty, str, affcnt, putc) (current_tty = (tty), tputs (str, affcnt, putc))
+
+extern struct tty_display_info *current_tty;
+extern void cmcheckmagic P_ ((struct tty_display_info *));
+extern int cmputc P_ ((int));
+extern void cmcostinit P_ ((struct tty_display_info *));
+extern void cmgoto P_ ((struct tty_display_info *, int, int));
+extern void Wcm_clear P_ ((struct tty_display_info *));
+extern int Wcm_init P_ ((struct tty_display_info *));
 
 /* arch-tag: acc1535a-7136-49d6-b22d-9bc85702251b
    (do not change this comment) */
index 0fb4b3f3444715809e47cab8efb4b5881f810a2a..4fe82cd8f2ddfc951f18a0b9782c1bb9a597e6a9 100644 (file)
@@ -863,6 +863,12 @@ Boston, MA 02111-1307, USA.  */
 #define HAVE_MOUSE
 #endif
 
+/* Multi-tty support relies on MULTI_KBOARD.  It seems safe to turn it
+   on unconditionally. */
+#ifndef MULTI_KBOARD
+#define MULTI_KBOARD
+#endif
+
 /* Define USER_FULL_NAME to return a string
    that is the user's full name.
    It can assume that the variable `pw'
index 5285e0174ae2ca93db016fdfd3d4086913fbf11c..7056519e7bf0adddad9a4dc37a0f32755f0bfd0c 100644 (file)
@@ -1278,7 +1278,7 @@ struct glyph_string
        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)
 */
 
@@ -2035,16 +2035,16 @@ struct it
 /* Call produce_glyphs or produce_glyphs_hook, if set.  Shortcut to
    avoid the function call overhead.  */
 
-#define PRODUCE_GLYPHS(IT)                     \
-     do {                                      \
-       extern int inhibit_free_realized_faces; \
-       if (rif != NULL)                                \
-        rif->produce_glyphs ((IT));            \
-       else                                    \
-        produce_glyphs ((IT));                 \
-       if ((IT)->glyph_row != NULL)            \
-        inhibit_free_realized_faces = 1;       \
-     } while (0)
+#define PRODUCE_GLYPHS(IT)                              \
+  do {                                                  \
+    extern int inhibit_free_realized_faces;             \
+    if (FRAME_RIF ((IT)->f) != NULL)                    \
+      FRAME_RIF ((IT)->f)->produce_glyphs ((IT));       \
+    else                                                \
+      produce_glyphs ((IT));                            \
+    if ((IT)->glyph_row != NULL)                        \
+      inhibit_free_realized_faces = 1;                  \
+  } while (0)
 
 /* Bit-flags indicating what operation move_it_to should perform.  */
 
@@ -2218,10 +2218,6 @@ struct redisplay_interface
 #endif /* HAVE_WINDOW_SYSTEM */
 };
 
-/* The current interface for window-based redisplay.  */
-
-extern struct redisplay_interface *rif;
-
 \f
 /***********************************************************************
                                Images
@@ -2641,11 +2637,11 @@ int image_background_transparent P_ ((struct image *, struct frame *,
 
 /* Defined in sysdep.c */
 
-void get_frame_size P_ ((int *, int *));
+void get_tty_size P_ ((int, int *, int *));
 void request_sigio P_ ((void));
 void unrequest_sigio P_ ((void));
-int tabs_safe_p P_ ((void));
-void init_baud_rate P_ ((void));
+int tabs_safe_p P_ ((int));
+void init_baud_rate P_ ((int));
 void init_sigio P_ ((int));
 
 /* Defined in xfaces.c */
@@ -2802,29 +2798,36 @@ extern Lisp_Object Qredisplay_dont_pause;
 /* Defined in term.c */
 
 extern void ring_bell P_ ((void));
-extern void set_terminal_modes P_ ((void));
-extern void reset_terminal_modes P_ ((void));
 extern void update_begin P_ ((struct frame *));
 extern void update_end P_ ((struct frame *));
 extern void set_terminal_window P_ ((int));
 extern void set_scroll_region P_ ((int, int));
-extern void turn_off_insert P_ ((void));
-extern void turn_off_highlight P_ ((void));
-extern void background_highlight P_ ((void));
+extern void turn_off_insert P_ ((struct tty_display_info *));
+extern void turn_off_highlight P_ ((struct tty_display_info *));
+extern void background_highlight P_ ((struct tty_display_info *));
 extern void clear_frame P_ ((void));
 extern void clear_end_of_line P_ ((int));
 extern void clear_end_of_line_raw P_ ((int));
+extern void tty_clear_end_of_line P_ ((int));
 extern void delete_glyphs P_ ((int));
 extern void ins_del_lines P_ ((int, int));
 extern int string_cost P_ ((char *));
 extern int per_line_cost P_ ((char *));
 extern void calculate_costs P_ ((struct frame *));
 extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object));
-extern void tty_setup_colors P_ ((int));
-extern void term_init P_ ((char *));
+extern void tty_setup_colors P_ ((struct tty_display_info *, int));
+extern struct display *get_named_tty_display P_ ((char *));
+extern Lisp_Object Fframe_tty_type P_ ((Lisp_Object));
+extern struct display *init_initial_display P_ ((void));
+extern struct display *term_init P_ ((char *, char *, int));
+extern void delete_tty P_ ((struct display *));
 extern void fatal P_ ((/* char *, ... */));
-void cursor_to P_ ((int, int));
-extern int tty_capable_p P_ ((struct frame *, unsigned, unsigned long, unsigned long));
+extern void cursor_to P_ ((int, int));
+extern int tty_capable_p P_ ((struct tty_display_info *, unsigned, unsigned long, unsigned long));
+extern void tty_set_terminal_modes P_ ((struct display *));
+extern void tty_reset_terminal_modes P_ ((struct display *));
+extern void create_tty_output P_ ((struct frame *));
+
 
 /* Defined in scroll.c */
 
index e1a3ed93dab9d1de2184252969d2b7cb59b1b3c5..3b6589938117f135321134d72cd42c0fdf9d15df 100644 (file)
@@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA.  */
 #include "lisp.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"
@@ -39,6 +38,7 @@ Boston, MA 02111-1307, USA.  */
 #include "charset.h"
 #include "keyboard.h"
 #include "frame.h"
+#include "termhooks.h"
 #include "window.h"
 #include "commands.h"
 #include "disptab.h"
@@ -214,9 +214,9 @@ int inverse_video;
 EMACS_INT baud_rate;
 
 /* Either nil or a symbol naming the window system under which Emacs
-   is running.  */
+   creates the first frame.  */
 
-Lisp_Object Vwindow_system;
+Lisp_Object Vinitial_window_system;
 
 /* Version number of X windows: 10, 11 or nil.  */
 
@@ -258,14 +258,6 @@ Lisp_Object selected_frame;
 
 struct frame *last_nonminibuf_frame;
 
-/* Stdio stream being used for copy of all output.  */
-
-FILE *termscript;
-
-/* Structure for info on cursor positioning.  */
-
-struct cm Wcm;
-
 /* 1 means SIGWINCH happened when not safe.  */
 
 int delayed_size_change;
@@ -304,11 +296,6 @@ int glyph_pool_count;
 
 static struct frame *frame_matrix_frame;
 
-/* Current interface for window-based redisplay.  Set from init_xterm.
-   A null value means we are not using window-based redisplay.  */
-
-struct redisplay_interface *rif;
-
 /* Non-zero means that fonts have been loaded since the last glyph
    matrix adjustments.  Redisplay must stop, and glyph matrices must
    be adjusted when this flag becomes non-zero during display.  The
@@ -1397,7 +1384,7 @@ line_hash_code (row)
        {
          int c = glyph->u.ch;
          int face_id = glyph->face_id;
-         if (must_write_spaces)
+         if (FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
            c -= SPACEGLYPH;
          hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
          hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
@@ -1429,7 +1416,7 @@ line_draw_cost (matrix, vpos)
   int glyph_table_len = GLYPH_TABLE_LENGTH;
 
   /* Ignore trailing and leading spaces if we can.  */
-  if (!must_write_spaces)
+  if (!FRAME_MUST_WRITE_SPACES (SELECTED_FRAME ())) /* XXX Is SELECTED_FRAME OK here? */
     {
       /* Skip from the end over trailing spaces.  */
       while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
@@ -1645,8 +1632,10 @@ realloc_glyph_pool (pool, matrix_dim)
 #if GLYPH_DEBUG
 
 
-/* Flush standard output.  This is sometimes useful to call from
-   the debugger.  */
+/* Flush standard output.  This is sometimes useful to call from the debugger.
+   XXX Maybe this should be changed to flush the current terminal instead of
+   stdout.
+*/
 
 void
 flush_stdout ()
@@ -3319,12 +3308,15 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
     return Qnil;
 
   update_begin (f);
+#ifdef MSDOS
   if (FRAME_MSDOS_P (f))
-    set_terminal_modes ();
+    set_terminal_modes (FRAME_DISPLAY (f));
+#endif
   clear_frame ();
   clear_current_matrices (f);
   update_end (f);
-  fflush (stdout);
+  if (FRAME_TERMCAP_P (f))
+    fflush (FRAME_TTY (f)->output);
   windows_or_buffers_changed++;
   /* Mark all windows as inaccurate, so that every window will have
      its redisplay done.  */
@@ -3465,7 +3457,7 @@ direct_output_for_insert (g)
 
   /* If we can't insert glyphs, we can use this method only
      at the end of a line.  */
-  if (!char_ins_del_ok)
+  if (!FRAME_CHAR_INS_DEL_OK (f))
     if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
       return 0;
 
@@ -3615,17 +3607,17 @@ direct_output_for_insert (g)
   updated_row = glyph_row;
   updated_area = TEXT_AREA;
   update_begin (f);
-  if (rif)
+  if (FRAME_RIF (f))
     {
-      rif->update_window_begin_hook (w);
+      FRAME_RIF (f)->update_window_begin_hook (w);
 
       if (glyphs == end - n
          /* In front of a space added by append_space.  */
          || (glyphs == end - n - 1
              && (end - n)->charpos <= 0))
-       rif->write_glyphs (glyphs, n);
+       FRAME_RIF (f)->write_glyphs (glyphs, n);
       else
-       rif->insert_glyphs (glyphs, n);
+       FRAME_RIF (f)->insert_glyphs (glyphs, n);
     }
   else
     {
@@ -3645,8 +3637,8 @@ direct_output_for_insert (g)
      a frame matrix is used, cursor_to expects frame coordinates,
      and the X and Y parameters are not used.  */
   if (window_redisplay_p)
-    rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
-                   w->cursor.y, w->cursor.x);
+    FRAME_RIF (f)->cursor_to (w->cursor.vpos, w->cursor.hpos,
+                              w->cursor.y, w->cursor.x);
   else
     {
       int x, y;
@@ -3662,11 +3654,12 @@ direct_output_for_insert (g)
   update_window_fringes (w, 0);
 #endif
 
-  if (rif)
-    rif->update_window_end_hook (w, 1, 0);
+  if (FRAME_RIF (f))
+    FRAME_RIF (f)->update_window_end_hook (w, 1, 0);
   update_end (f);
   updated_row = NULL;
-  fflush (stdout);
+  if (FRAME_TERMCAP_P (f))
+    fflush (FRAME_TTY (f)->output);
 
   TRACE ((stderr, "direct output for insert\n"));
   mark_window_display_accurate (it.window, 1);
@@ -3744,8 +3737,8 @@ direct_output_forward_char (n)
           && w->cursor.hpos < w->desired_matrix->matrix_w);
 
   if (FRAME_WINDOW_P (f))
-    rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
-                   w->cursor.y, w->cursor.x);
+    FRAME_RIF (f)->cursor_to (w->cursor.vpos, w->cursor.hpos,
+                              w->cursor.y, w->cursor.x);
   else
     {
       int x, y;
@@ -3757,7 +3750,8 @@ direct_output_forward_char (n)
       cursor_to (y, x);
     }
 
-  fflush (stdout);
+  if (FRAME_TERMCAP_P (f))
+    fflush (FRAME_TTY (f)->output);
   redisplay_performed_directly_p = 1;
   return 1;
 }
@@ -3830,14 +3824,14 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       update_end (f);
 
       /* This flush is a performance bottleneck under X,
-        and it doesn't seem to be necessary anyway (in general).
+        and it doesn't seem to be necessary anyway (in general).
          It is necessary when resizing the window with the mouse, or
-        at least the fringes are not redrawn in a timely manner.  ++kfs */
+        at least the fringes are not redrawn in a timely manner.  ++kfs */
       if (f->force_flush_display_p)
-       {
-         rif->flush_display (f);
-         f->force_flush_display_p = 0;
-       }
+       {
+         FRAME_RIF (f)->flush_display (f);
+         f->force_flush_display_p = 0;
+       }
     }
   else
     {
@@ -3853,9 +3847,12 @@ update_frame (f, force_p, inhibit_hairy_id_p)
       paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
       update_end (f);
 
-      if (termscript)
-       fflush (termscript);
-      fflush (stdout);
+      if (FRAME_TERMCAP_P (f))
+        {
+          if (FRAME_TTY (f)->termscript)
+            fflush (FRAME_TTY (f)->termscript);
+          fflush (FRAME_TTY (f)->output);
+        }
 
       /* Check window matrices for lost pointers.  */
 #if GLYPH_DEBUG
@@ -3938,7 +3935,8 @@ redraw_overlapped_rows (w, yb)
      int yb;
 {
   int i;
-
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  
   /* If rows overlapping others have been changed, the rows being
      overlapped have to be redrawn.  This won't draw lines that have
      already been drawn in update_window_line because overlapped_p in
@@ -3961,10 +3959,12 @@ redraw_overlapped_rows (w, yb)
            {
              updated_row = row;
              updated_area = area;
-             rif->cursor_to (i, 0, row->y, area == TEXT_AREA ? row->x : 0);
+             FRAME_RIF (f)->cursor_to (i, 0, row->y,
+                                        area == TEXT_AREA ? row->x : 0);
              if (row->used[area])
-               rif->write_glyphs (row->glyphs[area], row->used[area]);
-             rif->clear_end_of_line (-1);
+               FRAME_RIF (f)->write_glyphs (row->glyphs[area],
+                                             row->used[area]);
+             FRAME_RIF (f)->clear_end_of_line (-1);
            }
 
          row->overlapped_p = 0;
@@ -3986,7 +3986,8 @@ redraw_overlapping_rows (w, yb)
 {
   int i, bottom_y;
   struct glyph_row *row;
-
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
+  
   for (i = 0; i < w->current_matrix->nrows; ++i)
     {
       row = w->current_matrix->rows + i;
@@ -4066,6 +4067,7 @@ update_window (w, force_p)
 #if GLYPH_DEBUG
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 #endif
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
 
   /* Check that W's frame doesn't have glyph matrices.  */
   xassert (FRAME_WINDOW_P (f));
@@ -4237,6 +4239,7 @@ update_marginal_area (w, area, vpos)
      int area, vpos;
 {
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
 
   /* Let functions in xterm.c know what area subsequent X positions
      will be relative to.  */
@@ -4262,6 +4265,7 @@ update_text_area (w, vpos)
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
   int changed_p = 0;
 
   /* Let functions in xterm.c know what area subsequent X positions
@@ -4483,6 +4487,7 @@ update_window_line (w, vpos, mouse_face_overwritten_p)
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
   int changed_p = 0;
 
   /* Set the row being updated.  This is important to let xterm.c
@@ -4551,6 +4556,7 @@ set_window_cursor_after_update (w)
      struct window *w;
 {
   struct frame *f = XFRAME (w->frame);
+  struct redisplay_interface *rif = FRAME_RIF (f);
   int cx, cy, vpos, hpos;
 
   /* Not intended for frame matrix updates.  */
@@ -4774,6 +4780,7 @@ scrolling_window (w, header_line_p)
   int i, j, first_old, first_new, last_old, last_new;
   int nruns, nbytes, n, run_idx;
   struct row_entry *entry;
+  struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
 
   /* Skip over rows equal at the start.  */
   for (i = header_line_p ? 1 : 0; i < current_matrix->nrows - 1; ++i)
@@ -5098,7 +5105,7 @@ update_frame_1 (f, force_p, inhibit_id_p)
     }
 
   /* If we cannot insert/delete lines, it's no use trying it.  */
-  if (!line_ins_del_ok)
+  if (!FRAME_LINE_INS_DEL_OK (f))
     inhibit_id_p = 1;
 
   /* See if any of the desired lines are enabled; don't compute for
@@ -5126,18 +5133,18 @@ update_frame_1 (f, force_p, inhibit_id_p)
                 Also flush out if likely to have more than 1k buffered
                 otherwise.   I'm told that some telnet connections get
                 really screwed by more than 1k output at once.  */
-             int outq = PENDING_OUTPUT_COUNT (stdout);
+             int outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f)->output);
              if (outq > 900
                  || (outq > 20 && ((i - 1) % preempt_count == 0)))
                {
-                 fflush (stdout);
+                 fflush (FRAME_TTY (f)->output);
                  if (preempt_count == 1)
                    {
 #ifdef EMACS_OUTQSIZE
                      if (EMACS_OUTQSIZE (0, &outq) < 0)
                        /* Probably not a tty.  Ignore the error and reset
                           the outq count.  */
-                       outq = PENDING_OUTPUT_COUNT (stdout);
+                       outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
 #endif
                      outq *= 10;
                      if (baud_rate <= outq && baud_rate > 0)
@@ -5316,21 +5323,23 @@ scrolling (frame)
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
-  if ((!scroll_region_ok && changed_lines < baud_rate / 2400)
+  if ((!FRAME_SCROLL_REGION_OK (frame)
+       && changed_lines < baud_rate / 2400)
       || unchanged_at_bottom == FRAME_LINES (frame))
     return 1;
 
   window_size = (FRAME_LINES (frame) - unchanged_at_top
                 - unchanged_at_bottom);
 
-  if (scroll_region_ok)
+  if (FRAME_SCROLL_REGION_OK (frame))
     free_at_end_vpos -= unchanged_at_bottom;
-  else if (memory_below_frame)
+  else if (FRAME_MEMORY_BELOW_FRAME (frame))
     free_at_end_vpos = -1;
 
   /* If large window, fast terminal and few lines in common between
      current frame and desired frame, don't bother with i/d calc.  */
-  if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
+  if (!FRAME_SCROLL_REGION_OK (frame)
+      && window_size >= 18 && baud_rate > 2400
       && (window_size >=
          10 * scrolling_max_lines_saved (unchanged_at_top,
                                          FRAME_LINES (frame) - unchanged_at_bottom,
@@ -5410,7 +5419,7 @@ update_frame_line (f, vpos)
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
   int must_write_whole_line_p;
-  int write_spaces_p = must_write_spaces;
+  int write_spaces_p = FRAME_MUST_WRITE_SPACES (f);
   int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
                          != FACE_TTY_DEFAULT_BG_COLOR);
 
@@ -5489,7 +5498,7 @@ update_frame_line (f, vpos)
       nlen--;
 
   /* If there's no i/d char, quickly do the best we can without it.  */
-  if (!char_ins_del_ok)
+  if (!FRAME_CHAR_INS_DEL_OK (f))
     {
       int i, j;
 
@@ -5592,7 +5601,8 @@ update_frame_line (f, vpos)
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
-      && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem]))
+      && (!FRAME_CHAR_INS_DEL_OK (f)
+          || endmatch <= char_ins_del_cost (f)[tem]))
     endmatch = 0;
 
   /* nsp - osp is the distance to insert or delete.
@@ -5601,7 +5611,7 @@ update_frame_line (f, vpos)
      Is it worth it?  */
 
   if (nsp != osp
-      && (!char_ins_del_ok
+      && (!FRAME_CHAR_INS_DEL_OK (f)
          || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
     {
       begmatch = 0;
@@ -5978,28 +5988,31 @@ window_change_signal (signalnum) /* If we don't have an argument, */
 #endif
   int old_errno = errno;
 
-  get_frame_size (&width, &height);
+  struct tty_display_info *tty;
 
-  /* The frame size change obviously applies to a termcap-controlled
-     frame.  Find such a frame in the list, and assume it's the only
-     one (since the redisplay code always writes to stdout, not a
-     FILE * specified in the frame structure).  Record the new size,
-     but don't reallocate the data structures now.  Let that be done
-     later outside of the signal handler.  */
+  /* The frame size change obviously applies to a single
+     termcap-controlled terminal, but we can't decide which.
+     Therefore, we resize the frames corresponding to each tty.
+  */
+  for (tty = tty_list; tty; tty = tty->next) {
 
-  {
-    Lisp_Object tail, frame;
+    if (! tty->term_initted)
+      continue;
 
-    FOR_EACH_FRAME (tail, frame)
-      {
-       if (FRAME_TERMCAP_P (XFRAME (frame)))
-         {
-           change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
-           break;
-         }
-      }
+    get_tty_size (fileno (tty->input), &width, &height);
+    
+    {
+      Lisp_Object tail, frame;
+      
+      FOR_EACH_FRAME (tail, frame)
+        if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
+          /* Record the new sizes, but don't reallocate the data
+             structures now.  Let that be done later outside of the
+             signal handler.  */
+          change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+    }
   }
-
+  
   signal (SIGWINCH, window_change_signal);
   errno = old_errno;
 }
@@ -6054,10 +6067,11 @@ change_frame_size (f, newheight, newwidth, pretend, delay, safe)
 {
   Lisp_Object tail, frame;
 
-  if (! FRAME_WINDOW_P (f))
+  if (FRAME_MSDOS_P (f))
     {
-      /* When using termcap, or on MS-DOS, all frames use
-        the same screen, so a change in size affects all frames.  */
+      /* On MS-DOS, all frames use the same screen, so a change in
+         size affects all frames.  Termcap now supports multiple
+         ttys. */
       FOR_EACH_FRAME (tail, frame)
        if (! FRAME_WINDOW_P (XFRAME (frame)))
          change_frame_size_1 (XFRAME (frame), newheight, newwidth,
@@ -6137,7 +6151,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
                           newheight - FRAME_TOP_MARGIN (f), 0);
 
       if (FRAME_TERMCAP_P (f) && !pretend)
-       FrameRows = newheight;
+       FrameRows (FRAME_TTY (f)) = newheight;
     }
 
   if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
@@ -6147,7 +6161,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
        set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0);
 
       if (FRAME_TERMCAP_P (f) && !pretend)
-       FrameCols = newwidth;
+       FrameCols (FRAME_TTY (f)) = newwidth;
 
       if (WINDOWP (f->tool_bar_window))
        XSETFASTINT (XWINDOW (f->tool_bar_window)->total_cols, newwidth);
@@ -6197,14 +6211,22 @@ FILE = nil means just close any termscript file currently open.  */)
      (file)
      Lisp_Object file;
 {
-  if (termscript != 0) fclose (termscript);
-  termscript = 0;
+  struct tty_display_info *tty;
+
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
+    error ("Current frame is not on a tty device");
+
+  tty = CURTTY ();
+
+  if (tty->termscript != 0)
+    fclose (tty->termscript);
+  tty->termscript = 0;
 
   if (! NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
-      termscript = fopen (SDATA (file), "w");
-      if (termscript == 0)
+      tty->termscript = fopen (SDATA (file), "w");
+      if (tty->termscript == 0)
        report_file_error ("Opening termscript", Fcons (file, Qnil));
     }
   return Qnil;
@@ -6218,16 +6240,23 @@ Control characters in STRING will have terminal-dependent effects.  */)
      (string)
      Lisp_Object string;
 {
+  struct tty_display_info *tty;
+
   /* ??? Perhaps we should do something special for multibyte strings here.  */
   CHECK_STRING (string);
-  fwrite (SDATA (string), 1, SBYTES (string), stdout);
-  fflush (stdout);
-  if (termscript)
+
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
+    error ("Current frame is not on a tty device");
+
+  tty = CURTTY ();
+  
+  if (tty->termscript)
     {
-      fwrite (SDATA (string), 1, SBYTES (string),
-             termscript);
-      fflush (termscript);
+      fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
+      fflush (tty->termscript);
     }
+  fwrite (SDATA (string), 1, SBYTES (string), tty->output);
+  fflush (tty->output);
   return Qnil;
 }
 
@@ -6245,7 +6274,8 @@ terminate any keyboard macro currently executing.  */)
        putchar (07);
       else
        ring_bell ();
-      fflush (stdout);
+      if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+        fflush (CURTTY ()->output);
     }
   else
     bitch_at_user ();
@@ -6262,7 +6292,8 @@ bitch_at_user ()
     error ("Keyboard macro terminated by a command ringing the bell");
   else
     ring_bell ();
-  fflush (stdout);
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    fflush (CURTTY ()->output);
 }
 
 
@@ -6547,8 +6578,6 @@ the current state.  */)
                            Initialization
 ***********************************************************************/
 
-char *terminal_type;
-
 /* Initialization done when Emacs fork is started, before doing stty.
    Determine terminal type and set terminal_driver.  Then invoke its
    decoding routine to set up variables in the terminal package.  */
@@ -6556,6 +6585,8 @@ char *terminal_type;
 void
 init_display ()
 {
+  char *terminal_type;
+
 #ifdef HAVE_X_WINDOWS
   extern int display_arg;
 #endif
@@ -6565,14 +6596,13 @@ init_display ()
   SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' ');
   space_glyph.charpos = -1;
 
-  meta_key = 0;
   inverse_video = 0;
   cursor_in_echo_area = 0;
   terminal_type = (char *) 0;
 
   /* Now is the time to initialize this; it's used by init_sys_modes
      during startup.  */
-  Vwindow_system = Qnil;
+  Vinitial_window_system = Qnil;
 
   /* If the user wants to use a window system, we shouldn't bother
      initializing the terminal.  This is especially important when the
@@ -6601,7 +6631,7 @@ init_display ()
 #endif
      )
     {
-      Vwindow_system = intern ("x");
+      Vinitial_window_system = intern ("x");
 #ifdef HAVE_X11
       Vwindow_system_version = make_number (11);
 #else
@@ -6621,7 +6651,7 @@ init_display ()
 #ifdef HAVE_NTGUI
   if (!inhibit_window_system)
     {
-      Vwindow_system = intern ("w32");
+      Vinitial_window_system = intern ("w32");
       Vwindow_system_version = make_number (1);
       adjust_frame_glyphs_initially ();
       return;
@@ -6631,7 +6661,7 @@ init_display ()
 #ifdef MAC_OS
   if (!inhibit_window_system)
     {
-      Vwindow_system = intern ("mac");
+      Vinitial_window_system = intern ("mac");
       Vwindow_system_version = make_number (1);
       adjust_frame_glyphs_initially ();
       return;
@@ -6677,8 +6707,37 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
   }
 #endif /* VMS */
 
-  term_init (terminal_type);
+  {
+    struct display *d;
+    struct frame *f = XFRAME (selected_frame);
+
+    /* Open a display on the controlling tty. */
+    d = term_init (0, terminal_type, 1); /* Errors are fatal. */
+
+    /* Convert the initial frame to use the new display. */
+    if (f->output_method != output_initial)
+      abort ();
+    f->output_method = d->type;
+    f->display = d;
+#ifdef MULTI_KBOARD
+    f->kboard = d->display_info.tty->kboard;
+#endif
+
+    d->reference_count++;
+    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);
 
+    /* Delete the initial display. */
+    if (--initial_display->reference_count == 0
+        && initial_display->delete_display_hook)
+      (*initial_display->delete_display_hook) (initial_display);
+
+    /* Update frame parameters to reflect the new type. */
+    Fmodify_frame_parameters
+      (selected_frame, Fcons (Fcons (Qtty_type,
+                                     Fframe_tty_type (selected_frame)), Qnil));
+  }
+  
   {
     struct frame *sf = SELECTED_FRAME ();
     int width = FRAME_TOTAL_COLS (sf);
@@ -6712,7 +6771,7 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
         and internal_terminal_init.  */
       && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system)
 #endif
-      && NILP (Vwindow_system))
+      && NILP (Vinitial_window_system))
     {
       /* For the initial frame, we don't have any way of knowing what
         are the foreground and background colors of the terminal.  */
@@ -6824,8 +6883,8 @@ A non-nil value is useful if the terminal can automatically preserve
 Emacs's frame display when you reenter Emacs.
 It is up to you to set this variable if your terminal can do that.  */);
 
-  DEFVAR_LISP ("window-system", &Vwindow_system,
-              doc: /* Name of window system that Emacs is displaying through.
+  DEFVAR_LISP ("initial-window-system", &Vinitial_window_system,
+              doc: /* Name of the window system that Emacs uses for the first frame.
 The value is a symbol--for instance, `x' for X windows.
 The value is nil if Emacs is using a text-only terminal.  */);
 
@@ -6861,7 +6920,7 @@ See `buffer-display-table' for more information.  */);
   if (noninteractive)
 #endif
     {
-      Vwindow_system = Qnil;
+      Vinitial_window_system = Qnil;
       Vwindow_system_version = Qnil;
     }
 }
index b95f97368ca5a04d38dd1aa1d89856e8e5ce3d77..011d66c5cab527c6ce4f237e175bbf13190cd2d9 100644 (file)
@@ -54,6 +54,7 @@ Boston, MA 02111-1307, USA.  */
 #include "blockinput.h"
 #include "syssignal.h"
 #include "process.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "keyboard.h"
 #include "keymap.h"
@@ -200,7 +201,7 @@ int display_arg;
 char *stack_bottom;
 
 #ifdef HAVE_WINDOW_SYSTEM
-extern Lisp_Object Vwindow_system;
+extern Lisp_Object Vinitial_window_system;
 #endif /* HAVE_WINDOW_SYSTEM */
 
 extern Lisp_Object Vauto_save_list_file_name;
@@ -1586,13 +1587,7 @@ main (argc, argv
 #endif  /* end #ifdef HAVE_NTGUI */
     }
 
-  if (!noninteractive)
-    {
-#ifdef VMS
-      init_vms_input ();/* init_display calls get_frame_size, that needs this.  */
-#endif /* VMS */
-      init_display (); /* Determine terminal type.  init_sys_modes uses results.  */
-    }
+  init_process (); /* init_display uses add_keyboard_wait_descriptor. */
 #ifndef MAC_OS8
   /* Called before init_window_once for Mac OS Classic.  */
   init_keyboard ();    /* This too must precede init_sys_modes.  */
@@ -1600,7 +1595,13 @@ main (argc, argv
 #ifdef VMS
   init_vmsproc ();     /* And this too.  */
 #endif /* VMS */
-  init_sys_modes ();   /* Init system terminal modes (RAW or CBREAK, etc.).  */
+  if (!noninteractive)
+    {
+#ifdef VMS
+      init_vms_input ();/* init_display calls get_tty_size, that needs this.  */
+#endif /* VMS */
+      init_display (); /* Determine terminal type.  Calls init_sys_modes.  */
+    }
   init_fns ();
   init_xdisp ();
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1613,7 +1614,6 @@ main (argc, argv
 #ifdef VMS
   init_vmsfns ();
 #endif /* VMS */
-  init_process ();
 #ifdef HAVE_SOUND
   init_sound ();
 #endif
@@ -1936,9 +1936,9 @@ sort_args (argc, argv)
 
   bcopy (new, argv, sizeof (char *) * argc);
 
-  free (options);
-  free (new);
-  free (priority);
+  xfree (options);
+  xfree (new);
+  xfree (priority);
 }
 \f
 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
@@ -2017,15 +2017,14 @@ shut_down_emacs (sig, no_x, stuff)
     if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
        && tpgrp == pgrp)
       {
-       fflush (stdout);
-       reset_sys_modes ();
+       reset_all_sys_modes ();
        if (sig && sig != SIGTERM)
          fprintf (stderr, "Fatal error (%d)", sig);
       }
   }
 #else
   fflush (stdout);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
 #endif
 
   stuff_buffered_input (stuff);
@@ -2044,9 +2043,9 @@ shut_down_emacs (sig, no_x, stuff)
 #if 0 /* This triggers a bug in XCloseDisplay and is not needed.  */
 #ifdef HAVE_X_WINDOWS
   /* It's not safe to call intern here.  Maybe we are crashing.  */
-  if (!noninteractive && SYMBOLP (Vwindow_system)
-      && SCHARS (SYMBOL_NAME (Vwindow_system)) == 1
-      && SREF (SYMBOL_NAME (Vwindow_system), 0) == 'x'
+  if (!noninteractive && SYMBOLP (Vinitial_window_system)
+      && SCHARS (SYMBOL_NAME (Vinitial_window_system)) == 1
+      && SREF (SYMBOL_NAME (Vinitial_window_system), 0) == 'x'
       && ! no_x)
     Fx_close_current_connection ();
 #endif /* HAVE_X_WINDOWS */
index 6ed1efff092503951d1f8f84f2ffcdc66d9515a2..ad9dd3ccd2f5eef431bc17c3ffe2f5971e4d6d5d 100644 (file)
@@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA.  */
 #ifdef MAC_OS
 #include "macterm.h"
 #endif
+#include "termhooks.h"
 
 #ifdef FONTSET_DEBUG
 #undef xassert
@@ -1084,7 +1085,6 @@ name of a font, REGISTRY is a registry name of a font.  */)
   Lisp_Object realized;
   int from, to;
   int id;
-  Lisp_Object family, registry;
 
   fontset = check_fontset_name (name);
 
@@ -1280,7 +1280,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
       STORE_XCHAR2B (&char2b, c1, c2);
     else
       STORE_XCHAR2B (&char2b, 0, c1);
-    rif->encode_char (c, &char2b, fontp, NULL);
+    FRAME_RIF (f)->encode_char (c, &char2b, fontp, NULL);
     code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
   }
   return Fcons (build_string (face->font_name), make_number (code));
index 934c11d98bc776dd9d229adc8905a3e2acb48c66..7917b9ecdd636191a73fd89f38e024ac46bfc4fa 100644 (file)
@@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 #endif
 #include "blockinput.h"
+#include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
@@ -106,12 +107,13 @@ Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
 Lisp_Object Qleft_fringe, Qright_fringe;
 Lisp_Object Qbuffer_predicate, Qbuffer_list;
 Lisp_Object Qtty_color_mode;
+Lisp_Object Qtty, Qtty_type;
+Lisp_Object Qwindow_system;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 
 Lisp_Object Qface_set_after_frame_default;
 
-
 Lisp_Object Vterminal_frame;
 Lisp_Object Vdefault_frame_alist;
 Lisp_Object Vdefault_frame_scroll_bars;
@@ -121,8 +123,8 @@ Lisp_Object Vdelete_frame_functions;
 \f
 static void
 set_menu_bar_lines_1 (window, n)
-  Lisp_Object window;
-  int n;
+     Lisp_Object window;
+     int n;
 {
   struct window *w = XWINDOW (window);
 
@@ -180,8 +182,6 @@ set_menu_bar_lines (f, value, oldval)
 Lisp_Object Vemacs_iconified;
 Lisp_Object Vframe_list;
 
-struct x_output tty_display;
-
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object get_minibuffer ();
 extern Lisp_Object Fhandle_switch_frame ();
@@ -203,6 +203,7 @@ See also `frame-live-p'.  */)
     return Qnil;
   switch (XFRAME (object)->output_method)
     {
+    case output_initial: /* The initial frame is like a termcap frame. */
     case output_termcap:
       return Qt;
     case output_x_window:
@@ -233,6 +234,30 @@ return values.  */)
          : 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;
@@ -474,18 +499,19 @@ make_minibuffer_frame ()
 }
 #endif /* HAVE_WINDOW_SYSTEM */
 \f
-/* Construct a frame that refers to the terminal (stdin and stdout).  */
+/* Construct a frame that refers to a terminal.  */
 
 static int terminal_frame_count;
 
 struct frame *
-make_terminal_frame ()
+make_initial_frame (void)
 {
-  register struct frame *f;
+  struct frame *f;
+  struct display *display;
   Lisp_Object frame;
-  char name[20];
 
 #ifdef MULTI_KBOARD
+  /* Create the initial keyboard. */
   if (!initial_kboard)
     {
       initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
@@ -499,6 +525,52 @@ make_terminal_frame ()
   if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
     Vframe_list = Qnil;
 
+  display = init_initial_display ();
+
+  f = make_frame (1);
+  XSETFRAME (frame, f);
+
+  Vframe_list = Fcons (frame, Vframe_list);
+
+  terminal_frame_count = 1;
+  f->name = build_string ("F1");
+
+  f->visible = 1;
+  f->async_visible = 1;
+
+  f->output_method = display->type;
+  f->display = display;
+  f->display->reference_count++;
+  f->output_data.nothing = 0;
+  
+  FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
+  FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
+    
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
+#ifdef MULTI_KBOARD
+  f->kboard = initial_kboard;
+#endif
+
+  return f;
+}
+
+
+struct frame *
+make_terminal_frame (tty_name, tty_type)
+     char *tty_name;
+     char *tty_type;
+{
+  register struct frame *f;
+  struct display *display;
+  Lisp_Object frame;
+  char name[20];
+  
+  /* Open the display before creating the new frame, because
+     create_tty_display might throw an error. */
+  display = term_init (tty_name, tty_type, 0); /* Errors are not fatal. */
+  
   f = make_frame (1);
 
   XSETFRAME (frame, f);
@@ -537,12 +609,35 @@ make_terminal_frame ()
 #else
 #ifdef WINDOWSNT
   f->output_method = output_termcap;
-  f->output_data.x = &tty_display;
+  f->output_data.x = &tty_display; /* XXX ??? */
 #else
 #ifdef MAC_OS8
   make_mac_terminal_frame (f);
 #else
-  f->output_data.x = &tty_display;
+  {
+    f->output_method = output_termcap;
+    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;
+    
+    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. */
+    if (FRAME_TTY (f)->top_frame
+        && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
+      XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
+    
+    FRAME_TTY (f)->top_frame = frame;
+  }
+  
 #ifdef CANNOT_DUMP
   FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
   FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
@@ -559,12 +654,21 @@ make_terminal_frame ()
 
 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
        1, 1, 0,
-       doc: /* Create an additional terminal frame.
-You can create multiple frames on a text-only terminal in this way.
-Only the selected terminal frame is actually displayed.
+       doc: /* Create an additional terminal frame, possibly on another terminal.
 This function takes one argument, an alist specifying frame parameters.
-In practice, generally you don't need to specify any parameters.
-Note that changing the size of one terminal frame automatically affects all.  */)
+
+You can create multiple frames on a single text-only terminal, but
+only one of them (the selected terminal frame) is actually displayed.
+
+In practice, generally you don't need to specify any parameters,
+except when you want to create a new frame on another terminal.
+In that case, the `tty' parameter specifies the device file to open,
+and the `tty-type' parameter specifies the terminal type.  Example:
+
+   (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
+
+Note that changing the size of one terminal frame automatically
+affects all frames on the same terminal device.  */)
      (parms)
      Lisp_Object parms;
 {
@@ -582,20 +686,72 @@ Note that changing the size of one terminal frame automatically affects all.  */
   if (sf->output_method != output_mac)
     error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
 #else
+#if 0                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
+#endif
 #endif /* not MSDOS */
 
-  f = make_terminal_frame ();
+  { 
+    Lisp_Object tty, tty_type;
+    char *name = 0, *type = 0;
+
+    tty = Fassq (Qtty, parms);
+    if (EQ (tty, Qnil))
+      tty = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (EQ (tty, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame))
+        && FRAME_TTY (XFRAME (selected_frame))->name)
+      tty = build_string (FRAME_TTY (XFRAME (selected_frame))->name);
+    if (EQ (tty, Qnil))
+      tty = Fassq (Qtty, Vdefault_frame_alist);
+    if (! EQ (tty, Qnil) && ! STRINGP (tty))
+      tty = XCDR (tty);
+    if (EQ (tty, Qnil) || !STRINGP (tty))
+      tty = Qnil;
+
+    tty_type = Fassq (Qtty_type, parms);
+    if (EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (EQ (tty_type, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame))
+        && FRAME_TTY (XFRAME (selected_frame))->type)
+      tty_type = build_string (FRAME_TTY (XFRAME (selected_frame))->type);
+    if (EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty_type, Vdefault_frame_alist);
+    if (! EQ (tty_type, Qnil) && ! STRINGP (tty_type))
+      tty_type = XCDR (tty_type);
+    if (EQ (tty_type, Qnil) || !STRINGP (tty_type))
+      tty_type = Qnil;
+
+    if (! EQ (tty, Qnil))
+      {
+        name = (char *) alloca (SBYTES (tty) + 1);
+        strncpy (name, SDATA (tty), SBYTES (tty));
+        name[SBYTES (tty)] = 0;
+      }
+
+    if (! EQ (tty_type, Qnil))
+      {
+        type = (char *) alloca (SBYTES (tty_type) + 1);
+        strncpy (type, SDATA (tty_type), SBYTES (tty_type));
+        type[SBYTES (tty_type)] = 0;
+      }
+
+    f = make_terminal_frame (name, type);
+  }
 
-  change_frame_size (f, FRAME_LINES (sf),
-                    FRAME_COLS (sf), 0, 0, 0);
+  {
+    int width, height;
+    get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
+    change_frame_size (f, height, width, 0, 0, 0);
+  }
+  
   adjust_glyphs (f);
   calculate_costs (f);
   XSETFRAME (frame, f);
   Fmodify_frame_parameters (frame, Vdefault_frame_alist);
   Fmodify_frame_parameters (frame, parms);
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qnil), Qnil));
 
   /* Make the frame face alist be frame-specific, so that each
      frame could change its face definitions independently.  */
@@ -694,6 +850,15 @@ do_switch_frame (frame, track, for_deletion)
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+      && FRAME_TERMCAP_P (XFRAME (frame))
+      && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame)))
+    {
+      XFRAME (selected_frame)->async_visible = 2; /* obscured */
+      XFRAME (frame)->async_visible = 1;
+      FRAME_TTY (XFRAME (frame))->top_frame = frame;
+    }
+
   selected_frame = frame;
   if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
     last_nonminibuf_frame = XFRAME (selected_frame);
@@ -927,7 +1092,10 @@ next_frame (frame, minibuf)
        f = XCAR (tail);
 
        if (passed
-           && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+           && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+                 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+                || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+                    && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
          {
            /* Decide whether this frame is eligible to be returned.  */
 
@@ -1004,7 +1172,10 @@ prev_frame (frame, minibuf)
       if (EQ (frame, f) && !NILP (prev))
        return prev;
 
-      if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+      if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+           && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+          || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
        {
          /* Decide whether this frame is eligible to be returned,
             according to minibuf.  */
@@ -1231,7 +1402,7 @@ The functions are run with one arg, the frame to be deleted.  */)
        {
          FOR_EACH_FRAME (tail, frame1)
            {
-             if (! EQ (frame, frame1))
+             if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
                break;
            }
        }
@@ -1298,13 +1469,26 @@ The functions are run with one arg, the frame to be deleted.  */)
      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_DISPLAY (f)->delete_frame_hook)
+    (*FRAME_DISPLAY (f)->delete_frame_hook) (f);
+  
+  {
+    struct display *display = FRAME_DISPLAY (f);
 
-  f->output_data.nothing = 0;
+    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)
+    {
+      if (display->delete_display_hook)
+        (*display->delete_display_hook) (display);
+      else
+        delete_display (display);
+    }
+  }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
      another one.  */
@@ -1419,11 +1603,11 @@ and returns whatever that function returns.  */)
 
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
-  if (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);
@@ -1462,11 +1646,11 @@ and nil for X and Y.  */)
 
 #ifdef HAVE_MOUSE
   /* It's okay for the hook to refrain from storing anything.  */
-  if (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));
@@ -1728,16 +1912,19 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
      (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_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;
 }
@@ -1751,13 +1938,17 @@ doesn't support multiple overlapping frames, this function does nothing.  */)
      (frame)
      Lisp_Object frame;
 {
+  struct frame *f;
+  
   if (NILP (frame))
     frame = selected_frame;
 
   CHECK_LIVE_FRAME (frame);
 
-  if (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;
 }
@@ -1791,6 +1982,8 @@ The redirection lasts until `redirect-frame-focus' is called to change it.  */)
      (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.  */
@@ -1799,10 +1992,12 @@ The redirection lasts until `redirect-frame-focus' is called to change it.  */)
   if (! NILP (focus_frame))
     CHECK_LIVE_FRAME (focus_frame);
 
-  XFRAME (frame)->focus_frame = focus_frame;
+  f = XFRAME (frame);
+  
+  f->focus_frame = focus_frame;
 
-  if (frame_rehighlight_hook)
-    (*frame_rehighlight_hook) (XFRAME (frame));
+  if (FRAME_DISPLAY (f)->frame_rehighlight_hook)
+    (*FRAME_DISPLAY (f)->frame_rehighlight_hook) (f);
 
   return Qnil;
 }
@@ -2691,8 +2886,8 @@ x_set_frame_parameters (f, alist)
              if (NATNUMP (param_index)
                  && (XFASTINT (param_index)
                      < sizeof (frame_parms)/sizeof (frame_parms[0]))
-                 && rif->frame_parm_handlers[XINT (param_index)])
-               (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
+                  && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
+                (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
            }
        }
     }
@@ -2735,8 +2930,8 @@ x_set_frame_parameters (f, alist)
          if (NATNUMP (param_index)
              && (XFASTINT (param_index)
                  < sizeof (frame_parms)/sizeof (frame_parms[0]))
-             && rif->frame_parm_handlers[XINT (param_index)])
-           (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
+             && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
+           (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
        }
     }
 
@@ -3937,7 +4132,13 @@ syms_of_frame ()
   staticpro (&Qbackground_mode);
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
-
+  Qtty = intern ("tty");
+  staticpro (&Qtty);
+  Qtty_type = intern ("tty-type");
+  staticpro (&Qtty_type);
+  Qwindow_system = intern ("window-system");
+  staticpro (&Qwindow_system);
+  
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
@@ -4026,7 +4227,7 @@ Setting this variable does not affect existing frames, only new ones.  */);
   staticpro (&Qinhibit_default_face_x_resources);
 
   DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
-              doc: /* The initial frame-object, which represents Emacs's stdout.  */);
+               doc: /* The initial frame-object, which represents Emacs's stdout.  */);
 
   DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
               doc: /* Non-nil if all of emacs is iconified and frame updates are not needed.  */);
@@ -4074,6 +4275,7 @@ This variable is local to the current terminal and cannot be buffer-local.  */);
   defsubr (&Sactive_minibuffer_window);
   defsubr (&Sframep);
   defsubr (&Sframe_live_p);
+  defsubr (&Swindow_system);
   defsubr (&Smake_terminal_frame);
   defsubr (&Shandle_switch_frame);
   defsubr (&Signore_event);
index 8bdaff99754c6fe06b22e4e72113f3f9291e252b..2d87913309fc637f7185243c4b72dd71e1a3c6d5 100644 (file)
@@ -28,9 +28,7 @@ Boston, MA 02111-1307, USA.  */
 \f
 /* Miscellanea.  */
 
-/* Nonzero means don't assume anything about current contents of
-   actual terminal frame */
-
+/* Nonzero means there is at least one garbaged frame. */
 extern int frame_garbaged;
 
 /* Nonzero means FRAME_MESSAGE_BUF (selected_frame) is being used by
@@ -43,6 +41,7 @@ extern int message_buf_print;
 
 enum output_method
 {
+  output_initial,
   output_termcap,
   output_x_window,
   output_msdos_raw,
@@ -67,30 +66,10 @@ enum text_cursor_kinds
   HBAR_CURSOR
 };
 
-#if !defined(MSDOS) && !defined(WINDOWSNT) && !defined(MAC_OS)
-
-#if !defined(HAVE_X_WINDOWS)
-
-#define PIX_TYPE int
-
-/* A (mostly empty) x_output structure definition for building Emacs
-   on Unix and GNU/Linux without X support.  */
-struct x_output
-{
-  PIX_TYPE background_pixel;
-  PIX_TYPE foreground_pixel;
-};
-
-#endif /* ! HAVE_X_WINDOWS */
+#define FRAME_FOREGROUND_PIXEL(f) ((f)->foreground_pixel)
+#define FRAME_BACKGROUND_PIXEL(f) ((f)->background_pixel)
 
-
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
-
-/* A structure describing a termcap frame display.  */
-extern struct x_output tty_display;
-
-#endif /* ! MSDOS && ! WINDOWSNT && ! MAC_OS */
+struct display;
 
 struct frame
 {
@@ -278,20 +257,24 @@ struct frame
   /* Canonical Y unit.  Height of a line, in pixels.  */
   int line_height;
 
-  /* 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 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 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;
@@ -307,9 +290,12 @@ struct frame
   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, this points to initial_kboard.  For X frames,
-     it will be the same as display.x->display_info->kboard.  */
+     For termcap frames, it will be the same as
+     display->display_info.tty->kboard.
+     For X frames, it will be the same as
+     display->display_info.x->kboard.  */
   struct kboard *kboard;
 #endif
 
@@ -336,13 +322,13 @@ struct frame
      frame becomes visible again, it must be marked as garbaged.  The
      FRAME_SAMPLE_VISIBILITY macro takes care of this.
 
-     On Windows NT/9X, to avoid wasting effort updating visible frames
-     that are actually completely obscured by other windows on the
-     display, we bend the meaning of visible slightly: if greater than
-     1, then the frame is obscured - we still consider it to be
-     "visible" as seen from lisp, but we don't bother updating it.  We
-     must take care to garbage the frame when it ceaces to be obscured
-     though.  Note that these semantics are only used on NT/9X.
+     On ttys and on Windows NT/9X, to avoid wasting effort updating
+     visible frames that are actually completely obscured by other
+     windows on the display, we bend the meaning of visible slightly:
+     if greater than 1, then the frame is obscured - we still consider
+     it to be "visible" as seen from lisp, but we don't bother
+     updating it.  We must take care to garbage the frame when it
+     ceaces to be obscured though.
 
      iconified is nonzero if the frame is currently iconified.
 
@@ -455,7 +441,11 @@ struct frame
   /* Set to non-zero in when we want for force a flush_display in
      update_frame, usually after resizing the frame.  */
   unsigned force_flush_display_p : 1;
-
+  
+  /* All display backends seem to need these two pixel values. */
+  unsigned long background_pixel;
+  unsigned long foreground_pixel;
+  
   /* Set to non-zero if the default face for the frame has been
      realized.  Reset to zero whenever the default face changes.
      Used to see the difference between a font change and face change.  */
@@ -477,6 +467,7 @@ typedef struct frame *FRAME_PTR;
 #define WINDOW_FRAME(w) (w)->frame
 
 /* Test a frame for particular kinds of display methods.  */
+#define FRAME_INITIAL_P(f) ((f)->output_method == output_initial)
 #define FRAME_TERMCAP_P(f) ((f)->output_method == output_termcap)
 #define FRAME_X_P(f) ((f)->output_method == output_x_window)
 #define FRAME_W32_P(f) ((f)->output_method == output_w32)
@@ -500,7 +491,7 @@ typedef struct frame *FRAME_PTR;
 #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) \
@@ -740,7 +731,10 @@ typedef struct frame *FRAME_PTR;
 
    Also, if a frame used to be invisible, but has just become visible,
    it must be marked as garbaged, since redisplay hasn't been keeping
-   up its contents.  */
+   up its contents.
+
+   Note that a tty frame is visible if and only if it is the topmost
+   frame. */
 
 #define FRAME_SAMPLE_VISIBILITY(f) \
   (((f)->async_visible && (f)->visible != (f)->async_visible) ? \
@@ -780,10 +774,12 @@ typedef struct frame *FRAME_PTR;
 
 
 extern Lisp_Object Qframep, Qframe_live_p;
+extern Lisp_Object Qtty, Qtty_type;
 
 extern struct frame *last_nonminibuf_frame;
 
-extern struct frame *make_terminal_frame P_ ((void));
+extern struct frame *make_initial_frame P_ ((void));
+extern struct frame *make_terminal_frame P_ ((char *, char *));
 extern struct frame *make_frame P_ ((int));
 #ifdef HAVE_WINDOW_SYSTEM
 extern struct frame *make_minibuffer_frame P_ ((void));
@@ -1011,6 +1007,8 @@ extern Lisp_Object Qx_resource_name;
 extern Lisp_Object Qleft, Qright, Qtop, Qbox;
 extern Lisp_Object Qdisplay;
 
+extern Lisp_Object Qwindow_system;
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* The class of this X application.  */
index 3eafda4f6395102f79001a19e15c0f9d424624a5..aecb51349fcc2280cbece56f6eccaa1d586ae2cc 100644 (file)
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 #include "buffer.h"
 #include "blockinput.h"
+#include "termhooks.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 
@@ -588,7 +589,7 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
       break;
     }
 
-  rif->draw_fringe_bitmap (w, row, &p);
+  FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
 }
 
 void
@@ -997,8 +998,9 @@ If WHICH overrides a standard fringe bitmap, the original bitmap is restored.  *
   fbp = &fringe_bitmaps[n];
   if (*fbp && (*fbp)->dynamic)
     {
-      if (rif->destroy_fringe_bitmap)
-       rif->destroy_fringe_bitmap (n);
+      /* XXX Is SELECTED_FRAME OK here? */
+      if (FRAME_RIF (SELECTED_FRAME ())->destroy_fringe_bitmap)
+       FRAME_RIF (SELECTED_FRAME ())->destroy_fringe_bitmap (n);
       xfree (*fbp);
       *fbp = NULL;
     }
@@ -1079,8 +1081,9 @@ init_fringe_bitmap (which, fb, once_p)
     {
       Fdestroy_fringe_bitmap (make_number (which));
 
-      if (rif->define_fringe_bitmap)
-       rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
+      /* XXX Is SELECTED_FRAME OK here? */
+      if (FRAME_RIF (SELECTED_FRAME ())->define_fringe_bitmap)
+       FRAME_RIF (SELECTED_FRAME ())->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
 
       fringe_bitmaps[which] = fb;
       if (which >= max_used_fringe_bitmap)
@@ -1252,7 +1255,6 @@ resp.  Return nil if POS is not visible in WINDOW.  */)
      Lisp_Object pos, window;
 {
   struct window *w;
-  struct buffer *old_buffer = NULL;
   struct glyph_row *row;
   int textpos;
 
index 2651d4d7c0696810ec67b6f94ce3249c848c6425..99422698d512ec99d5f187b92ef51d66f2d9a7e0 100644 (file)
@@ -20,6 +20,8 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
+#include <stdio.h>
+
 #include "lisp.h"
 #include "buffer.h"
 #include "charset.h"
index 060731be64e722bed6c501c9f4a919da2bdbc40e..15e59537377db4643b5531d9a52036825f946b29 100644 (file)
@@ -85,7 +85,7 @@ struct interval
                         || STRINGP ((Lisp_Object){(EMACS_INT)(i)}))
 #endif
 #define NULL_INTERVAL_P(i) \
-   (CHECK (!INT_LISPLIKE (i), "non-interval"), (i) == NULL_INTERVAL)
+  ((void)CHECK (!INT_LISPLIKE (i), "non-interval"), (i) == NULL_INTERVAL)
 /* old #define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL || INT_LISPLIKE (i)) */
 
 /* True if this interval has no right child. */
@@ -289,6 +289,7 @@ extern INTERVAL balance_intervals P_ ((INTERVAL));
 extern INLINE void copy_intervals_to_string P_ ((Lisp_Object, struct buffer *,
                                                 int, int));
 extern INTERVAL copy_intervals P_ ((INTERVAL, int, int));
+extern int compare_string_intervals P_ ((Lisp_Object s1, Lisp_Object s2));
 extern Lisp_Object textget P_ ((Lisp_Object, Lisp_Object));
 extern Lisp_Object lookup_char_property P_ ((Lisp_Object, Lisp_Object, int));
 extern void move_if_not_intangible P_ ((int));
index 3e58a2a75a864f2c991f3885c5c1ea414743f85a..dc9bcd7f4f3713414b1099237da31d0ea1a5e645 100644 (file)
@@ -22,13 +22,13 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
-#include "lisp.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"
@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA.  */
 #endif /* not MSDOS */
 
 #include "syssignal.h"
-#include "systty.h"
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
@@ -89,9 +88,6 @@ int interrupt_input_blocked;
 int interrupt_input_pending;
 
 
-/* File descriptor to use for input.  */
-extern int input_fd;
-
 #ifdef HAVE_WINDOW_SYSTEM
 /* Make all keyboard buffers much bigger when using X windows.  */
 #ifdef MAC_OS8
@@ -464,11 +460,6 @@ FILE *dribble;
 /* Nonzero if input is available.  */
 int input_pending;
 
-/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
-   keep 0200 bit in input chars.  0 to ignore the 0200 bit.  */
-
-int meta_key;
-
 /* Non-zero means force key bindings update in parse_menu_item.  */
 
 int update_menu_bindings;
@@ -595,9 +586,6 @@ int interrupt_input;
 /* Nonzero while interrupts are temporarily deferred during redisplay.  */
 int interrupts_deferred;
 
-/* Nonzero means use ^S/^Q for flow control.  */
-int flow_control;
-
 /* Allow m- file to inhibit use of FIONREAD.  */
 #ifdef BROKEN_FIONREAD
 #undef FIONREAD
@@ -674,6 +662,7 @@ static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
 static void clear_event P_ ((struct input_event *));
 static void any_kboard_state P_ ((void));
 static SIGTYPE interrupt_signal P_ ((int signalnum));
+static void handle_interrupt P_ ((void));
 
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
@@ -1184,9 +1173,7 @@ cmd_error_internal (data, context)
   if (!sf->glyphs_initialized_p
       /* This is the case of the frame dumped with Emacs, when we're
         running under a window system.  */
-      || (!NILP (Vwindow_system)
-         && !inhibit_window_system
-         && FRAME_TERMCAP_P (sf))
+      || FRAME_INITIAL_P (sf)
       || noninteractive)
     {
       stream = Qexternal_debugging_output;
@@ -1335,6 +1322,7 @@ cancel_hourglass_unwind (arg)
      Lisp_Object arg;
 {
   cancel_hourglass ();
+  return Qnil;
 }
 #endif
 
@@ -1347,12 +1335,12 @@ command_loop_1 ()
   Lisp_Object keybuf[30];
   int i;
   int no_direct;
-  int prev_modiff;
+  int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
 #endif
-  int already_adjusted;
+  int already_adjusted = 0;
 
   current_kboard->Vprefix_arg = Qnil;
   current_kboard->Vlast_prefix_arg = Qnil;
@@ -2050,7 +2038,10 @@ void
 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.  */
@@ -2084,7 +2075,10 @@ int
 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
@@ -2096,7 +2090,10 @@ void
 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
 }
@@ -3612,7 +3609,7 @@ kbd_buffer_store_event_hold (event, hold_quit)
          }
 
          last_event_timestamp = event->timestamp;
-         interrupt_signal (0 /* dummy */);
+         handle_interrupt ();
          return;
        }
 
@@ -4088,7 +4085,11 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
         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);
+
+      /* XXX Can f or mouse_position_hook be NULL here? */
+      if (f && FRAME_DISPLAY (f)->mouse_position_hook)
+        (*FRAME_DISPLAY (f)->mouse_position_hook) (&f, 0, &bar_window,
+                                                   &part, &x, &y, &time);
 
       obj = Qnil;
 
@@ -6247,10 +6248,10 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist_or_stem,
          char *buf = (char *) alloca (len + 50);
          if (sizeof (int) == sizeof (EMACS_INT))
            sprintf (buf, "%s-%d", SDATA (name_alist_or_stem),
-                    XINT (symbol_int) + 1);
+                    (int)XINT (symbol_int) + 1);
          else if (sizeof (long) == sizeof (EMACS_INT))
            sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
-                    XINT (symbol_int) + 1);
+                    (long)XINT (symbol_int) + 1);
          value = intern (buf);
        }
       else if (name_table != 0 && name_table[symbol_num])
@@ -6529,7 +6530,10 @@ gobble_input (expected)
     }
   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));
@@ -6606,147 +6610,215 @@ static int
 read_avail_input (expected)
      int expected;
 {
-  register int i;
   int nread = 0;
+  int err = 0;
+  struct display *d;
 
-  if (read_socket_hook)
+  /* Loop through the available displays, and call their input hooks. */
+  d = display_list;
+  while (d)
     {
-      int discard = 0;
-      int nr;
-      struct input_event hold_quit;
+      struct display *next = d->next_display;
 
-      EVENT_INIT (hold_quit);
-      hold_quit.kind = NO_EVENT;
+      if (d->read_socket_hook)
+        {
+          int nr;
 
-      /* No need for FIONREAD or fcntl; just say don't wait.  */
-      while (nr = (*read_socket_hook) (input_fd, expected, &hold_quit), nr > 0)
-       {
-         nread += nr;
-         expected = 0;
-       }
-      if (hold_quit.kind != NO_EVENT)
-       kbd_buffer_store_event (&hold_quit);
+          struct input_event hold_quit;
+
+          EVENT_INIT (hold_quit);
+          hold_quit.kind = NO_EVENT;
+
+          /* No need for FIONREAD or fcntl; just say don't wait.  */
+          while (nr = (*d->read_socket_hook) (d, expected, &hold_quit), nr > 0)
+            {
+              nread += nr;
+              expected = 0;
+            }
+          
+          if (nr == -1)          /* Not OK to read input now. */
+            {
+              err = 1;
+            }
+          else if (nr == -2)          /* Non-transient error. */
+            {
+              /* The display device terminated; it should be closed. */
+              
+              /* Kill Emacs if this was our last display. */
+              if (! display_list->next_display)
+                /* Formerly simply reported no input, but that
+                   sometimes led to a failure of Emacs to terminate.
+                   SIGHUP seems appropriate if we can't reach the
+                   terminal.  */
+                /* ??? Is it really right to send the signal just to
+                   this process rather than to the whole process
+                   group?  Perhaps on systems with FIONREAD Emacs is
+                   alone in its group.  */
+                kill (getpid (), SIGHUP);
+              
+              /* XXX Is calling delete_display safe here?  It calls Fdelete_frame. */
+              if (d->delete_display_hook)
+                (*d->delete_display_hook) (d);
+              else
+                delete_display (d);
+            }
+
+          if (hold_quit.kind != NO_EVENT)
+            kbd_buffer_store_event (&hold_quit);
+        }
+
+      d = next;
     }
-  else
-    {
-      /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
-        the kbd_buffer can really hold.  That may prevent loss
-        of characters on some systems when input is stuffed at us.  */
-      unsigned char cbuf[KBD_BUFFER_SIZE - 1];
-      int n_to_read;
 
-      /* Determine how many characters we should *try* to read.  */
+  if (err && !nread)
+    nread = -1;
+
+  return nread;
+}
+
+/* This is the tty way of reading available input.
+
+   Note that each terminal device has its own `struct display' object,
+   and so this function is called once for each individual termcap
+   display.  The first parameter indicates which device to read from.  */
+
+int
+tty_read_avail_input (struct display *display,
+                      int expected,
+                      struct input_event *hold_quit)
+{
+  /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
+     the kbd_buffer can really hold.  That may prevent loss
+     of characters on some systems when input is stuffed at us.  */
+  unsigned char cbuf[KBD_BUFFER_SIZE - 1];
+  int n_to_read, i;
+  struct tty_display_info *tty = display->display_info.tty;
+  int nread = 0;
+
+  if (display->type != output_termcap)
+    abort ();
+
+  /* XXX I think the following code should be moved to separate hook
+     functions in system-dependent files. */
 #ifdef WINDOWSNT
-      return 0;
+  return 0;
 #else /* not WINDOWSNT */
 #ifdef MSDOS
-      n_to_read = dos_keysns ();
-      if (n_to_read == 0)
-       return 0;
+  n_to_read = dos_keysns ();
+  if (n_to_read == 0)
+    return 0;
+
+  cbuf[0] = dos_keyread ();
+  nread = 1;
+
 #else /* not MSDOS */
+
+  if (! tty->term_initted)      /* In case we get called during bootstrap. */
+    return 0;
+
+  if (! tty->input)
+    return 0;                   /* The terminal is suspended. */
+
+  /* Determine how many characters we should *try* to read.  */
 #ifdef FIONREAD
-      /* Find out how much input is available.  */
-      if (ioctl (input_fd, FIONREAD, &n_to_read) < 0)
-       /* Formerly simply reported no input, but that sometimes led to
-          a failure of Emacs to terminate.
-          SIGHUP seems appropriate if we can't reach the terminal.  */
-       /* ??? Is it really right to send the signal just to this process
-          rather than to the whole process group?
-          Perhaps on systems with FIONREAD Emacs is alone in its group.  */
-       {
-         if (! noninteractive)
-           kill (getpid (), SIGHUP);
-         else
-           n_to_read = 0;
-       }
-      if (n_to_read == 0)
-       return 0;
-      if (n_to_read > sizeof cbuf)
-       n_to_read = sizeof cbuf;
+  /* Find out how much input is available.  */
+  if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0)
+    {
+      if (! noninteractive)
+        return -2;          /* Close this display. */
+      else
+        n_to_read = 0;
+    }
+  if (n_to_read == 0)
+    return 0;
+  if (n_to_read > sizeof cbuf)
+    n_to_read = sizeof cbuf;
 #else /* no FIONREAD */
 #if defined (USG) || defined (DGUX) || defined(CYGWIN)
-      /* Read some input if available, but don't wait.  */
-      n_to_read = sizeof cbuf;
-      fcntl (input_fd, F_SETFL, O_NDELAY);
+  /* Read some input if available, but don't wait.  */
+  n_to_read = sizeof cbuf;
+  fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
 #else
-      you lose;
+  you lose;
 #endif
 #endif
-#endif /* not MSDOS */
-#endif /* not WINDOWSNT */
 
-      /* Now read; for one reason or another, this will not block.
-        NREAD is set to the number of chars read.  */
-      do
-       {
-#ifdef MSDOS
-         cbuf[0] = dos_keyread ();
-         nread = 1;
-#else
-         nread = emacs_read (input_fd, cbuf, n_to_read);
-#endif
-         /* POSIX infers that processes which are not in the session leader's
-            process group won't get SIGHUP's at logout time.  BSDI adheres to
-            this part standard and returns -1 from read (0) with errno==EIO
-            when the control tty is taken away.
-            Jeffrey Honig <jch@bsdi.com> says this is generally safe.  */
-         if (nread == -1 && errno == EIO)
-           kill (0, SIGHUP);
+  /* Now read; for one reason or another, this will not block.
+     NREAD is set to the number of chars read.  */
+  do
+    {
+      nread = emacs_read (fileno (tty->input), cbuf, n_to_read);
+      /* POSIX infers that processes which are not in the session leader's
+         process group won't get SIGHUP's at logout time.  BSDI adheres to
+         this part standard and returns -1 from read (0) with errno==EIO
+         when the control tty is taken away.
+         Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+      if (nread == -1 && errno == EIO)
+        return -2;          /* Close this display. */
 #if defined (AIX) && (! defined (aix386) && defined (_BSD))
-         /* The kernel sometimes fails to deliver SIGHUP for ptys.
-            This looks incorrect, but it isn't, because _BSD causes
-            O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
-            and that causes a value other than 0 when there is no input.  */
-         if (nread == 0)
-           kill (0, SIGHUP);
-#endif
-       }
-      while (
-            /* We used to retry the read if it was interrupted.
-               But this does the wrong thing when O_NDELAY causes
-               an EAGAIN error.  Does anybody know of a situation
-               where a retry is actually needed?  */
+      /* The kernel sometimes fails to deliver SIGHUP for ptys.
+         This looks incorrect, but it isn't, because _BSD causes
+         O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
+         and that causes a value other than 0 when there is no input.  */
+      if (nread == 0)
+        return -2;          /* Close this display. */
+#endif
+    }
+  while (
+         /* We used to retry the read if it was interrupted.
+            But this does the wrong thing when O_NDELAY causes
+            an EAGAIN error.  Does anybody know of a situation
+            where a retry is actually needed?  */
 #if 0
-            nread < 0 && (errno == EAGAIN
+         nread < 0 && (errno == EAGAIN
 #ifdef EFAULT
-                          || errno == EFAULT
+                       || errno == EFAULT
 #endif
 #ifdef EBADSLT
-                          || errno == EBADSLT
+                       || errno == EBADSLT
 #endif
-                          )
+                       )
 #else
-            0
+         0
 #endif
-            );
+         );
 
 #ifndef FIONREAD
 #if defined (USG) || defined (DGUX) || defined (CYGWIN)
-      fcntl (input_fd, F_SETFL, 0);
+  fcntl (fileno (tty->input), F_SETFL, 0);
 #endif /* USG or DGUX or CYGWIN */
 #endif /* no FIONREAD */
-      for (i = 0; i < nread; i++)
-       {
-         struct input_event buf;
-         EVENT_INIT (buf);
-         buf.kind = ASCII_KEYSTROKE_EVENT;
-         buf.modifiers = 0;
-         if (meta_key == 1 && (cbuf[i] & 0x80))
-           buf.modifiers = meta_modifier;
-         if (meta_key != 2)
-           cbuf[i] &= ~0x80;
-
-         buf.code = cbuf[i];
-         buf.frame_or_window = selected_frame;
-         buf.arg = Qnil;
-
-         kbd_buffer_store_event (&buf);
-         /* Don't look at input that follows a C-g too closely.
-            This reduces lossage due to autorepeat on C-g.  */
-         if (buf.kind == ASCII_KEYSTROKE_EVENT
-             && buf.code == quit_char)
-           break;
-       }
+
+  if (nread <= 0)
+    return nread;
+
+#endif /* not MSDOS */
+#endif /* not WINDOWSNT */
+
+  for (i = 0; i < nread; i++)
+    {
+      struct input_event buf;
+      EVENT_INIT (buf);
+      buf.kind = ASCII_KEYSTROKE_EVENT;
+      buf.modifiers = 0;
+      if (tty->meta_key == 1 && (cbuf[i] & 0x80))
+        buf.modifiers = meta_modifier;
+      if (tty->meta_key != 2)
+        cbuf[i] &= ~0x80;
+      
+      buf.code = cbuf[i];
+      /* Set the frame corresponding to the active tty.  Note that the
+         value of selected_frame is not reliable here, redisplay tends
+         to temporarily change it. */
+      buf.frame_or_window = tty->top_frame;
+      buf.arg = Qnil;
+      
+      kbd_buffer_store_event (&buf);
+      /* Don't look at input that follows a C-g too closely.
+         This reduces lossage due to autorepeat on C-g.  */
+      if (buf.kind == ASCII_KEYSTROKE_EVENT
+          && buf.code == quit_char)
+        break;
     }
 
   return nread;
@@ -9862,8 +9934,12 @@ detect_input_pending_run_timers (do_display)
         from an idle timer function.  The symptom of the bug is that
         the cursor sometimes doesn't become visible until the next X
         event is processed.  --gerd.  */
-      if (rif)
-       rif->flush_display (NULL);
+      {
+        Lisp_Object tail, frame;
+        FOR_EACH_FRAME (tail, frame)
+          if (FRAME_RIF (XFRAME (frame)))
+            FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
+      }
     }
 
   return input_pending;
@@ -10105,6 +10181,9 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
   int width, height;
   struct gcpro gcpro1;
 
+  if (tty_list && tty_list->next)
+    error ("Suspend is not supported with multiple ttys");
+
   if (!NILP (stuffstring))
     CHECK_STRING (stuffstring);
 
@@ -10113,11 +10192,11 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
     call1 (Vrun_hooks, intern ("suspend-hook"));
 
   GCPRO1 (stuffstring);
-  get_frame_size (&old_width, &old_height);
-  reset_sys_modes ();
+  get_tty_size (fileno (CURTTY ()->input), &old_width, &old_height);
+  reset_all_sys_modes ();
   /* sys_suspend can get an error if it tries to fork a subshell
      and the system resources aren't available for that.  */
-  record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes,
+  record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_all_sys_modes,
                         Qnil);
   stuff_buffered_input (stuffstring);
   if (cannot_suspend)
@@ -10129,7 +10208,7 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
   /* Check if terminal/window size has changed.
      Note that this is not useful when we are running directly
      with a window system; but suspend should be disabled in that case.  */
-  get_frame_size (&width, &height);
+  get_tty_size (fileno (CURTTY ()->input), &width, &height);
   if (width != old_width || height != old_height)
     change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
 
@@ -10189,10 +10268,10 @@ set_waiting_for_input (time_to_clear)
 {
   input_available_clear_time = time_to_clear;
 
-  /* Tell interrupt_signal to throw back to read_char,  */
+  /* Tell handle_interrupt to throw back to read_char,  */
   waiting_for_input = 1;
 
-  /* If interrupt_signal was called before and buffered a C-g,
+  /* If handle_interrupt was called before and buffered a C-g,
      make it run again now, to avoid timing error. */
   if (!NILP (Vquit_flag))
     quit_throw_to_read_char ();
@@ -10201,45 +10280,76 @@ set_waiting_for_input (time_to_clear)
 void
 clear_waiting_for_input ()
 {
-  /* Tell interrupt_signal not to throw back to read_char,  */
+  /* Tell handle_interrupt not to throw back to read_char,  */
   waiting_for_input = 0;
   input_available_clear_time = 0;
 }
 
-/* This routine is called at interrupt level in response to C-g.
-
-   If interrupt_input, this is the handler for SIGINT.  Otherwise, it
-   is called from kbd_buffer_store_event, in handling SIGIO or
-   SIGTINT.
+/* The SIGINT handler.
 
-   If `waiting_for_input' is non zero, then unless `echoing' is
-   nonzero, immediately throw back to read_char.
-
-   Otherwise it sets the Lisp variable quit-flag not-nil.  This causes
-   eval to throw, when it gets a chance.  If quit-flag is already
-   non-nil, it stops the job right away.  */
+   If we have a frame on the controlling tty, the SIGINT was generated
+   by C-g, so we call handle_interrupt.  Otherwise, the handler kills
+   Emacs.  */
 
 static SIGTYPE
 interrupt_signal (signalnum)   /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls. */
 {
-  char c;
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-  struct frame *sf = SELECTED_FRAME ();
+  struct display *display;
 
 #if defined (USG) && !defined (POSIX_SIGNALS)
-  if (!read_socket_hook && NILP (Vwindow_system))
+  /* USG systems forget handlers when they are used;
+     must reestablish each time */
+  signal (SIGINT, interrupt_signal);
+  signal (SIGQUIT, interrupt_signal);
+#endif /* USG */
+
+  /* See if we have a display on our controlling terminal. */
+  display = get_named_tty_display (NULL);
+  if (!display)
     {
-      /* USG systems forget handlers when they are used;
-        must reestablish each time */
-      signal (SIGINT, interrupt_signal);
-      signal (SIGQUIT, interrupt_signal);
+      /* If there are no frames there, let's pretend that we are a
+         well-behaving UN*X program and quit. */
+      Fkill_emacs (Qnil);
+    }
+  else
+    {
+      /* Otherwise, the SIGINT was probably generated by C-g.  */
+
+      /* Set internal_last_event_frame to the top frame of the
+         controlling tty, if we have a frame there.  We disable the
+         interrupt key on secondary ttys, so the SIGINT must have come
+         from the controlling tty.  */
+      internal_last_event_frame = display->display_info.tty->top_frame;
+
+      handle_interrupt ();
     }
-#endif /* USG */
+
+  errno = old_errno;
+}
+
+/* This routine is called at interrupt level in response to C-g.
+
+   It is called from the SIGINT handler or kbd_buffer_store_event.
+
+   If `waiting_for_input' is non zero, then unless `echoing' is
+   nonzero, immediately throw back to read_char.
+
+   Otherwise it sets the Lisp variable quit-flag not-nil.  This causes
+   eval to throw, when it gets a chance.  If quit-flag is already
+   non-nil, it stops the job right away. */
+
+static void
+handle_interrupt ()
+{
+  char c;
+  struct frame *sf = SELECTED_FRAME ();
 
   cancel_echoing ();
 
+  /* XXX This code needs to be revised for multi-tty support. */
   if (!NILP (Vquit_flag)
       && (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)))
     {
@@ -10249,7 +10359,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
       sigblock (sigmask (SIGINT));
 
       fflush (stdout);
-      reset_sys_modes ();
+      reset_all_sys_modes ();
 
 #ifdef SIGTSTP                 /* Support possible in later USG versions */
 /*
@@ -10328,7 +10438,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
       printf ("Continuing...\n");
 #endif /* not MSDOS */
       fflush (stdout);
-      init_sys_modes ();
+      init_all_sys_modes ();
       sigfree ();
     }
   else
@@ -10356,9 +10466,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
     }
 
   if (waiting_for_input && !echoing)
-    quit_throw_to_read_char ();
-
-  errno = old_errno;
+      quit_throw_to_read_char ();
 }
 
 /* Handle a C-g by making read_char return C-g.  */
@@ -10405,6 +10513,11 @@ See also `current-input-mode'.  */)
      (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");
@@ -10415,12 +10528,12 @@ See also `current-input-mode'.  */)
 
 #ifndef DOS_NT
   /* this causes startup screen to be restored and messes with the mouse */
-  reset_sys_modes ();
+  reset_all_sys_modes ();
 #endif
 
 #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.  */
@@ -10441,19 +10554,24 @@ See also `current-input-mode'.  */)
   interrupt_input = 1;
 #endif
 
-  flow_control = !NILP (flow);
-  if (NILP (meta))
-    meta_key = 0;
-  else if (EQ (meta, Qt))
-    meta_key = 1;
-  else
-    meta_key = 2;
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    {
+      struct tty_display_info *tty = CURTTY ();
+      tty->flow_control = !NILP (flow);
+      if (NILP (meta))
+        tty->meta_key = 0;
+      else if (EQ (meta, Qt))
+        tty->meta_key = 1;
+      else
+        tty->meta_key = 2;
+    }
+
   if (!NILP (quit))
     /* Don't let this value be out of range.  */
-    quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
+    quit_char = XINT (quit) & (NILP (meta) ? 0177 : 0377);
 
 #ifndef DOS_NT
-  init_sys_modes ();
+  init_all_sys_modes ();
 #endif
 
 #ifdef POLL_FOR_INPUT
@@ -10480,10 +10598,21 @@ The elements of this list correspond to the arguments of
      ()
 {
   Lisp_Object val[4];
+  struct frame *sf = XFRAME (selected_frame);
 
   val[0] = interrupt_input ? Qt : Qnil;
-  val[1] = flow_control ? Qt : Qnil;
-  val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil;
+  if (FRAME_TERMCAP_P (sf))
+    {
+      val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
+      val[2] = (FRAME_TTY (sf)->meta_key == 2
+                ? make_number (0)
+                : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
+    }
+  else
+    {
+      val[1] = Qnil;
+      val[2] = Qt;
+    }
   XSETFASTINT (val[3], quit_char);
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
@@ -10591,8 +10720,14 @@ init_keyboard ()
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
 
-  if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
+  if (!noninteractive)
     {
+      /* Before multi-tty support, these handlers used to be installed
+         only if the current session was a tty session.  Now an Emacs
+         session may have multiple display types, so we always handle
+         SIGINT.  There is special code in interrupt_signal to exit
+         Emacs on SIGINT when there are no termcap frames on the
+         controlling terminal. */
       signal (SIGINT, interrupt_signal);
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
       /* For systems with SysV TERMIO, C-g is set up for both SIGINT and
index d92f13a50596b6fc0d9a6b52f5e68cadc31c2f8a..3f38b7ded6b42d747cca8ab6bff4c364f0c18c08 100644 (file)
@@ -21,7 +21,7 @@ Boston, MA 02111-1307, USA.  */
 /* Length of echobuf field in each KBOARD.  */
 
 /* Each KBOARD represents one logical input stream from which Emacs gets input.
-   If we are using an ordinary terminal, it has one KBOARD object.
+   If we are using ordinary terminals, it has one KBOARD object for each terminal device.
    Usually each X display screen has its own KBOARD,
    but when two of them are on the same X server,
    we assume they share a keyboard and give them one KBOARD in common.
@@ -152,7 +152,7 @@ struct kboard
   };
 
 #ifdef MULTI_KBOARD
-/* Temporarily used before a frame has been opened, and for termcap frames */
+/* Temporarily used before a frame has been opened. */
 extern KBOARD *initial_kboard;
 
 /* In the single-kboard state, this is the kboard
@@ -342,5 +342,8 @@ extern void kbd_buffer_store_help_event P_ ((Lisp_Object, Lisp_Object));
 extern Lisp_Object menu_item_eval_property P_ ((Lisp_Object));
 extern int  kbd_buffer_events_waiting P_ ((int));
 
+extern int tty_read_avail_input P_ ((struct display *, int,
+                                     struct input_event *));
+
 /* arch-tag: 769cbade-1ba9-4950-b886-db265b061aa3
    (do not change this comment) */
index b181c3c507440ee1e080ec54ef35dec0fd12b431..4cea62c10fb678a1325b058522ecc51d20555a57 100644 (file)
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "buffer.h"
 #include "charset.h"
 #include "keyboard.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "blockinput.h"
 #include "puresize.h"
index 642162144997d7d053c8221ab8ad478550c30cd4..48b9c0c79120c266fac2119c887747f79e9769ce 100644 (file)
@@ -63,14 +63,14 @@ extern void die P_((const char *, const char *, int));
 
 #ifdef ENABLE_CHECKING
 
-#define CHECK(check,msg) (((check) || suppress_checking                \
-                          ? (void) 0                           \
-                          : die ((msg), __FILE__, __LINE__)),  \
+#define CHECK(check,msg) ((void)((check) || suppress_checking           \
+                                 ? (void) 0                             \
+                                 : die ((msg), __FILE__, __LINE__)),   \
                          0)
 #else
 
 /* Produce same side effects and result, but don't complain.  */
-#define CHECK(check,msg) ((check),0)
+#define CHECK(check,msg) ((void)(check),0)
 
 #endif
 
@@ -3002,26 +3002,28 @@ EXFUN (Fx_popup_menu, 2);
 EXFUN (Fx_popup_dialog, 2);
 extern void syms_of_xmenu P_ ((void));
 
+/* defined in termchar.h */
+struct tty_display_info;
+
+/* defined in termhooks.h */
+struct display;
+
 /* defined in sysdep.c */
 extern void stuff_char P_ ((char c));
 extern void init_sigio P_ ((int));
-extern void request_sigio P_ ((void));
-extern void unrequest_sigio P_ ((void));
-extern void reset_sys_modes P_ ((void));
 extern void sys_subshell P_ ((void));
 extern void sys_suspend P_ ((void));
 extern void discard_tty_input P_ ((void));
-extern void init_sys_modes P_ ((void));
-extern void reset_sys_modes P_ ((void));
-extern void get_frame_size P_ ((int *, int *));
+extern void init_sys_modes P_ ((struct tty_display_info *));
+extern void reset_sys_modes P_ ((struct tty_display_info *));
+extern void init_all_sys_modes P_ ((void));
+extern void reset_all_sys_modes P_ ((void));
 extern void wait_for_termination P_ ((int));
 extern void flush_pending_output P_ ((int));
 extern void child_setup_tty P_ ((int));
 extern void setup_pty P_ ((int));
 extern int set_window_size P_ ((int, int, int));
 extern void create_process P_ ((Lisp_Object, char **, Lisp_Object));
-extern int tabs_safe_p P_ ((void));
-extern void init_baud_rate P_ ((void));
 extern int emacs_open P_ ((const char *, int, int));
 extern int emacs_close P_ ((int));
 extern int emacs_read P_ ((int, char *, unsigned int));
index 4aa49c59eef778d2af0fff27347598417dbd08fd..ac353c798dc7a9fd726179cd48496a4491b4ea9d 100644 (file)
@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA.  */
 #include <epaths.h>
 #include "commands.h"
 #include "keyboard.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "coding.h"
 
index 6a0f1aa1b0fac11d4604f4126cbb31f9e49f0c95..93f3e73472447590b86037a4d7618d9781bc47b8 100644 (file)
@@ -9044,12 +9044,13 @@ mac_initialize ()
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
 
-  scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;          /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;   /* X does this well */
-  memory_below_frame = 0;       /* we don't remember what scrolls
-                                  off the bottom */
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
+                                                         scrolls off the
+                                                         bottom */
   baud_rate = 19200;
 
   x_noop_count = 0;
index 868ce88318c7995ec0a6714c08800c5980a7a3f3..1b4148ed71daa50e7291c752761e65a58058a5ce 100644 (file)
@@ -399,9 +399,6 @@ typedef struct mac_output mac_output;
 #define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP)
 #define FRAME_X_WINDOW(f) ((f)->output_data.mac->mWP)
 
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
-
 #define FRAME_FONT(f) ((f)->output_data.mac->font)
 #define FRAME_FONTSET(f) ((f)->output_data.mac->fontset)
 
index b91a4a4fc2a422272769bace6222afe669184d9b..1f5a114540d54d5ab0a3736865a491df26d2ff08 100644 (file)
@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA.  */
 #include "syntax.h"
 #include "intervals.h"
 #include "keymap.h"
+#include "termhooks.h"
 
 extern int quit_char;
 
@@ -695,8 +696,12 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
       XWINDOW (minibuf_window)->cursor.x = 0;
       XWINDOW (minibuf_window)->must_be_updated_p = 1;
       update_frame (XFRAME (selected_frame), 1, 1);
-      if (rif && rif->flush_display)
-       rif->flush_display (XFRAME (XWINDOW (minibuf_window)->frame));
+      {
+        struct frame *f = XFRAME (XWINDOW (minibuf_window)->frame);
+        struct redisplay_interface *rif = FRAME_RIF (f);
+        if (rif && rif->flush_display)
+          rif->flush_display (f);
+      }
     }
 
   /* Make minibuffer contents into a string.  */
index c58dc6875fef569cbb30bdf8ea72ab6a9c194a94..39d2856489020543b78d2514ed37f8b3c7c22c25 100644 (file)
@@ -2580,7 +2580,7 @@ internal_terminal_init ()
   set_terminal_modes_hook = IT_set_terminal_modes;
   reset_terminal_modes_hook = IT_reset_terminal_modes;
   set_terminal_window_hook = IT_set_terminal_window;
-  char_ins_del_ok = 0;
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0;
 #endif
 }
 
@@ -4858,7 +4858,7 @@ croak (badfunc)
      char *badfunc;
 {
   fprintf (stderr, "%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 \f
index 0db0638f85d7ba680fd43842d1547a1c6648c8bf..3e4b5dbc673d544cb1cff884929488138f501216 100644 (file)
@@ -126,11 +126,11 @@ Boston, MA 02111-1307, USA.  */
 #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"
@@ -302,11 +302,11 @@ extern int keyboard_bit_set P_ ((SELECT_TYPE *));
 
 static SELECT_TYPE input_wait_mask;
 
-/* Mask that excludes keyboard input descriptor (s).  */
+/* Mask that excludes keyboard input descriptor(s).  */
 
 static SELECT_TYPE non_keyboard_wait_mask;
 
-/* Mask that excludes process input descriptor (s).  */
+/* Mask that excludes process input descriptor(s).  */
 
 static SELECT_TYPE non_process_wait_mask;
 
@@ -6536,20 +6536,12 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
 
 
 \f
-/* The first time this is called, assume keyboard input comes from DESC
-   instead of from where we used to expect it.
-   Subsequent calls mean assume input keyboard can come from DESC
-   in addition to other places.  */
-
-static int add_keyboard_wait_descriptor_called_flag;
+/* Add DESC to the set of keyboard input descriptors.  */
 
 void
 add_keyboard_wait_descriptor (desc)
      int desc;
 {
-  if (! add_keyboard_wait_descriptor_called_flag)
-    FD_CLR (0, &input_wait_mask);
-  add_keyboard_wait_descriptor_called_flag = 1;
   FD_SET (desc, &input_wait_mask);
   FD_SET (desc, &non_process_wait_mask);
   if (desc > max_keyboard_desc)
@@ -6614,7 +6606,12 @@ init_process ()
   process_output_skip = 0;
 #endif
 
+  /* Don't do this, it caused infinite select loops.  The display
+     method should call add_keyboard_wait_descriptor on stdin if it
+     needs that.  */
+#if 0
   FD_SET (0, &input_wait_mask);
+#endif
 
   Vprocess_alist = Qnil;
   for (i = 0; i < MAXDESC; i++)
index 6c6aa4abf98a559e1932b0b4cc4f87a72a8746cd..8f83851a2e0231ff5443ffd0e9d57c53c419775e 100644 (file)
@@ -22,12 +22,13 @@ Boston, MA 02111-1307, USA.  */
 #include <config.h>
 #include <stdio.h>
 #include <string.h>
-#include "termchar.h"
 #include "lisp.h"
+#include "termchar.h"
 #include "dispextern.h"
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
+#include "termhooks.h"
 
 /* All costs measured in characters.
    So no cost can exceed the area of a frame, measured in characters.
@@ -100,7 +101,8 @@ calculate_scrolling (frame, matrix, window_size, lines_below,
   register struct matrix_elt *p, *p1;
   register int cost, cost1;
 
-  int lines_moved = window_size + (scroll_region_ok ? 0 : lines_below);
+  int lines_moved = window_size
+    + (FRAME_SCROLL_REGION_OK (frame) ? 0 : lines_below);
   /* first_insert_cost[I] is the cost of doing the first insert-line
      at the i'th line of the lines we are considering,
      where I is origin 1 (as it is below).  */
@@ -466,7 +468,8 @@ calculate_direct_scrolling (frame, matrix, window_size, lines_below,
   /* Overhead of setting the scroll window, plus the extra cost
      cost of scrolling by a distance of one.  The extra cost is
      added once for consistency with the cost vectors */
-  scroll_overhead = scroll_region_cost + extra_cost;
+  scroll_overhead
+    = FRAME_SCROLL_REGION_COST (frame) + extra_cost;
 
   /* initialize the top left corner of the matrix */
   matrix->writecost = 0;
@@ -818,7 +821,7 @@ scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
   matrix = ((struct matrix_elt *)
            alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
 
-  if (scroll_region_ok)
+  if (FRAME_SCROLL_REGION_OK (frame))
     {
       calculate_direct_scrolling (frame, matrix, window_size,
                                  unchanged_at_bottom,
@@ -914,7 +917,7 @@ scroll_cost (frame, from, to, amount)
   if (amount == 0)
     return 0;
 
-  if (! scroll_region_ok)
+  if (! FRAME_SCROLL_REGION_OK (frame))
     limit = height;
   else if (amount > 0)
     limit += amount;
index 5ede3d27208b11384f98cccd427584f5a38f4fac..20d57b6a6a3fb693827534e8ba3f8329eb77852a 100644 (file)
@@ -46,6 +46,8 @@ extern void srandom P_ ((unsigned int));
 #endif
 #endif
 
+#include "sysselect.h"
+
 #include "blockinput.h"
 #undef NULL
 
@@ -184,6 +186,7 @@ extern int quit_char;
 #include "termopts.h"
 #include "dispextern.h"
 #include "process.h"
+#include "cm.h"  /* for reset_sys_modes */
 
 #ifdef WINDOWSNT
 #include <direct.h>
@@ -246,16 +249,11 @@ static int baud_convert[] =
 
 int emacs_ospeed;
 
-/* The file descriptor for Emacs's input terminal.
-   Under Unix, this is normally zero except when using X;
-   under VMS, we place the input channel number here.  */
-int input_fd;
-
 void croak P_ ((char *));
 
 #ifdef AIXHFT
-void hft_init ();
-void hft_reset ();
+void hft_init P_ ((struct tty_display_info *));
+void hft_reset P_ ((struct tty_display_info *));
 #endif
 
 /* Temporary used by `sigblock' when defined in terms of signprocmask.  */
@@ -263,16 +261,7 @@ void hft_reset ();
 SIGMASKTYPE sigprocmask_set;
 
 \f
-/* Specify a different file descriptor for further input operations.  */
-
-void
-change_input_fd (fd)
-     int fd;
-{
-  input_fd = fd;
-}
-
-/* Discard pending input on descriptor input_fd.  */
+/* Discard pending input on all input descriptors.  */
 
 void
 discard_tty_input ()
@@ -283,54 +272,61 @@ discard_tty_input ()
   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, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
+  SYS$QIOW (0, fileno (CURTTY()->input), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
            &buf.main, 0, 0, terminator_mask, 0, 0);
   queue_kbd_input ();
 #else /* not VMS */
 #ifdef APOLLO
   {
-    int zero = 0;
-    ioctl (input_fd, TIOCFLUSH, &zero);
+    struct tty_display_info *tty;
+    for (tty = tty_list; tty; tty = tty->next)
+      {
+        int zero = 0;
+        if (tty->input)
+          ioctl (fileno (tty->input), TIOCFLUSH, &zero);
+      }
   }
 #else /* not Apollo */
 #ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
   while (dos_keyread () != -1)
     ;
 #else /* not MSDOS */
-  EMACS_GET_TTY (input_fd, &buf);
-  EMACS_SET_TTY (input_fd, &buf, 0);
+  {
+    struct tty_display_info *tty;
+    for (tty = tty_list; tty; tty = tty->next)
+      {
+        if (tty->input)         /* Is the device suspended? */
+          {
+            EMACS_GET_TTY (fileno (tty->input), &buf);
+            EMACS_SET_TTY (fileno (tty->input), &buf, 0);
+          }
+      }
+  }
 #endif /* not MSDOS */
 #endif /* not Apollo */
 #endif /* not VMS */
 #endif /* not WINDOWSNT */
 }
 
+\f
 #ifdef SIGTSTP
 
 /* Arrange for character C to be read as the next input from
-   the terminal.  */
+   the terminal.
+   XXX What if we have multiple ttys?
+*/
 
 void
-#ifdef PROTOTYPES
 stuff_char (char c)
-#else
-stuff_char (c)
-     char c;
-#endif
 {
-  if (read_socket_hook)
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
     return;
 
 /* Should perhaps error if in batch mode */
 #ifdef TIOCSTI
-  ioctl (input_fd, TIOCSTI, &c);
+  ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
 #else /* no TIOCSTI */
   error ("Cannot stuff terminal input characters in this version of Unix");
 #endif /* no TIOCSTI */
@@ -339,7 +335,7 @@ stuff_char (c)
 #endif /* SIGTSTP */
 \f
 void
-init_baud_rate ()
+init_baud_rate (int fd)
 {
   if (noninteractive)
     emacs_ospeed = 0;
@@ -354,7 +350,7 @@ init_baud_rate ()
 #ifdef VMS
       struct sensemode sg;
 
-      SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
+      SYS$QIOW (0, fd, IO$_SENSEMODE, &sg, 0, 0,
                &sg.class, 12, 0, 0, 0, 0 );
       emacs_ospeed = sg.xmit_baud;
 #else /* not VMS */
@@ -362,7 +358,7 @@ init_baud_rate ()
       struct termios sg;
 
       sg.c_cflag = B9600;
-      tcgetattr (input_fd, &sg);
+      tcgetattr (fd, &sg);
       emacs_ospeed = cfgetospeed (&sg);
 #if defined (USE_GETOBAUD) && defined (getobaud)
       /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
@@ -375,16 +371,16 @@ init_baud_rate ()
 
       sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (input_fd, &sg);
+      tcgetattr (fd, &sg);
 #else
-      ioctl (input_fd, TCGETA, &sg);
+      ioctl (fd, TCGETA, &sg);
 #endif
       emacs_ospeed = sg.c_cflag & CBAUD;
 #else /* neither VMS nor TERMIOS nor TERMIO */
       struct sgttyb sg;
 
       sg.sg_ospeed = B9600;
-      if (ioctl (input_fd, TIOCGETP, &sg) < 0)
+      if (ioctl (fd, TIOCGETP, &sg) < 0)
        abort ();
       emacs_ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
@@ -400,6 +396,7 @@ init_baud_rate ()
     baud_rate = 1200;
 }
 
+\f
 /*ARGSUSED*/
 void
 set_exclusive_use (fd)
@@ -658,7 +655,7 @@ child_setup_tty (out)
 
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (0);
 #endif /* BSD4_1 */
 #ifdef RTU
   {
@@ -915,53 +912,88 @@ restore_signal_handlers (saved_handlers)
     }
 }
 \f
+#ifndef SIGIO
+/* If SIGIO is broken, don't do anything. */
+void
+init_sigio (int fd)
+{
+}
+
+void
+reset_sigio (int fd)
+{
+}
+
+void
+request_sigio (void)
+{
+}
+
+void
+unrequest_sigio (void)
+{
+}
+
+#else
 #ifdef F_SETFL
 
-int old_fcntl_flags;
+int old_fcntl_flags[MAXDESC];
 
 void
 init_sigio (fd)
      int fd;
 {
 #ifdef FASYNC
-  old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
-  fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
+  old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
 #endif
   interrupts_deferred = 0;
 }
 
 void
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
-  unrequest_sigio ();
+#ifdef FASYNC
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
+#endif
 }
 
 #ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
+/* 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));
 #endif
-  fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
+  sigunblock (sigmask (SIGIO));
 
   interrupts_deferred = 0;
 }
 
 void
-unrequest_sigio ()
-{
+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
-  fcntl (input_fd, F_SETFL, old_fcntl_flags);
+  sigblock (sigmask (SIGIO));
   interrupts_deferred = 1;
 }
 
@@ -976,7 +1008,8 @@ request_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (input_fd, FIOASYNC, &on);
+  /* XXX CURTTY() is bogus here. */
+  ioctl (fileno (CURTTY ()->input), FIOASYNC, &on);
   interrupts_deferred = 0;
 }
 
@@ -988,7 +1021,8 @@ unrequest_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (input_fd, FIOASYNC, &off);
+  /* XXX CURTTY() is bogus here. */
+  ioctl (fileno (CURTTY ()->input), FIOASYNC, &off);
   interrupts_deferred = 1;
 }
 
@@ -1009,7 +1043,7 @@ request_sigio ()
 
   sigemptyset (&st);
   sigaddset (&st, SIGIO);
-  ioctl (input_fd, FIOASYNC, &on);
+  ioctl (0, FIOASYNC, &on);     /* XXX This fails for multiple ttys. */
   interrupts_deferred = 0;
   sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
 }
@@ -1022,7 +1056,7 @@ unrequest_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (input_fd, FIOASYNC, &off);
+  ioctl (0, FIOASYNC, &off);  /* XXX This fails for multiple ttys. */
   interrupts_deferred = 1;
 }
 
@@ -1052,6 +1086,7 @@ unrequest_sigio ()
 #endif /* STRIDE */
 #endif /* FASYNC */
 #endif /* F_SETFL */
+#endif /* SIGIO */
 \f
 /* Saving and restoring the process group of Emacs's terminal.  */
 
@@ -1074,30 +1109,35 @@ unrequest_sigio ()
    the tty's pgroup just like any other terminal setting.  If
    inherited_group was not the tty's pgroup, then we'll get a
    SIGTTmumble when we try to change the tty's pgroup, and a CONT if
-   it goes foreground in the future, which is what should happen.  */
+   it goes foreground in the future, which is what should happen.
+
+   This variable is initialized in emacs.c.  */
 int inherited_pgroup;
 
-/* Split off the foreground process group to Emacs alone.
-   When we are in the foreground, but not started in our own process
-   group, redirect the TTY to point to our own process group.  We need
-   to be in our own process group to receive SIGIO properly.  */
+/* Split off the foreground process group to Emacs alone.  When we are
+   in the foreground, but not started in our own process group,
+   redirect the tty device handle FD to point to our own process
+   group.  We need to be in our own process group to receive SIGIO
+   properly.  */
 void
-narrow_foreground_group ()
+narrow_foreground_group (int fd)
 {
   int me = getpid ();
 
   setpgrp (0, inherited_pgroup);
+  if (! inherited_pgroup)
+    abort ();                   /* Should not happen. */
   if (inherited_pgroup != me)
-    EMACS_SET_TTY_PGRP (input_fd, &me);
+      EMACS_SET_TTY_PGRP (fd, &me); /* XXX This only works on the controlling tty. */
   setpgrp (0, me);
 }
 
 /* Set the tty to our original foreground group.  */
 void
-widen_foreground_group ()
+widen_foreground_group (int fd)
 {
   if (inherited_pgroup != getpid ())
-    EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+    EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
   setpgrp (0, inherited_pgroup);
 }
 
@@ -1255,14 +1295,6 @@ emacs_set_tty (fd, settings, flushp)
 }
 
 \f
-/* The initial tty mode bits */
-struct emacs_tty old_tty;
-
-/* 1 if we have been through init_sys_modes.  */
-int term_initted;
-
-/* 1 if outer tty status has been recorded.  */
-int old_tty_valid;
 
 #ifdef BSD4_1
 /* BSD 4.1 needs to keep track of the lmode bits in order to start
@@ -1272,7 +1304,7 @@ int lmode;
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
-int old_fcntl_owner;
+int old_fcntl_owner[MAXDESC];
 #endif /* F_SETOWN */
 #endif /* F_SETOWN_BUG */
 
@@ -1297,8 +1329,22 @@ static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 #endif
 
+/* Initialize the terminal mode on all tty devices that are currently
+   open. */
+
 void
-init_sys_modes ()
+init_all_sys_modes (void)
+{
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
+    init_sys_modes (tty);
+}
+
+/* Initialize the terminal mode on the given tty device. */
+
+void
+init_sys_modes (tty_out)
+     struct tty_display_info *tty_out;
 {
   struct emacs_tty tty;
 
@@ -1324,6 +1370,9 @@ nil means don't delete them until `list-processes' is run.  */);
   if (noninteractive)
     return;
 
+  if (!tty_out->output)
+    return;                     /* The tty is suspended. */
+  
 #ifdef VMS
   if (!input_ef)
     input_ef = get_kbd_event_flag ();
@@ -1354,266 +1403,287 @@ nil means don't delete them until `list-processes' is run.  */);
 #ifndef VMS4_4
   sys_access_reinit ();
 #endif
-#endif /* not VMS */
+#endif /* VMS */
 
 #ifdef BSD_PGRPS
-  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
-    narrow_foreground_group ();
+#if 0
+  /* read_socket_hook is not global anymore.  I think doing this
+     unconditionally will not cause any problems. */
+  if (! read_socket_hook && EQ (Vinitial_window_system, Qnil))
 #endif
-
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the initialization code below.  */
-  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+    narrow_foreground_group (fileno (tty_out->input));
 #endif
-    {
-      EMACS_GET_TTY (input_fd, &old_tty);
 
-      old_tty_valid = 1;
+  if (! tty_out->old_tty)
+    tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
+      
+  EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
 
-      tty = old_tty;
+  tty = *tty_out->old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
-      XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
+  XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
 
 #ifdef DGUX
-      /* This allows meta to be sent on 8th bit.  */
-      tty.main.c_iflag &= ~INPCK;      /* don't check input for parity */
+  /* This allows meta to be sent on 8th bit.  */
+  tty.main.c_iflag &= ~INPCK;  /* don't check input for parity */
 #endif
-      tty.main.c_iflag |= (IGNBRK);    /* Ignore break condition */
-      tty.main.c_iflag &= ~ICRNL;      /* Disable map of CR to NL on input */
+  tty.main.c_iflag |= (IGNBRK);        /* Ignore break condition */
+  tty.main.c_iflag &= ~ICRNL;  /* Disable map of CR to NL on input */
 #ifdef INLCR  /* I'm just being cautious,
                 since I can't check how widespread INLCR is--rms.  */
-      tty.main.c_iflag &= ~INLCR;      /* Disable map of NL to CR on input */
+  tty.main.c_iflag &= ~INLCR;  /* Disable map of NL to CR on input */
 #endif
 #ifdef ISTRIP
-      tty.main.c_iflag &= ~ISTRIP;     /* don't strip 8th bit on input */
+  tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
 #endif
-      tty.main.c_lflag &= ~ECHO;       /* Disable echo */
-      tty.main.c_lflag &= ~ICANON;     /* Disable erase/kill processing */
+  tty.main.c_lflag &= ~ECHO;   /* Disable echo */
+  tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
 #ifdef IEXTEN
-      tty.main.c_lflag &= ~IEXTEN;     /* Disable other editing characters.  */
+  tty.main.c_lflag &= ~IEXTEN; /* Disable other editing characters.  */
 #endif
-      tty.main.c_lflag |= ISIG;        /* Enable signals */
-      if (flow_control)
-       {
-         tty.main.c_iflag |= IXON;     /* Enable start/stop output control */
+  tty.main.c_lflag |= ISIG;    /* Enable signals */
+  if (tty_out->flow_control)
+    {
+      tty.main.c_iflag |= IXON;        /* Enable start/stop output control */
 #ifdef IXANY
-         tty.main.c_iflag &= ~IXANY;
+      tty.main.c_iflag &= ~IXANY;
 #endif /* IXANY */
-       }
-      else
-       tty.main.c_iflag &= ~IXON;      /* Disable start/stop output control */
-      tty.main.c_oflag &= ~ONLCR;      /* Disable map of NL to CR-NL
-                                          on output */
-      tty.main.c_oflag &= ~TAB3;       /* Disable tab expansion */
+    }
+  else
+    tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
+  tty.main.c_oflag &= ~ONLCR;  /* Disable map of NL to CR-NL
+                                   on output */
+  tty.main.c_oflag &= ~TAB3;   /* Disable tab expansion */
 #ifdef CS8
-      if (meta_key)
-       {
-         tty.main.c_cflag |= CS8;      /* allow 8th bit on input */
-         tty.main.c_cflag &= ~PARENB;/* Don't check parity */
-       }
+  if (tty_out->meta_key)
+    {
+      tty.main.c_cflag |= CS8; /* allow 8th bit on input */
+      tty.main.c_cflag &= ~PARENB;/* Don't check parity */
+    }
 #endif
+  if (tty_out->input == stdin)
+    {
       tty.main.c_cc[VINTR] = quit_char;        /* C-g (usually) gives SIGINT */
       /* Set up C-g for both SIGQUIT and SIGINT.
-        We don't know which we will get, but we handle both alike
-        so which one it really gives us does not matter.  */
+         We don't know which we will get, but we handle both alike
+         so which one it really gives us does not matter.  */
       tty.main.c_cc[VQUIT] = quit_char;
-      tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
-      tty.main.c_cc[VTIME] = 0;        /* no matter how long that takes.  */
+    }
+  else
+    {
+      /* We normally don't get interrupt or quit signals from tty
+         devices other than our controlling terminal; therefore,
+         we must handle C-g as normal input.  Unfortunately, this
+         means that the interrupt and quit feature must be
+         disabled on secondary ttys, or we would not even see the
+         keypress.
+         
+         Note that even though emacsclient could have special code
+         to pass SIGINT to Emacs, we should _not_ enable
+         interrupt/quit keys for emacsclient frames.  This means
+         that we can't break out of loops in C code from a
+         secondary tty frame, but we can always decide what
+         display the C-g came from, which is more important from a
+         usability point of view.  (Consider the case when two
+         people work together using the same Emacs instance.)  */
+      tty.main.c_cc[VINTR] = CDISABLE;
+      tty.main.c_cc[VQUIT] = CDISABLE;
+    }
+  tty.main.c_cc[VMIN] = 1;     /* Input should wait for at least 1 char */
+  tty.main.c_cc[VTIME] = 0;    /* no matter how long that takes.  */
 #ifdef VSWTCH
-      tty.main.c_cc[VSWTCH] = CDISABLE;        /* Turn off shell layering use
+  tty.main.c_cc[VSWTCH] = CDISABLE;    /* Turn off shell layering use
                                           of C-z */
 #endif /* VSWTCH */
-
+  
 #if defined (mips) || defined (HAVE_TCATTR)
 #ifdef VSUSP
-      tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z.  */
+  tty.main.c_cc[VSUSP] = CDISABLE;     /* Turn off mips handling of C-z.  */
 #endif /* VSUSP */
 #ifdef V_DSUSP
-      tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
+  tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y.  */
 #endif /* V_DSUSP */
 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
-      tty.main.c_cc[VDSUSP] = CDISABLE;
+  tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* VDSUSP */
 #ifdef VLNEXT
-      tty.main.c_cc[VLNEXT] = CDISABLE;
+  tty.main.c_cc[VLNEXT] = CDISABLE;
 #endif /* VLNEXT */
 #ifdef VREPRINT
-      tty.main.c_cc[VREPRINT] = CDISABLE;
+  tty.main.c_cc[VREPRINT] = CDISABLE;
 #endif /* VREPRINT */
 #ifdef VWERASE
-      tty.main.c_cc[VWERASE] = CDISABLE;
+  tty.main.c_cc[VWERASE] = CDISABLE;
 #endif /* VWERASE */
 #ifdef VDISCARD
-      tty.main.c_cc[VDISCARD] = CDISABLE;
+  tty.main.c_cc[VDISCARD] = CDISABLE;
 #endif /* VDISCARD */
 
-      if (flow_control)
-       {
+  if (tty_out->flow_control)
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = '\021';
+      tty.main.c_cc[VSTART] = '\021';
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = '\023';
+      tty.main.c_cc[VSTOP] = '\023';
 #endif /* VSTOP */
-       }
-      else
-       {
+    }
+  else
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = CDISABLE;
+      tty.main.c_cc[VSTART] = CDISABLE;
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = CDISABLE;
+      tty.main.c_cc[VSTOP] = CDISABLE;
 #endif /* VSTOP */
-       }
+    }
 #endif /* mips or HAVE_TCATTR */
 
 #ifdef SET_LINE_DISCIPLINE
-      /* Need to explicitly request TERMIODISC line discipline or
-         Ultrix's termios does not work correctly.  */
-      tty.main.c_line = SET_LINE_DISCIPLINE;
+  /* Need to explicitly request TERMIODISC line discipline or
+     Ultrix's termios does not work correctly.  */
+  tty.main.c_line = SET_LINE_DISCIPLINE;
 #endif
 #ifdef AIX
 #ifndef IBMR2AIX
-      /* AIX enhanced edit loses NULs, so disable it.  */
-      tty.main.c_line = 0;
-      tty.main.c_iflag &= ~ASCEDIT;
+  /* AIX enhanced edit loses NULs, so disable it.  */
+  tty.main.c_line = 0;
+  tty.main.c_iflag &= ~ASCEDIT;
 #else
-      tty.main.c_cc[VSTRT] = 255;
-      tty.main.c_cc[VSTOP] = 255;
-      tty.main.c_cc[VSUSP] = 255;
-      tty.main.c_cc[VDSUSP] = 255;
+  tty.main.c_cc[VSTRT] = 255;
+  tty.main.c_cc[VSTOP] = 255;
+  tty.main.c_cc[VSUSP] = 255;
+  tty.main.c_cc[VDSUSP] = 255;
 #endif /* IBMR2AIX */
-      if (flow_control)
-       {
+  if (tty_out->flow_control)
+    {
 #ifdef VSTART
-         tty.main.c_cc[VSTART] = '\021';
+      tty.main.c_cc[VSTART] = '\021';
 #endif /* VSTART */
 #ifdef VSTOP
-         tty.main.c_cc[VSTOP] = '\023';
+      tty.main.c_cc[VSTOP] = '\023';
 #endif /* VSTOP */
-       }
-      /* Also, PTY overloads NUL and BREAK.
-        don't ignore break, but don't signal either, so it looks like NUL.
-        This really serves a purpose only if running in an XTERM window
-        or via TELNET or the like, but does no harm elsewhere.  */
-      tty.main.c_iflag &= ~IGNBRK;
-      tty.main.c_iflag &= ~BRKINT;
+    }
+  /* Also, PTY overloads NUL and BREAK.
+     don't ignore break, but don't signal either, so it looks like NUL.
+     This really serves a purpose only if running in an XTERM window
+     or via TELNET or the like, but does no harm elsewhere.  */
+  tty.main.c_iflag &= ~IGNBRK;
+  tty.main.c_iflag &= ~BRKINT;
 #endif
 #else /* if not HAVE_TERMIO */
 #ifdef VMS
-      tty.main.tt_char |= TT$M_NOECHO;
-      if (meta_key)
-       tty.main.tt_char |= TT$M_EIGHTBIT;
-      if (flow_control)
-       tty.main.tt_char |= TT$M_TTSYNC;
-      else
-       tty.main.tt_char &= ~TT$M_TTSYNC;
-      tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
+  tty.main.tt_char |= TT$M_NOECHO;
+  if (meta_key)
+    tty.main.tt_char |= TT$M_EIGHTBIT;
+  if (tty_out->flow_control)
+    tty.main.tt_char |= TT$M_TTSYNC;
+  else
+    tty.main.tt_char &= ~TT$M_TTSYNC;
+  tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
 #else /* not VMS (BSD, that is) */
 #ifndef DOS_NT
-      XSETINT (Vtty_erase_char, tty.main.sg_erase);
-      tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
-      if (meta_key)
-       tty.main.sg_flags |= ANYP;
-      tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
+  XSETINT (Vtty_erase_char, tty.main.sg_erase);
+  tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
+  if (meta_key)
+    tty.main.sg_flags |= ANYP;
+  tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
 #endif /* not DOS_NT */
 #endif /* not VMS (BSD, that is) */
 #endif /* not HAVE_TERMIO */
 
-      /* If going to use CBREAK mode, we must request C-g to interrupt
-        and turn off start and stop chars, etc.  If not going to use
-        CBREAK mode, do this anyway so as to turn off local flow
-        control for user coming over network on 4.2; in this case,
-        only t_stopc and t_startc really matter.  */
+  /* If going to use CBREAK mode, we must request C-g to interrupt
+     and turn off start and stop chars, etc.  If not going to use
+     CBREAK mode, do this anyway so as to turn off local flow
+     control for user coming over network on 4.2; in this case,
+     only t_stopc and t_startc really matter.  */
 #ifndef HAVE_TERMIO
 #ifdef HAVE_TCHARS
-      /* Note: if not using CBREAK mode, it makes no difference how we
-        set this */
-      tty.tchars = new_tchars;
-      tty.tchars.t_intrc = quit_char;
-      if (flow_control)
-       {
-         tty.tchars.t_startc = '\021';
-         tty.tchars.t_stopc = '\023';
-       }
-
-      tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
+  /* Note: if not using CBREAK mode, it makes no difference how we
+     set this */
+  tty.tchars = new_tchars;
+  tty.tchars.t_intrc = quit_char;
+  if (tty_out->flow_control)
+    {
+      tty.tchars.t_startc = '\021';
+      tty.tchars.t_stopc = '\023';
+    }
+  
+  tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode;
 #ifdef ultrix
-      /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
-        anything, and leaving it in breaks the meta key.  Go figure.  */
-      tty.lmode &= ~LLITOUT;
+  /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
+     anything, and leaving it in breaks the meta key.  Go figure.  */
+  tty.lmode &= ~LLITOUT;
 #endif
-
+  
 #ifdef BSD4_1
-      lmode = tty.lmode;
+  lmode = tty.lmode;
 #endif
 
 #endif /* HAVE_TCHARS */
 #endif /* not HAVE_TERMIO */
 
 #ifdef HAVE_LTCHARS
-      tty.ltchars = new_ltchars;
+  tty.ltchars = new_ltchars;
 #endif /* HAVE_LTCHARS */
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-      if (!term_initted)
-       internal_terminal_init ();
-      dos_ttraw ();
+  if (!tty_out->term_initted)
+    internal_terminal_init ();
+  dos_ttraw ();
 #endif
 
-      EMACS_SET_TTY (input_fd, &tty, 0);
+  EMACS_SET_TTY (fileno (tty_out->input), &tty, 0);
 
-      /* This code added to insure that, if flow-control is not to be used,
-        we have an unlocked terminal at the start. */
+  /* This code added to insure that, if flow-control is not to be used,
+     we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (input_fd, TCXONC, 1);
+  if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
 #endif
 #ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
+  if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
 #endif
 #endif
 
 #if defined (HAVE_TERMIOS) || defined (HPUX9)
 #ifdef TCOON
-      if (!flow_control) tcflow (input_fd, TCOON);
+  if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
 #endif
 #endif
 
 #ifdef AIXHFT
-      hft_init ();
+  hft_init (tty_out);
 #ifdef IBMR2AIX
-      {
-       /* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
-          to be only LF.  This is the way that is done. */
-       struct termio tty;
-
-       if (ioctl (1, HFTGETID, &tty) != -1)
-         write (1, "\033[20l", 5);
-      }
+  {
+    /* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
+       to be only LF.  This is the way that is done. */
+    struct termio tty;
+    
+    if (ioctl (1, HFTGETID, &tty) != -1)
+      write (1, "\033[20l", 5);
+  }
 #endif
 #endif /* AIXHFT */
 
 #ifdef VMS
 /*  Appears to do nothing when in PASTHRU mode.
-      SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
+      SYS$QIOW (0, fileno (tty_out->input), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
                interrupt_signal, oob_chars, 0, 0, 0, 0);
 */
-      queue_kbd_input (0);
+  queue_kbd_input (0);
 #endif /* VMS */
-    }
 
 #ifdef F_SETFL
 #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))
+  if (interrupt_input)
     {
-      old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
-      fcntl (input_fd, F_SETOWN, getpid ());
-      init_sigio (input_fd);
+      old_fcntl_owner[fileno (tty_out->input)] =
+        fcntl (fileno (tty_out->input), F_GETOWN, 0);
+      fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
+      init_sigio (fileno (tty_out->input));
     }
 #endif /* F_GETOWN */
 #endif /* F_SETOWN_BUG */
@@ -1621,7 +1691,7 @@ nil means don't delete them until `list-processes' is run.  */);
 
 #ifdef BSD4_1
   if (interrupt_input)
-    init_sigio (input_fd);
+    init_sigio (fileno (tty_out->input));
 #endif
 
 #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
@@ -1631,53 +1701,55 @@ nil means don't delete them until `list-processes' is run.  */);
   /* This symbol is defined on recent USG systems.
      Someone says without this call USG won't really buffer the file
      even with a call to setbuf. */
-  setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
+  setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
 #else
-  setbuf (stdout, (char *) _sobuf);
-#endif
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the initialization code below.  */
-  if (EQ (Vwindow_system, Qnil)
-#ifndef WINDOWSNT
-      /* When running in tty mode on NT/Win95, we have a read_socket
-        hook, but still need the rest of the initialization code below.  */
-      && (! read_socket_hook)
+  setbuf (tty_out->output, (char *) _sobuf);
 #endif
-      )
-#endif
-    set_terminal_modes ();
 
-  if (!term_initted
-      && FRAMEP (Vterminal_frame)
-      && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
-    init_frame_faces (XFRAME (Vterminal_frame));
+  tty_set_terminal_modes (tty_out->display);
+
+  if (!tty_out->term_initted)
+    {
+      Lisp_Object tail, frame;
+      FOR_EACH_FRAME (tail, frame)
+        {
+          /* XXX This needs to be revised. */
+          if (FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (frame)) == tty_out)
+            init_frame_faces (XFRAME (frame));
+        }
+    }
 
-  if (term_initted && no_redraw_on_reenter)
+  if (tty_out->term_initted && no_redraw_on_reenter)
     {
       if (display_completed)
        direct_output_forward_char (0);
     }
   else
     {
+      Lisp_Object tail, frame;
       frame_garbaged = 1;
-      if (FRAMEP (Vterminal_frame))
-       FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
+      FOR_EACH_FRAME (tail, frame)
+        {
+          if (FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (frame)) == tty_out)
+            FRAME_GARBAGED_P (XFRAME (frame)) = 1;
+        }
     }
 
-  term_initted = 1;
+  tty_out->term_initted = 1;
 }
 
 /* Return nonzero if safe to use tabs in output.
    At the time this is called, init_sys_modes has not been done yet.  */
 
 int
-tabs_safe_p ()
+tabs_safe_p (int fd)
 {
-  struct emacs_tty tty;
+  struct emacs_tty etty;
 
-  EMACS_GET_TTY (input_fd, &tty);
-  return EMACS_TTY_TABS_OK (&tty);
+  EMACS_GET_TTY (fd, &etty);
+  return EMACS_TTY_TABS_OK (&etty);
 }
 \f
 /* Get terminal size from system.
@@ -1685,8 +1757,7 @@ tabs_safe_p ()
    We store 0 if there's no valid information.  */
 
 void
-get_frame_size (widthp, heightp)
-     int *widthp, *heightp;
+get_tty_size (int fd, int *widthp, int *heightp)
 {
 
 #ifdef TIOCGWINSZ
@@ -1694,7 +1765,7 @@ get_frame_size (widthp, heightp)
   /* BSD-style.  */
   struct winsize size;
 
-  if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
+  if (ioctl (fd, TIOCGWINSZ, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1708,7 +1779,7 @@ get_frame_size (widthp, heightp)
   /* SunOS - style.  */
   struct ttysize size;
 
-  if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
+  if (ioctl (fd, TIOCGSIZE, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1721,7 +1792,7 @@ get_frame_size (widthp, heightp)
 
   struct sensemode tty;
 
-  SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
+  SYS$QIOW (0, fd, IO$_SENSEMODE, &tty, 0, 0,
            &tty.class, 12, 0, 0, 0, 0);
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
@@ -1734,7 +1805,6 @@ get_frame_size (widthp, heightp)
   *widthp = 0;
   *heightp = 0;
 #endif
-
 #endif /* not VMS */
 #endif /* not SunOS-style */
 #endif /* not BSD-style */
@@ -1778,37 +1848,58 @@ set_window_size (fd, height, width)
 }
 
 \f
-/* Prepare the terminal for exiting Emacs; move the cursor to the
-   bottom of the frame, turn off interrupt-driven I/O, etc.  */
+
+/* Prepare all terminal devices for exiting Emacs. */
+
 void
-reset_sys_modes ()
+reset_all_sys_modes (void)
 {
-  struct frame *sf;
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
+    reset_sys_modes (tty);
+}
 
+/* Prepare the terminal for closing it; move the cursor to the
+   bottom of the frame, turn off interrupt-driven I/O, etc.  */
+
+void
+reset_sys_modes (tty_out)
+     struct tty_display_info *tty_out;
+{
   if (noninteractive)
     {
       fflush (stdout);
       return;
     }
-  if (!term_initted)
+  if (!tty_out->term_initted)
     return;
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
-     needs the clean-up code below.  */
-  if (!EQ (Vwindow_system, Qnil)
-#ifndef WINDOWSNT
-      /* When running in tty mode on NT/Win95, we have a read_socket
-        hook, but still need the rest of the clean-up code below.  */
-      || read_socket_hook
-#endif
-      )
-    return;
-#endif
-  sf = SELECTED_FRAME ();
-  cursor_to (FRAME_LINES (sf) - 1, 0);
-  clear_end_of_line (FRAME_COLS (sf));
-  /* clear_end_of_line may move the cursor */
-  cursor_to (FRAME_LINES (sf) - 1, 0);
+
+  if (!tty_out->output)
+    return;                     /* The tty is suspended. */
+  
+  /* Go to and clear the last line of the terminal. */
+
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+  
+  /* Code adapted from tty_clear_end_of_line. */
+  if (tty_out->TS_clr_line)
+    {
+      emacs_tputs (tty_out, tty_out->TS_clr_line, 1, cmputc);
+    }
+  else
+    {                  /* have to do it the hard way */
+      int i;
+      turn_off_insert (tty_out);
+      
+      for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
+        {
+          fputc (' ', tty_out->output);
+        }
+    }
+  
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+  fflush (tty_out->output);
+  
 #if defined (IBMR2AIX) && defined (AIXHFT)
   {
     /* HFT devices normally use ^J as a LF/CR.  We forced it to
@@ -1820,12 +1911,12 @@ reset_sys_modes ()
   }
 #endif
 
-  reset_terminal_modes ();
-  fflush (stdout);
+  tty_reset_terminal_modes (tty_out->display);
+  fflush (tty_out->output);
 #ifdef BSD_SYSTEM
 #ifndef BSD4_1
   /* Avoid possible loss of output when changing terminal modes.  */
-  fsync (fileno (stdout));
+  fsync (fileno (tty_out->output));
 #endif
 #endif
 
@@ -1834,22 +1925,25 @@ reset_sys_modes ()
 #ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
-      reset_sigio ();
-      fcntl (input_fd, F_SETOWN, old_fcntl_owner);
+      reset_sigio (fileno (tty_out->input));
+      fcntl (fileno (tty_out->input), F_SETOWN,
+             old_fcntl_owner[fileno (tty_out->input)]);
     }
 #endif /* F_SETOWN */
 #endif /* F_SETOWN_BUG */
 #ifdef O_NDELAY
-  fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
+  fcntl (fileno (tty_out->input), F_SETFL,
+         fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
 #endif
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (fileno (tty_out->input));
 #endif /* BSD4_1 */
 
-  if (old_tty_valid)
-    while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
+  if (tty_out->old_tty)
+    while (EMACS_SET_TTY (fileno (tty_out->input),
+                          tty_out->old_tty, 0) < 0 && errno == EINTR)
       ;
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
@@ -1860,7 +1954,7 @@ reset_sys_modes ()
   /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
      A different old line discipline is therefore not restored, yet.
      Restore the old line discipline by hand.  */
-  ioctl (0, TIOCSETD, &old_tty.main.c_line);
+  ioctl (0, TIOCSETD, &tty_out->old_tty.main.c_line);
 #endif
 
 #ifdef AIXHFT
@@ -1868,7 +1962,7 @@ reset_sys_modes ()
 #endif
 
 #ifdef BSD_PGRPS
-  widen_foreground_group ();
+  widen_foreground_group (fileno (tty_out->input));
 #endif
 }
 \f
@@ -1933,9 +2027,9 @@ init_vms_input ()
 {
   int status;
 
-  if (input_fd == 0)
+  if (fileno (CURTTY ()->input)) == 0)
     {
-      status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
+      status = SYS$ASSIGN (&input_dsc, &fileno (CURTTY ()->input)), 0, 0);
       if (! (status & 1))
        LIB$STOP (status);
     }
@@ -1946,7 +2040,7 @@ init_vms_input ()
 void
 stop_vms_input ()
 {
-  return SYS$DASSGN (input_fd);
+  return SYS$DASSGN (fileno (CURTTY ()->input)));
 }
 
 short input_buffer;
@@ -1962,7 +2056,7 @@ queue_kbd_input ()
 
   waiting_for_ast = 0;
   stop_input = 0;
-  status = SYS$QIO (0, input_fd, IO$_READVBLK,
+  status = SYS$QIO (0, fileno (CURTTY()->input), IO$_READVBLK,
                    &input_iosb, kbd_input_ast, 1,
                    &input_buffer, 1, 0, terminator_mask, 0, 0);
 }
@@ -2079,7 +2173,7 @@ end_kbd_input ()
 #endif
   if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_event! */
     {
-      SYS$CANCEL (input_fd);
+      SYS$CANCEL (fileno (CURTTY()->input));
       return;
     }
 
@@ -2088,7 +2182,7 @@ end_kbd_input ()
   SYS$CLREF (input_ef);
   waiting_for_ast = 1;
   stop_input = 1;
-  SYS$CANCEL (input_fd);
+  SYS$CANCEL (fileno (CURTTY()->input));
   SYS$SETAST (1);
   SYS$WAITFR (input_ef);
   waiting_for_ast = 0;
@@ -2150,7 +2244,8 @@ init_sigio (fd)
   request_sigio ();
 }
 
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   unrequest_sigio ();
 }
@@ -2485,7 +2580,9 @@ sys_select (nfds, rfds, wfds, efds, timeout)
      SELECT_TYPE *rfds, *wfds, *efds;
      EMACS_TIME *timeout;
 {
-  int ravail = 0;
+  /* XXX This needs to be updated for multi-tty support.  Is there
+     anybody who needs to emulate select these days?  */ 
+ int ravail = 0;
   SELECT_TYPE orfds;
   int timeoutval;
   int *local_timeout;
@@ -2500,7 +2597,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 #if defined (HAVE_SELECT) && defined (HAVE_X_WINDOWS)
   /* If we're using X, then the native select will work; we only need the
      emulation for non-X usage.  */
-  if (!NILP (Vwindow_system))
+  if (!NILP (Vinitial_window_system))
     return select (nfds, rfds, wfds, efds, timeout);
 #endif
   timeoutval = timeout ? EMACS_SECS (*timeout) : 100000;
@@ -2609,7 +2706,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
     }
   return ravail;
 }
-#endif /* not WINDOWSNT */
+#endif not WINDOWSNT
 
 /* Read keyboard input into the standard buffer,
    waiting for at least one character.  */
@@ -2617,6 +2714,8 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 void
 read_input_waiting ()
 {
+  /* XXX This needs to be updated for multi-tty support.  Is there
+     anybody who needs to emulate select these days?  */
   int nread, i;
   extern int quit_char;
 
@@ -2670,6 +2769,10 @@ read_input_waiting ()
     }
 }
 
+#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
+#define select sys_select
+#endif
+
 #endif /* not HAVE_SELECT */
 #endif /* not VMS */
 #endif /* not MSDOS */
@@ -2686,12 +2789,13 @@ init_sigio (fd)
 }
 
 void
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   if (noninteractive)
     return;
   lmode = ~LINTRUP & lmode;
-  ioctl (0, TIOCLSET, &lmode);
+  ioctl (fd, TIOCLSET, &lmode);
 }
 
 void
@@ -3139,7 +3243,7 @@ sys_getenv (name)
 #undef abort
 sys_abort ()
 {
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   LIB$SIGNAL (SS$_DEBUG);
 }
 #endif /* abort */
@@ -3456,7 +3560,7 @@ croak (badfunc)
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5044,7 +5148,7 @@ croak (badfunc)
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5066,7 +5170,7 @@ srandom (seed)
 
 /* Called from init_sys_modes.  */
 void
-hft_init ()
+hft_init (struct tty_display_info *tty_out)
 {
   int junk;
 
@@ -5112,15 +5216,12 @@ hft_init ()
     keymap.hfkey[1].hf_char = 127;
     hftctl (0, HFSKBD, &buf);
   }
-  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
-     at times.  */
-  line_ins_del_ok = char_ins_del_ok = 0;
 }
 
 /* Reset the rubout key to backspace.  */
 
 void
-hft_reset ()
+hft_reset (struct tty_display_info *tty_out)
 {
   struct hfbuf buf;
   struct hfkeymap keymap;
index 2b536758e276d33a11c6856db5562ccdebf6a00f..7c3690903df0d686d356ef1d66ad9fe16c573f58 100644 (file)
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
    indicate that SIGIO doesn't work by #undef-ing SIGIO.  If this file
    #includes <signal.h>, then that will re-#define SIGIO and confuse
    things.  */
+/* XXX This is not correct anymore, there is a BROKEN_SIGIO macro. */
 
 #define SIGMASKTYPE sigset_t
 
index dc0e51cdf8173aebb757e8a02cf3dfaf8b251d06..f43b77158aa4abf84c77e81f28d3b21f6c3724ac 100644 (file)
@@ -26,9 +26,16 @@ Boston, MA 02111-1307, USA.  */
 #include <ctype.h>
 #include <string.h>
 
+#include <sys/file.h>
+
+#include <unistd.h>             /* For isatty. */
+#include <termio.h>            /* For TIOCNOTTY. */
+
+#include <signal.h>
+
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
-#include "lisp.h"
 #include "charset.h"
 #include "coding.h"
 #include "keyboard.h"
@@ -38,6 +45,8 @@ Boston, MA 02111-1307, USA.  */
 #include "dispextern.h"
 #include "window.h"
 #include "keymap.h"
+#include "syssignal.h"
+#include "systty.h"
 
 /* For now, don't try to include termcap.h.  On some systems,
    configure finds a non-standard termcap.h that the main build
@@ -60,24 +69,42 @@ extern int tgetnum P_ ((char *id));
 #include "macterm.h"
 #endif
 
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
 static void turn_on_face P_ ((struct frame *, int face_id));
 static void turn_off_face P_ ((struct frame *, int face_id));
-static void tty_show_cursor P_ ((void));
-static void tty_hide_cursor P_ ((void));
+static void tty_show_cursor P_ ((struct tty_display_info *));
+static void tty_hide_cursor P_ ((struct tty_display_info *));
+
+void delete_initial_display 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,                                        \
+               (int) (FRAME_LINES (XFRAME (selected_frame))     \
+                      - curY (tty)),                            \
+               cmputc)
 
-#define OUTPUT(a) \
-     tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
-#define OUTPUT1(a) tputs (a, 1, cmputc)
-#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
+#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
+#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
 
-#define OUTPUT_IF(a)                                                   \
-     do {                                                              \
-       if (a)                                                          \
-         tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame))        \
-                         - curY), cmputc);                             \
-     } while (0)
+#define OUTPUT_IF(tty, a)                                               \
+  do {                                                                  \
+    if (a)                                                              \
+      emacs_tputs ((tty), a,                                            \
+                   (int) (FRAME_LINES (XFRAME (selected_frame))         \
+                          - curY (tty) ),                               \
+                   cmputc);                                             \
+  } while (0)
 
-#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
+#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
 
 /* Display space properties */
 
@@ -87,203 +114,33 @@ extern Lisp_Object Qspace, QCalign_to, QCwidth;
 
 Lisp_Object Vring_bell_function;
 
-/* Terminal characteristics that higher levels want to look at.
-   These are all extern'd in termchar.h */
-
-int must_write_spaces;         /* Nonzero means spaces in the text
-                                  must actually be output; can't just skip
-                                  over some columns to leave them blank.  */
-int min_padding_speed;         /* Speed below which no padding necessary */
-
-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 a scroll window,
-                                  measured in characters */
-int memory_below_frame;                /* Terminal remembers lines
-                                  scrolled off bottom */
-int fast_clear_end_of_line;    /* Terminal has a `ce' string */
-
-/* Nonzero means no need to redraw the entire frame on resuming
-   a suspended Emacs.  This is useful on terminals with multiple pages,
-   where one page is used for Emacs and another for all else. */
+/* Functions to call after deleting a tty. */
+Lisp_Object Vdelete_tty_after_functions;
 
-int no_redraw_on_reenter;
-
-/* Hook functions that you can set to snap out the functions in this file.
-   These are all extern'd in termhooks.h  */
-
-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));
+/* Functions to call after suspending a tty. */
+Lisp_Object Vsuspend_tty_functions;
 
-int (*read_socket_hook) P_ ((int, int, struct input_event *));
+/* Functions to call after resuming a tty. */
+Lisp_Object Vresume_tty_functions;
 
-void (*frame_up_to_date_hook) P_ ((struct frame *));
+/* Chain of all displays currently in use. */
+struct display *display_list;
 
-/* Return the current position of the mouse.
+/* The initial display device, created by initial_term_init. */
+struct display *initial_display;
 
-   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.
+/* Chain of all tty device parameters. */
+struct tty_display_info *tty_list;
 
-   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.
+/* Nonzero means no need to redraw the entire frame on resuming a
+   suspended Emacs.  This is useful on terminals with multiple
+   pages, where one page is used for Emacs and another for all
+   else. */
+int no_redraw_on_reenter;
 
-   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
-   row of the character cell the mouse is over.
+Lisp_Object Qframe_tty_name, Qframe_tty_type;
 
-   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));
-
-/* Strings, numbers and flags taken from the termcap entry.  */
-
-char *TS_ins_line;             /* "al" */
-char *TS_ins_multi_lines;      /* "AL" (one parameter, # lines to insert) */
-char *TS_bell;                 /* "bl" */
-char *TS_clr_to_bottom;                /* "cd" */
-char *TS_clr_line;             /* "ce", clear to end of line */
-char *TS_clr_frame;            /* "cl" */
-char *TS_set_scroll_region;    /* "cs" (2 params, first line and last line) */
-char *TS_set_scroll_region_1;   /* "cS" (4 params: total lines,
-                                  lines above scroll region, lines below it,
-                                  total lines again) */
-char *TS_del_char;             /* "dc" */
-char *TS_del_multi_chars;      /* "DC" (one parameter, # chars to delete) */
-char *TS_del_line;             /* "dl" */
-char *TS_del_multi_lines;      /* "DL" (one parameter, # lines to delete) */
-char *TS_delete_mode;          /* "dm", enter character-delete mode */
-char *TS_end_delete_mode;      /* "ed", leave character-delete mode */
-char *TS_end_insert_mode;      /* "ei", leave character-insert mode */
-char *TS_ins_char;             /* "ic" */
-char *TS_ins_multi_chars;      /* "IC" (one parameter, # chars to insert) */
-char *TS_insert_mode;          /* "im", enter character-insert mode */
-char *TS_pad_inserted_char;    /* "ip".  Just padding, no commands.  */
-char *TS_end_keypad_mode;      /* "ke" */
-char *TS_keypad_mode;          /* "ks" */
-char *TS_pad_char;             /* "pc", char to use as padding */
-char *TS_repeat;               /* "rp" (2 params, # times to repeat
-                                  and character to be repeated) */
-char *TS_end_standout_mode;    /* "se" */
-char *TS_fwd_scroll;           /* "sf" */
-char *TS_standout_mode;                /* "so" */
-char *TS_rev_scroll;           /* "sr" */
-char *TS_end_termcap_modes;    /* "te" */
-char *TS_termcap_modes;                /* "ti" */
-char *TS_visible_bell;         /* "vb" */
-char *TS_cursor_normal;                /* "ve" */
-char *TS_cursor_visible;       /* "vs" */
-char *TS_cursor_invisible;     /* "vi" */
-char *TS_set_window;           /* "wi" (4 params, start and end of window,
-                                  each as vpos and hpos) */
-
-/* Value of the "NC" (no_color_video) capability, or 0 if not
-   present.  */
-
-static int TN_no_color_video;
 
 /* Meaning of bits in no_color_video.  Each bit set means that the
    corresponding attribute cannot be combined with colors.  */
@@ -301,68 +158,6 @@ enum no_color_bit
   NC_ALT_CHARSET = 1 << 8
 };
 
-/* "md" -- turn on bold (extra bright mode).  */
-
-char *TS_enter_bold_mode;
-
-/* "mh" -- turn on half-bright mode.  */
-
-char *TS_enter_dim_mode;
-
-/* "mb" -- enter blinking mode.  */
-
-char *TS_enter_blink_mode;
-
-/* "mr" -- enter reverse video mode.  */
-
-char *TS_enter_reverse_mode;
-
-/* "us"/"ue" -- start/end underlining.  */
-
-char *TS_exit_underline_mode, *TS_enter_underline_mode;
-
-/* "as"/"ae" -- start/end alternate character set.  Not really
-   supported, yet.  */
-
-char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode;
-
-/* "me" -- switch appearances off.  */
-
-char *TS_exit_attribute_mode;
-
-/* "Co" -- number of colors.  */
-
-int TN_max_colors;
-
-/* "pa" -- max. number of color pairs on screen.  Not handled yet.
-   Could be a problem if not equal to TN_max_colors * TN_max_colors.  */
-
-int TN_max_pairs;
-
-/* "op" -- SVr4 set default pair to its original value.  */
-
-char *TS_orig_pair;
-
-/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
-   1 param, the color index.  */
-
-char *TS_set_foreground, *TS_set_background;
-
-int TF_hazeltine;      /* termcap hz flag. */
-int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */
-int TF_standout_motion;        /* termcap mi flag: can move while in standout mode. */
-int TF_underscore;     /* termcap ul flag: _ underlines if over-struck on
-                          non-blank position.  Must clear before writing _.  */
-int TF_teleray;                /* termcap xt flag: many weird consequences.
-                          For t1061. */
-
-static int RPov;       /* # chars to start a TS_repeat */
-
-static int delete_in_insert_mode;      /* delete mode == insert mode */
-
-static int se_is_so;   /* 1 if same string both enters and leaves
-                          standout mode */
-
 /* internal state */
 
 /* The largest frame width in any call to calculate_costs.  */
@@ -373,33 +168,19 @@ int max_frame_cols;
 
 int max_frame_lines;
 
-static int costs_set;    /* Nonzero if costs have been calculated. */
-
-int insert_mode;                       /* Nonzero when in insert mode.  */
-int standout_mode;                     /* Nonzero when in standout mode.  */
-
-/* Size of window specified by higher levels.
-   This is the number of lines, from the top of frame downwards,
-   which can participate in insert-line/delete-line operations.
-
-   Effectively it excludes the bottom frame_lines - specified_window_size
-   lines from those operations.  */
-
-int specified_window;
-
 /* Frame currently being redisplayed; 0 if not currently redisplaying.
    (Direct output does not count).  */
 
 FRAME_PTR updating_frame;
 
+/* Non-zero if we have dropped our controlling tty and therefore
+   should not open a frame on stdout. */
+static int no_controlling_tty;
+
 /* Provided for lisp packages.  */
 
 static int system_uses_terminfo;
 
-/* Flag used in tty_show/hide_cursor.  */
-
-static int tty_cursor_hidden;
-
 char *tparam ();
 
 extern char *tgetstr ();
@@ -419,6 +200,8 @@ extern char *tgetstr ();
 void
 ring_bell ()
 {
+  struct frame *f = XFRAME (selected_frame);
+
   if (!NILP (Vring_bell_function))
     {
       Lisp_Object function;
@@ -438,42 +221,58 @@ ring_bell ()
 
       Vring_bell_function = function;
     }
-  else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
-    (*ring_bell_hook) ();
-  else
-    OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
+  else if (FRAME_DISPLAY (f)->ring_bell_hook)
+    (*FRAME_DISPLAY (f)->ring_bell_hook) ();
+}
+
+/* Ring the bell on a tty. */
+
+void
+tty_ring_bell ()
+{
+  struct frame *f = XFRAME (selected_frame);
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  OUTPUT (tty, (tty->TS_visible_bell && visible_bell
+                ? tty->TS_visible_bell
+                : tty->TS_bell));
 }
 
+/* Set up termcap modes for Emacs. */
+
 void
-set_terminal_modes ()
+tty_set_terminal_modes (struct display *display)
 {
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+  struct tty_display_info *tty = display->display_info.tty;
+  
+  if (tty->output)
     {
-      OUTPUT_IF (TS_termcap_modes);
-      OUTPUT_IF (TS_cursor_visible);
-      OUTPUT_IF (TS_keypad_mode);
-      losecursor ();
+      OUTPUT_IF (tty, tty->TS_termcap_modes);
+      OUTPUT_IF (tty, tty->TS_cursor_visible);
+      OUTPUT_IF (tty, tty->TS_keypad_mode);
+      losecursor (tty);
     }
-  else
-    (*set_terminal_modes_hook) ();
 }
 
+/* Reset termcap modes before exiting Emacs. */
+
 void
-reset_terminal_modes ()
+tty_reset_terminal_modes (struct display *display)
 {
-  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+  struct tty_display_info *tty = display->display_info.tty;
+
+  if (tty->output)
     {
-      turn_off_highlight ();
-      turn_off_insert ();
-      OUTPUT_IF (TS_end_keypad_mode);
-      OUTPUT_IF (TS_cursor_normal);
-      OUTPUT_IF (TS_end_termcap_modes);
-      OUTPUT_IF (TS_orig_pair);
+      turn_off_highlight (tty);
+      turn_off_insert (tty);
+      OUTPUT_IF (tty, tty->TS_end_keypad_mode);
+      OUTPUT_IF (tty, tty->TS_cursor_normal);
+      OUTPUT_IF (tty, tty->TS_end_termcap_modes);
+      OUTPUT_IF (tty, tty->TS_orig_pair);
       /* Output raw CR so kernel can track the cursor hpos.  */
+      current_tty = tty;
       cmputc ('\r');
     }
-  else if (reset_terminal_modes_hook)
-    (*reset_terminal_modes_hook) ();
 }
 
 void
@@ -481,39 +280,59 @@ update_begin (f)
      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 (!XWINDOW (selected_window)->cursor_off_p)
-       tty_show_cursor ();
-      turn_off_insert ();
-      background_highlight ();
-    }
-  else
-    update_end_hook (f);
-
+  if (FRAME_DISPLAY (f)->update_end_hook)
+    (*FRAME_DISPLAY (f)->update_end_hook) (f);
   updating_frame = NULL;
 }
 
+/* Flag the end of a display update on a termcap display. */
+
+void
+tty_update_end (struct frame *f)
+{
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  if (!XWINDOW (selected_window)->cursor_off_p)
+    tty_show_cursor (tty);
+  turn_off_insert (tty);
+  background_highlight (tty);
+}
+
+/* Specify how many text lines, from the top of the window,
+   should be affected by insert-lines and delete-lines operations.
+   This, and those operations, are used only within an update
+   that is bounded by calls to update_begin and update_end.  */
+
 void
 set_terminal_window (size)
      int size;
 {
-  if (FRAME_TERMCAP_P (updating_frame))
-    {
-      specified_window = size ? size : FRAME_LINES (updating_frame);
-      if (scroll_region_ok)
-       set_scroll_region (0, specified_window);
-    }
-  else
-    set_terminal_window_hook (size);
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->set_terminal_window_hook)
+    (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size);
+}
+
+/* The implementation of set_terminal_window for termcap frames. */
+
+void
+tty_set_terminal_window (int size)
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  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);
 }
 
 void
@@ -521,77 +340,79 @@ set_scroll_region (start, stop)
      int start, stop;
 {
   char *buf;
-  struct frame *sf = XFRAME (selected_frame);
-
-  if (TS_set_scroll_region)
-    buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
-  else if (TS_set_scroll_region_1)
-    buf = tparam (TS_set_scroll_region_1, 0, 0,
-                 FRAME_LINES (sf), start,
-                 FRAME_LINES (sf) - stop,
-                 FRAME_LINES (sf));
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  if (tty->TS_set_scroll_region)
+    buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
+  else if (tty->TS_set_scroll_region_1)
+    buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
+                 FRAME_LINES (f), start,
+                 FRAME_LINES (f) - stop,
+                 FRAME_LINES (f));
   else
-    buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf));
+    buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
 
-  OUTPUT (buf);
+  OUTPUT (tty, buf);
   xfree (buf);
-  losecursor ();
+  losecursor (tty);
 }
 
 \f
 static void
-turn_on_insert ()
+turn_on_insert (struct tty_display_info *tty)
 {
-  if (!insert_mode)
-    OUTPUT (TS_insert_mode);
-  insert_mode = 1;
+  if (!tty->insert_mode)
+    OUTPUT (tty, tty->TS_insert_mode);
+  tty->insert_mode = 1;
 }
 
 void
-turn_off_insert ()
+turn_off_insert (struct tty_display_info *tty)
 {
-  if (insert_mode)
-    OUTPUT (TS_end_insert_mode);
-  insert_mode = 0;
+  if (tty->insert_mode)
+    OUTPUT (tty, tty->TS_end_insert_mode);
+  tty->insert_mode = 0;
 }
 \f
 /* Handle highlighting.  */
 
 void
-turn_off_highlight ()
+turn_off_highlight (struct tty_display_info *tty)
 {
-  if (standout_mode)
-    OUTPUT_IF (TS_end_standout_mode);
-  standout_mode = 0;
+  if (tty->standout_mode)
+    OUTPUT_IF (tty, tty->TS_end_standout_mode);
+  tty->standout_mode = 0;
 }
 
 static void
-turn_on_highlight ()
+turn_on_highlight (struct tty_display_info *tty)
 {
-  if (!standout_mode)
-    OUTPUT_IF (TS_standout_mode);
-  standout_mode = 1;
+  if (!tty->standout_mode)
+    OUTPUT_IF (tty, tty->TS_standout_mode);
+  tty->standout_mode = 1;
 }
 
 static void
-toggle_highlight ()
+toggle_highlight (struct tty_display_info *tty)
 {
-  if (standout_mode)
-    turn_off_highlight ();
+  if (tty->standout_mode)
+    turn_off_highlight (tty);
   else
-    turn_on_highlight ();
+    turn_on_highlight (tty);
 }
 
 
 /* Make cursor invisible.  */
 
 static void
-tty_hide_cursor ()
+tty_hide_cursor (struct tty_display_info *tty)
 {
-  if (tty_cursor_hidden == 0)
+  if (tty->cursor_hidden == 0)
     {
-      tty_cursor_hidden = 1;
-      OUTPUT_IF (TS_cursor_invisible);
+      tty->cursor_hidden = 1;
+      OUTPUT_IF (tty, tty->TS_cursor_invisible);
     }
 }
 
@@ -599,13 +420,13 @@ tty_hide_cursor ()
 /* Ensure that cursor is visible.  */
 
 static void
-tty_show_cursor ()
+tty_show_cursor (struct tty_display_info *tty)
 {
-  if (tty_cursor_hidden)
+  if (tty->cursor_hidden)
     {
-      tty_cursor_hidden = 0;
-      OUTPUT_IF (TS_cursor_normal);
-      OUTPUT_IF (TS_cursor_visible);
+      tty->cursor_hidden = 0;
+      OUTPUT_IF (tty, tty->TS_cursor_normal);
+      OUTPUT_IF (tty, tty->TS_cursor_visible);
     }
 }
 
@@ -615,23 +436,23 @@ tty_show_cursor ()
    depends on the user option inverse-video.  */
 
 void
-background_highlight ()
+background_highlight (struct tty_display_info *tty)
 {
   if (inverse_video)
-    turn_on_highlight ();
+    turn_on_highlight (tty);
   else
-    turn_off_highlight ();
+    turn_off_highlight (tty);
 }
 
 /* Set standout mode to the mode specified for the text to be output.  */
 
 static void
-highlight_if_desired ()
+highlight_if_desired (struct tty_display_info *tty)
 {
   if (inverse_video)
-    turn_on_highlight ();
+    turn_on_highlight (tty);
   else
-    turn_off_highlight ();
+    turn_off_highlight (tty);
 }
 \f
 
@@ -642,26 +463,32 @@ void
 cursor_to (vpos, hpos)
      int vpos, hpos;
 {
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
-    {
-      (*cursor_to_hook) (vpos, hpos);
-      return;
-    }
+  if (FRAME_DISPLAY (f)->cursor_to_hook)
+    (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
+}
+
+void
+tty_cursor_to (int vpos, int hpos)
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
-  if (! costs_set)
+  if (! tty->costs_set)
     return;
 
-  if (curY == vpos && curX == hpos)
+  if (curY (tty) == vpos
+      && curX (tty) == hpos)
     return;
-  if (!TF_standout_motion)
-    background_highlight ();
-  if (!TF_insmode_motion)
-    turn_off_insert ();
-  cmgoto (vpos, hpos);
+  if (!tty->TF_standout_motion)
+    background_highlight (tty);
+  if (!tty->TF_insmode_motion)
+    turn_off_insert (tty);
+  cmgoto (tty, vpos, hpos);
 }
 
 /* Similar but don't take any account of the wasted characters.  */
@@ -670,45 +497,61 @@ void
 raw_cursor_to (row, col)
      int row, col;
 {
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  if (! FRAME_TERMCAP_P (f))
-    {
-      (*raw_cursor_to_hook) (row, col);
-      return;
-    }
-  if (curY == row && curX == col)
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->raw_cursor_to_hook)
+    (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col);  
+}
+
+void
+tty_raw_cursor_to (int row, int col)
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  if (curY (tty) == row
+      && curX (tty) == col)
     return;
-  if (!TF_standout_motion)
-    background_highlight ();
-  if (!TF_insmode_motion)
-    turn_off_insert ();
-  cmgoto (row, col);
+  if (!tty->TF_standout_motion)
+    background_highlight (tty);
+  if (!tty->TF_insmode_motion)
+    turn_off_insert (tty);
+  cmgoto (tty, row, col);
 }
 \f
 /* Erase operations */
 
-/* clear from cursor to end of frame */
+/* Clear from cursor to end of frame. */
 void
 clear_to_end ()
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->clear_to_end_hook)
+    (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
+}
+
+/* Clear from cursor to end of frame on a termcap device. */
+
+void
+tty_clear_to_end (void)
 {
   register int i;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  struct tty_display_info *tty = FRAME_TTY (f);
 
-  if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
-    {
-      (*clear_to_end_hook) ();
-      return;
-    }
-  if (TS_clr_to_bottom)
+  if (tty->TS_clr_to_bottom)
     {
-      background_highlight ();
-      OUTPUT (TS_clr_to_bottom);
+      background_highlight (tty);
+      OUTPUT (tty, tty->TS_clr_to_bottom);
     }
   else
     {
-      for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++)
+      for (i = curY (tty); i < FRAME_LINES (f); i++)
        {
          cursor_to (i, 0);
-         clear_end_of_line (FRAME_COLS (XFRAME (selected_frame)));
+         clear_end_of_line (FRAME_COLS (f));
        }
     }
 }
@@ -718,19 +561,26 @@ clear_to_end ()
 void
 clear_frame ()
 {
-  struct frame *sf = XFRAME (selected_frame);
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  if (clear_frame_hook
-      && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf)))
-    {
-      (*clear_frame_hook) ();
-      return;
-    }
-  if (TS_clr_frame)
+  if (FRAME_DISPLAY (f)->clear_frame_hook)
+    (*FRAME_DISPLAY (f)->clear_frame_hook) ();
+}
+
+/* Clear an entire termcap frame. */
+
+void
+tty_clear_frame ()
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  if (tty->TS_clr_frame)
     {
-      background_highlight ();
-      OUTPUT (TS_clr_frame);
-      cmat (0, 0);
+      background_highlight (tty);
+      OUTPUT (tty, tty->TS_clr_frame);
+      cmat (tty, 0, 0);
     }
   else
     {
@@ -748,46 +598,52 @@ void
 clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
-  register int i;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  if (clear_end_of_line_hook
-      && ! FRAME_TERMCAP_P ((updating_frame
-                              ? updating_frame
-                            : XFRAME (selected_frame))))
-    {
-      (*clear_end_of_line_hook) (first_unused_hpos);
-      return;
-    }
+  if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
+    (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
+}
+
+/* An implementation of clear_end_of_line for termcap frames.
+
+   Note that the cursor may be moved, on terminals lacking a `ce' string.  */
+
+void
+tty_clear_end_of_line (int first_unused_hpos)
+{
+  register int i;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
-  if (! costs_set)
+  if (! tty->costs_set)
     return;
 
-  if (curX >= first_unused_hpos)
+  if (curX (tty) >= first_unused_hpos)
     return;
-  background_highlight ();
-  if (TS_clr_line)
+  background_highlight (tty);
+  if (tty->TS_clr_line)
     {
-      OUTPUT1 (TS_clr_line);
+      OUTPUT1 (tty, tty->TS_clr_line);
     }
   else
     {                  /* have to do it the hard way */
-      struct frame *sf = XFRAME (selected_frame);
-      turn_off_insert ();
+      turn_off_insert (tty);
 
       /* Do not write in last row last col with Auto-wrap on. */
-      if (AutoWrap && curY == FRAME_LINES (sf) - 1
-         && first_unused_hpos == FRAME_COLS (sf))
+      if (AutoWrap (tty)
+          && curY (tty) == FrameRows (tty) - 1
+         && first_unused_hpos == FrameCols (tty))
        first_unused_hpos--;
 
-      for (i = curX; i < first_unused_hpos; i++)
+      for (i = curX (tty); i < first_unused_hpos; i++)
        {
-         if (termscript)
-           fputc (' ', termscript);
-         putchar (' ');
+         if (tty->termscript)
+           fputc (' ', tty->termscript);
+         fputc (' ', tty->output);
        }
-      cmplus (first_unused_hpos - curX);
+      cmplus (tty, first_unused_hpos - curX (tty));
     }
 }
 \f
@@ -900,38 +756,47 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
 }
 
 
+/* Output LEN glyphs starting at STRING at the nominal cursor position.
+   Advance the nominal cursor over the text.  */
+
 void
 write_glyphs (string, len)
      register struct glyph *string;
      register int len;
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->write_glyphs_hook)
+    (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
+}
+
+/* An implementation of write_glyphs for termcap frames. */
+
+void
+tty_write_glyphs (struct glyph *string, int len)
 {
   int produced, consumed;
-  struct frame *sf = XFRAME (selected_frame);
-  struct frame *f = updating_frame ? updating_frame : sf;
   unsigned char conversion_buffer[1024];
   int conversion_buffer_size = sizeof conversion_buffer;
 
-  if (write_glyphs_hook
-      && ! FRAME_TERMCAP_P (f))
-    {
-      (*write_glyphs_hook) (string, len);
-      return;
-    }
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  turn_off_insert ();
-  tty_hide_cursor ();
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  turn_off_insert (tty);
+  tty_hide_cursor (tty);
 
   /* Don't dare write in last column of bottom line, if Auto-Wrap,
      since that would scroll the whole frame on some terminals.  */
 
-  if (AutoWrap
-      && curY + 1 == FRAME_LINES (sf)
-      && (curX + len) == FRAME_COLS (sf))
+  if (AutoWrap (tty)
+      && curY (tty) + 1 == FRAME_LINES (f)
+      && (curX (tty) + len) == FRAME_COLS (f))
     len --;
   if (len <= 0)
     return;
 
-  cmplus (len);
+  cmplus (tty, len);
 
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
@@ -948,7 +813,7 @@ write_glyphs (string, len)
          break;
 
       /* Turn appearance modes of the face of the run on.  */
-      highlight_if_desired ();
+      highlight_if_desired (tty);
       turn_on_face (f, face_id);
 
       while (n > 0)
@@ -961,11 +826,13 @@ write_glyphs (string, len)
                                           &consumed);
          if (produced > 0)
            {
-             fwrite (conversion_buffer, 1, produced, stdout);
-             if (ferror (stdout))
-               clearerr (stdout);
-             if (termscript)
-               fwrite (conversion_buffer, 1, produced, termscript);
+             fwrite (conversion_buffer, 1, produced,
+                      tty->output);
+             if (ferror (tty->output))
+               clearerr (tty->output);
+             if (tty->termscript)
+               fwrite (conversion_buffer, 1, produced,
+                        tty->termscript);
            }
          len -= consumed;
          n -= consumed;
@@ -974,7 +841,7 @@ write_glyphs (string, len)
 
       /* Turn appearance modes off.  */
       turn_off_face (f, face_id);
-      turn_off_highlight ();
+      turn_off_highlight (tty);
     }
 
   /* We may have to output some codes to terminate the writing.  */
@@ -985,53 +852,60 @@ write_glyphs (string, len)
                     0, conversion_buffer_size);
       if (terminal_coding.produced > 0)
        {
-         fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
-         if (ferror (stdout))
-           clearerr (stdout);
-         if (termscript)
+         fwrite (conversion_buffer, 1, terminal_coding.produced,
+                  tty->output);
+         if (ferror (tty->output))
+           clearerr (tty->output);
+         if (tty->termscript)
            fwrite (conversion_buffer, 1, terminal_coding.produced,
-                   termscript);
+                   tty->termscript);
        }
     }
 
-  cmcheckmagic ();
+  cmcheckmagic (tty);
 }
 
-/* If start is zero, insert blanks instead of a string at start */
+/* Insert LEN glyphs from START at the nominal cursor position.
+
+   If start is zero, insert blanks instead of a string at start */
 
 void
 insert_glyphs (start, len)
      register struct glyph *start;
      register int len;
 {
-  char *buf;
-  struct glyph *glyph = NULL;
-  struct frame *f, *sf;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
   if (len <= 0)
     return;
 
-  if (insert_glyphs_hook)
-    {
-      (*insert_glyphs_hook) (start, len);
-      return;
-    }
+  if (FRAME_DISPLAY (f)->insert_glyphs_hook)
+    (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
+}
+
+/* An implementation of insert_glyphs for termcap frames. */
+
+void
+tty_insert_glyphs (struct glyph *start, int len)
+{
+  char *buf;
+  struct glyph *glyph = NULL;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  sf = XFRAME (selected_frame);
-  f = updating_frame ? updating_frame : sf;
+  struct tty_display_info *tty = FRAME_TTY (f);
 
-  if (TS_ins_multi_chars)
+  if (tty->TS_ins_multi_chars)
     {
-      buf = tparam (TS_ins_multi_chars, 0, 0, len);
-      OUTPUT1 (buf);
+      buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
+      OUTPUT1 (tty, buf);
       xfree (buf);
       if (start)
        write_glyphs (start, len);
       return;
     }
 
-  turn_on_insert ();
-  cmplus (len);
+  turn_on_insert (tty);
+  cmplus (tty, len);
   /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail.  */
   terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
   while (len-- > 0)
@@ -1040,7 +914,7 @@ insert_glyphs (start, len)
       unsigned char conversion_buffer[1024];
       int conversion_buffer_size = sizeof conversion_buffer;
 
-      OUTPUT1_IF (TS_ins_char);
+      OUTPUT1_IF (tty, tty->TS_ins_char);
       if (!start)
        {
          conversion_buffer[0] = SPACEGLYPH;
@@ -1048,7 +922,7 @@ insert_glyphs (start, len)
        }
       else
        {
-         highlight_if_desired ();
+         highlight_if_desired (tty);
          turn_on_face (f, start->face_id);
          glyph = start;
          ++start;
@@ -1056,7 +930,7 @@ insert_glyphs (start, len)
             occupies more than one column.  */
          while (len && CHAR_GLYPH_PADDING_P (*start))
            {
-             OUTPUT1_IF (TS_ins_char);
+             OUTPUT1_IF (tty, tty->TS_ins_char);
              start++, len--;
            }
 
@@ -1072,58 +946,70 @@ insert_glyphs (start, len)
 
       if (produced > 0)
        {
-         fwrite (conversion_buffer, 1, produced, stdout);
-         if (ferror (stdout))
-           clearerr (stdout);
-         if (termscript)
-           fwrite (conversion_buffer, 1, produced, termscript);
+         fwrite (conversion_buffer, 1, produced,
+                  tty->output);
+         if (ferror (tty->output))
+           clearerr (tty->output);
+         if (tty->termscript)
+           fwrite (conversion_buffer, 1, produced,
+                    tty->termscript);
        }
 
-      OUTPUT1_IF (TS_pad_inserted_char);
+      OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
       if (start)
        {
          turn_off_face (f, glyph->face_id);
-         turn_off_highlight ();
+         turn_off_highlight (tty);
        }
     }
 
-  cmcheckmagic ();
+  cmcheckmagic (tty);
 }
 
+/* Delete N glyphs at the nominal cursor position. */
+
 void
 delete_glyphs (n)
      register int n;
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->delete_glyphs_hook)
+    (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
+}
+
+/* An implementation of delete_glyphs for termcap frames. */
+
+void
+tty_delete_glyphs (int n)
 {
   char *buf;
   register int i;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
 
-  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
-    {
-      (*delete_glyphs_hook) (n);
-      return;
-    }
+  struct tty_display_info *tty = FRAME_TTY (f);
 
-  if (delete_in_insert_mode)
+  if (tty->delete_in_insert_mode)
     {
-      turn_on_insert ();
+      turn_on_insert (tty);
     }
   else
     {
-      turn_off_insert ();
-      OUTPUT_IF (TS_delete_mode);
+      turn_off_insert (tty);
+      OUTPUT_IF (tty, tty->TS_delete_mode);
     }
 
-  if (TS_del_multi_chars)
+  if (tty->TS_del_multi_chars)
     {
-      buf = tparam (TS_del_multi_chars, 0, 0, n);
-      OUTPUT1 (buf);
+      buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
+      OUTPUT1 (tty, buf);
       xfree (buf);
     }
   else
     for (i = 0; i < n; i++)
-      OUTPUT1 (TS_del_char);
-  if (!delete_in_insert_mode)
-    OUTPUT_IF (TS_end_delete_mode);
+      OUTPUT1 (tty, tty->TS_del_char);
+  if (!tty->delete_in_insert_mode)
+    OUTPUT_IF (tty, tty->TS_end_delete_mode);
 }
 \f
 /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
@@ -1132,21 +1018,26 @@ void
 ins_del_lines (vpos, n)
      int vpos, n;
 {
-  char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
-  char *single = n > 0 ? TS_ins_line : TS_del_line;
-  char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
-  struct frame *sf;
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  
+  if (FRAME_DISPLAY (f)->ins_del_lines_hook)
+    (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n);
+}
 
-  register int i = n > 0 ? n : -n;
-  register char *buf;
+/* An implementation of ins_del_lines for termcap frames. */
 
-  if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
-    {
-      (*ins_del_lines_hook) (vpos, n);
-      return;
-    }
+void
+tty_ins_del_lines (int vpos, int n)
+{
+  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+  char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
+  char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
+  char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
 
-  sf = XFRAME (selected_frame);
+  register int i = n > 0 ? n : -n;
+  register char *buf;
 
   /* If the lines below the insertion are being pushed
      into the end of the window, this is the same as clearing;
@@ -1155,44 +1046,48 @@ ins_del_lines (vpos, n)
   /* If the lines below the deletion are blank lines coming
      out of the end of the window, don't bother,
      as there will be a matching inslines later that will flush them. */
-  if (scroll_region_ok && vpos + i >= specified_window)
+  if (FRAME_SCROLL_REGION_OK (f)
+      && vpos + i >= tty->specified_window)
     return;
-  if (!memory_below_frame && vpos + i >= FRAME_LINES (sf))
+  if (!FRAME_MEMORY_BELOW_FRAME (f)
+      && vpos + i >= FRAME_LINES (f))
     return;
-
+  
   if (multi)
     {
       raw_cursor_to (vpos, 0);
-      background_highlight ();
+      background_highlight (tty);
       buf = tparam (multi, 0, 0, i);
-      OUTPUT (buf);
+      OUTPUT (tty, buf);
       xfree (buf);
     }
   else if (single)
     {
       raw_cursor_to (vpos, 0);
-      background_highlight ();
+      background_highlight (tty);
       while (--i >= 0)
-       OUTPUT (single);
-      if (TF_teleray)
-       curX = 0;
+        OUTPUT (tty, single);
+      if (tty->TF_teleray)
+        curX (tty) = 0;
     }
   else
     {
-      set_scroll_region (vpos, specified_window);
+      set_scroll_region (vpos, tty->specified_window);
       if (n < 0)
-       raw_cursor_to (specified_window - 1, 0);
+        raw_cursor_to (tty->specified_window - 1, 0);
       else
-       raw_cursor_to (vpos, 0);
-      background_highlight ();
+        raw_cursor_to (vpos, 0);
+      background_highlight (tty);
       while (--i >= 0)
-       OUTPUTL (scroll, specified_window - vpos);
-      set_scroll_region (0, specified_window);
+        OUTPUTL (tty, scroll, tty->specified_window - vpos);
+      set_scroll_region (0, tty->specified_window);
     }
-
-  if (!scroll_region_ok && memory_below_frame && n < 0)
+  
+  if (!FRAME_SCROLL_REGION_OK (f)
+      && FRAME_MEMORY_BELOW_FRAME (f)
+      && n < 0)
     {
-      cursor_to (FRAME_LINES (sf) + n, 0);
+      cursor_to (FRAME_LINES (f) + n, 0);
       clear_to_end ();
     }
 }
@@ -1251,26 +1146,27 @@ int *char_ins_del_vector;
 
 /* ARGSUSED */
 static void
-calculate_ins_del_char_costs (frame)
-     FRAME_PTR frame;
+calculate_ins_del_char_costs (f)
+     FRAME_PTR f;
 {
+  struct tty_display_info *tty = FRAME_TTY (f);
   int ins_startup_cost, del_startup_cost;
   int ins_cost_per_char, del_cost_per_char;
   register int i;
   register int *p;
 
-  if (TS_ins_multi_chars)
+  if (tty->TS_ins_multi_chars)
     {
       ins_cost_per_char = 0;
-      ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
+      ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
     }
-  else if (TS_ins_char || TS_pad_inserted_char
-          || (TS_insert_mode && TS_end_insert_mode))
+  else if (tty->TS_ins_char || tty->TS_pad_inserted_char
+          || (tty->TS_insert_mode && tty->TS_end_insert_mode))
     {
-      ins_startup_cost = (30 * (string_cost (TS_insert_mode)
-                               + string_cost (TS_end_insert_mode))) / 100;
-      ins_cost_per_char = (string_cost_one_line (TS_ins_char)
-                          + string_cost_one_line (TS_pad_inserted_char));
+      ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
+                               + string_cost (tty->TS_end_insert_mode))) / 100;
+      ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
+                          + string_cost_one_line (tty->TS_pad_inserted_char));
     }
   else
     {
@@ -1278,18 +1174,18 @@ calculate_ins_del_char_costs (frame)
       ins_cost_per_char = 0;
     }
 
-  if (TS_del_multi_chars)
+  if (tty->TS_del_multi_chars)
     {
       del_cost_per_char = 0;
-      del_startup_cost = string_cost_one_line (TS_del_multi_chars);
+      del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
     }
-  else if (TS_del_char)
+  else if (tty->TS_del_char)
     {
-      del_startup_cost = (string_cost (TS_delete_mode)
-                         + string_cost (TS_end_delete_mode));
-      if (delete_in_insert_mode)
+      del_startup_cost = (string_cost (tty->TS_delete_mode)
+                         + string_cost (tty->TS_end_delete_mode));
+      if (tty->delete_in_insert_mode)
        del_startup_cost /= 2;
-      del_cost_per_char = string_cost_one_line (TS_del_char);
+      del_cost_per_char = string_cost_one_line (tty->TS_del_char);
     }
   else
     {
@@ -1298,16 +1194,16 @@ calculate_ins_del_char_costs (frame)
     }
 
   /* Delete costs are at negative offsets */
-  p = &char_ins_del_cost (frame)[0];
-  for (i = FRAME_COLS (frame); --i >= 0;)
+  p = &char_ins_del_cost (f)[0];
+  for (i = FRAME_COLS (f); --i >= 0;)
     *--p = (del_startup_cost += del_cost_per_char);
 
   /* Doing nothing is free */
-  p = &char_ins_del_cost (frame)[0];
+  p = &char_ins_del_cost (f)[0];
   *p++ = 0;
 
   /* Insert costs are at positive offsets */
-  for (i = FRAME_COLS (frame); --i >= 0;)
+  for (i = FRAME_COLS (f); --i >= 0;)
     *p++ = (ins_startup_cost += ins_cost_per_char);
 }
 
@@ -1315,58 +1211,64 @@ void
 calculate_costs (frame)
      FRAME_PTR frame;
 {
-  register char *f = (TS_set_scroll_region
-                     ? TS_set_scroll_region
-                     : TS_set_scroll_region_1);
-
   FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
-  scroll_region_cost = string_cost (f);
+  if (FRAME_TERMCAP_P (frame))
+    {
+      struct tty_display_info *tty = FRAME_TTY (frame);
+      register char *f = (tty->TS_set_scroll_region
+                          ? tty->TS_set_scroll_region
+                          : tty->TS_set_scroll_region_1);
 
-  /* These variables are only used for terminal stuff.  They are allocated
-     once for the terminal frame of X-windows emacs, but not used afterwards.
+      FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
 
-     char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
-     X turns off char_ins_del_ok. */
+      tty->costs_set = 1;
 
-  max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
-  max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
+      /* These variables are only used for terminal stuff.  They are
+         allocated once for the terminal frame of X-windows emacs, but not
+         used afterwards.
 
-  costs_set = 1;
+         char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
+         X turns off char_ins_del_ok. */
 
-  if (char_ins_del_vector != 0)
-    char_ins_del_vector
-      = (int *) xrealloc (char_ins_del_vector,
-                         (sizeof (int)
-                          + 2 * max_frame_cols * sizeof (int)));
-  else
-    char_ins_del_vector
-      = (int *) xmalloc (sizeof (int)
-                        + 2 * max_frame_cols * sizeof (int));
-
-  bzero (char_ins_del_vector, (sizeof (int)
-                              + 2 * max_frame_cols * sizeof (int)));
-
-  if (f && (!TS_ins_line && !TS_del_line))
-    do_line_insertion_deletion_costs (frame,
-                                     TS_rev_scroll, TS_ins_multi_lines,
-                                     TS_fwd_scroll, TS_del_multi_lines,
-                                     f, f, 1);
-  else
-    do_line_insertion_deletion_costs (frame,
-                                     TS_ins_line, TS_ins_multi_lines,
-                                     TS_del_line, TS_del_multi_lines,
-                                     0, 0, 1);
+      max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
+      max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
 
-  calculate_ins_del_char_costs (frame);
+      if (char_ins_del_vector != 0)
+        char_ins_del_vector
+          = (int *) xrealloc (char_ins_del_vector,
+                              (sizeof (int)
+                               + 2 * max_frame_cols * sizeof (int)));
+      else
+        char_ins_del_vector
+          = (int *) xmalloc (sizeof (int)
+                             + 2 * max_frame_cols * sizeof (int));
+
+      bzero (char_ins_del_vector, (sizeof (int)
+                                   + 2 * max_frame_cols * sizeof (int)));
 
-  /* Don't use TS_repeat if its padding is worse than sending the chars */
-  if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
-    RPov = string_cost (TS_repeat);
-  else
-    RPov = FRAME_COLS (frame) * 2;
 
-  cmcostinit ();               /* set up cursor motion costs */
+      if (f && (!tty->TS_ins_line && !tty->TS_del_line))
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_rev_scroll, tty->TS_ins_multi_lines,
+                                          tty->TS_fwd_scroll, tty->TS_del_multi_lines,
+                                          f, f, 1);
+      else
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_ins_line, tty->TS_ins_multi_lines,
+                                          tty->TS_del_line, tty->TS_del_multi_lines,
+                                          0, 0, 1);
+
+      calculate_ins_del_char_costs (frame);
+
+      /* Don't use TS_repeat if its padding is worse than sending the chars */
+      if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
+        tty->RPov = string_cost (tty->TS_repeat);
+      else
+        tty->RPov = FRAME_COLS (frame) * 2;
+
+      cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
+    }
 }
 \f
 struct fkey_table {
@@ -1898,10 +1800,10 @@ produce_special_glyphs (it, what)
    from them.  Some display attributes may not be used together with
    color; the termcap capability `NC' specifies which ones.  */
 
-#define MAY_USE_WITH_COLORS_P(ATTR)            \
-     (TN_max_colors > 0                                \
-      ? (TN_no_color_video & (ATTR)) == 0      \
-      : 1)
+#define MAY_USE_WITH_COLORS_P(tty, ATTR)                \
+  (tty->TN_max_colors > 0                              \
+   ? (tty->TN_no_color_video & (ATTR)) == 0             \
+   : 1)
 
 /* Turn appearances of face FACE_ID on tty frame F on.  */
 
@@ -1913,12 +1815,13 @@ turn_on_face (f, face_id)
   struct face *face = FACE_FROM_ID (f, face_id);
   long fg = face->foreground;
   long bg = face->background;
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Do this first because TS_end_standout_mode may be the same
      as TS_exit_attribute_mode, which turns all appearances off. */
-  if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
+  if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
     {
-      if (TN_max_colors > 0)
+      if (tty->TN_max_colors > 0)
        {
          if (fg >= 0 && bg >= 0)
            {
@@ -1932,13 +1835,13 @@ turn_on_face (f, face_id)
            {
              if (fg == FACE_TTY_DEFAULT_FG_COLOR
                  || bg == FACE_TTY_DEFAULT_BG_COLOR)
-               toggle_highlight ();
+               toggle_highlight (tty);
            }
          else
            {
              if (fg == FACE_TTY_DEFAULT_BG_COLOR
                  || bg == FACE_TTY_DEFAULT_FG_COLOR)
-               toggle_highlight ();
+               toggle_highlight (tty);
            }
        }
       else
@@ -1949,53 +1852,53 @@ turn_on_face (f, face_id)
            {
              if (fg == FACE_TTY_DEFAULT_FG_COLOR
                  || bg == FACE_TTY_DEFAULT_BG_COLOR)
-               toggle_highlight ();
+               toggle_highlight (tty);
            }
          else
            {
              if (fg == FACE_TTY_DEFAULT_BG_COLOR
                  || bg == FACE_TTY_DEFAULT_FG_COLOR)
-               toggle_highlight ();
+               toggle_highlight (tty);
            }
        }
     }
 
   if (face->tty_bold_p)
     {
-      if (MAY_USE_WITH_COLORS_P (NC_BOLD))
-       OUTPUT1_IF (TS_enter_bold_mode);
+      if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
+       OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
     }
   else if (face->tty_dim_p)
-    if (MAY_USE_WITH_COLORS_P (NC_DIM))
-      OUTPUT1_IF (TS_enter_dim_mode);
+    if (MAY_USE_WITH_COLORS_P (tty, NC_DIM))
+      OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
 
   /* Alternate charset and blinking not yet used.  */
   if (face->tty_alt_charset_p
-      && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
-    OUTPUT1_IF (TS_enter_alt_charset_mode);
+      && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
+    OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
 
   if (face->tty_blinking_p
-      && MAY_USE_WITH_COLORS_P (NC_BLINK))
-    OUTPUT1_IF (TS_enter_blink_mode);
+      && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
+    OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
 
-  if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
-    OUTPUT1_IF (TS_enter_underline_mode);
+  if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
+    OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
 
-  if (TN_max_colors > 0)
+  if (tty->TN_max_colors > 0)
     {
       char *p;
 
-      if (fg >= 0 && TS_set_foreground)
+      if (fg >= 0 && tty->TS_set_foreground)
        {
-         p = tparam (TS_set_foreground, NULL, 0, (int) fg);
-         OUTPUT (p);
+         p = tparam (tty->TS_set_foreground, NULL, 0, (int) fg);
+         OUTPUT (tty, p);
          xfree (p);
        }
 
-      if (bg >= 0 && TS_set_background)
+      if (bg >= 0 && tty->TS_set_background)
        {
-         p = tparam (TS_set_background, NULL, 0, (int) bg);
-         OUTPUT (p);
+         p = tparam (tty->TS_set_background, NULL, 0, (int) bg);
+         OUTPUT (tty, p);
          xfree (p);
        }
     }
@@ -2010,10 +1913,11 @@ turn_off_face (f, face_id)
      int face_id;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   xassert (face != NULL);
 
-  if (TS_exit_attribute_mode)
+  if (tty->TS_exit_attribute_mode)
     {
       /* Capability "me" will turn off appearance modes double-bright,
         half-bright, reverse-video, standout, underline.  It may or
@@ -2025,32 +1929,32 @@ turn_off_face (f, face_id)
          || face->tty_blinking_p
          || face->tty_underline_p)
        {
-         OUTPUT1_IF (TS_exit_attribute_mode);
-         if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
-           standout_mode = 0;
+         OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
+         if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
+           tty->standout_mode = 0;
        }
 
       if (face->tty_alt_charset_p)
-       OUTPUT_IF (TS_exit_alt_charset_mode);
+       OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
     }
   else
     {
       /* If we don't have "me" we can only have those appearances
         that have exit sequences defined.  */
       if (face->tty_alt_charset_p)
-       OUTPUT_IF (TS_exit_alt_charset_mode);
+       OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
 
       if (face->tty_underline_p)
-       OUTPUT_IF (TS_exit_underline_mode);
+       OUTPUT_IF (tty, tty->TS_exit_underline_mode);
     }
 
   /* Switch back to default colors.  */
-  if (TN_max_colors > 0
+  if (tty->TN_max_colors > 0
       && ((face->foreground != FACE_TTY_DEFAULT_COLOR
           && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
          || (face->background != FACE_TTY_DEFAULT_COLOR
              && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
-    OUTPUT1_IF (TS_orig_pair);
+    OUTPUT1_IF (tty, tty->TS_orig_pair);
 }
 
 
@@ -2059,26 +1963,72 @@ turn_off_face (f, face_id)
    colors FG and BG.  */
 
 int
-tty_capable_p (f, caps, fg, bg)
-     struct frame *f;
+tty_capable_p (tty, caps, fg, bg)
+     struct tty_display_info *tty;
      unsigned caps;
      unsigned long fg, bg;
 {
-#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit)                             \
-  if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit)))     \
+#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit)                                \
+  if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit)))        \
     return 0;
 
-  TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE,  TS_standout_mode,        NC_REVERSE);
-  TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
-  TTY_CAPABLE_P_TRY (TTY_CAP_BOLD,     TS_enter_bold_mode,      NC_BOLD);
-  TTY_CAPABLE_P_TRY (TTY_CAP_DIM,      TS_enter_dim_mode,       NC_DIM);
-  TTY_CAPABLE_P_TRY (TTY_CAP_BLINK,    TS_enter_blink_mode,     NC_BLINK);
-  TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE,     tty->TS_standout_mode,          NC_REVERSE);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE,   tty->TS_enter_underline_mode,   NC_UNDERLINE);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD,        tty->TS_enter_bold_mode,        NC_BOLD);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM,                 tty->TS_enter_dim_mode,         NC_DIM);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK,       tty->TS_enter_blink_mode,       NC_BLINK);
+  TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET,         tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
 
   /* We can do it!  */
   return 1;
 }
 
+/* Return the tty display object specified by DISPLAY.  DISPLAY may be
+   a frame, a string, or nil for the display device of the current
+   frame. */
+
+static struct display *
+get_tty_display (Lisp_Object display)
+{
+  struct display *d;
+
+  if (NILP (display))
+    display = selected_frame;
+
+  if (! FRAMEP (display) && ! STRINGP (display))
+    return 0;
+
+  /* The initial frame does not support colors. */
+  if (FRAMEP (display) && FRAME_INITIAL_P (XFRAME (display)))
+    return 0;
+
+  if (FRAMEP (display))
+    {
+      if (! FRAME_TERMCAP_P (XFRAME (display)))
+#if 0   /* XXX We need a predicate as the first argument; find one. */
+        wrong_type_argument ("Not a termcap frame", display);
+#else /* Until we fix the wrong_type_argument call above, simply throw
+         a dumb error. */
+      error ("DISPLAY is not a termcap frame");
+#endif  
+  
+      d = FRAME_DISPLAY (XFRAME (display));
+    }
+  else if (STRINGP (display))
+    {
+      char *name = (char *) alloca (SBYTES (display) + 1);
+      strncpy (name, SDATA (display), SBYTES (display));
+      name[SBYTES (display)] = 0;
+
+      d = get_named_tty_display (name);
+
+      if (!d)
+        error ("There is no tty display on %s", name);
+    }
+
+  return d;
+}
+
 
 /* Return non-zero if the terminal is capable to display colors.  */
 
@@ -2088,7 +2038,11 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
      (display)
      Lisp_Object display;
 {
-  return TN_max_colors > 0 ? Qt : Qnil;
+  struct display *d = get_tty_display (display);
+  if (!d)
+    return Qnil;
+  else
+    return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
 }
 
 /* Return the number of supported colors.  */
@@ -2098,7 +2052,11 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
      (display)
      Lisp_Object display;
 {
-  return make_number (TN_max_colors);
+  struct display *d = get_tty_display (display);
+  if (!d)
+    return Qnil;
+  else
+    return make_number (d->display_info.tty->TN_max_colors);
 }
 
 #ifndef WINDOWSNT
@@ -2106,8 +2064,7 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
 /* Save or restore the default color-related capabilities of this
    terminal.  */
 static void
-tty_default_color_capabilities (save)
-     int save;
+tty_default_color_capabilities (struct tty_display_info *tty, int save)
 {
   static char
     *default_orig_pair, *default_set_foreground, *default_set_background;
@@ -2117,30 +2074,30 @@ tty_default_color_capabilities (save)
     {
       if (default_orig_pair)
        xfree (default_orig_pair);
-      default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
+      default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
 
       if (default_set_foreground)
        xfree (default_set_foreground);
-      default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
+      default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
                               : NULL;
 
       if (default_set_background)
        xfree (default_set_background);
-      default_set_background = TS_set_background ? xstrdup (TS_set_background)
+      default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
                               : NULL;
 
-      default_max_colors = TN_max_colors;
-      default_max_pairs = TN_max_pairs;
-      default_no_color_video = TN_no_color_video;
+      default_max_colors = tty->TN_max_colors;
+      default_max_pairs = tty->TN_max_pairs;
+      default_no_color_video = tty->TN_no_color_video;
     }
   else
     {
-      TS_orig_pair = default_orig_pair;
-      TS_set_foreground = default_set_foreground;
-      TS_set_background = default_set_background;
-      TN_max_colors = default_max_colors;
-      TN_max_pairs = default_max_pairs;
-      TN_no_color_video = default_no_color_video;
+      tty->TS_orig_pair = default_orig_pair;
+      tty->TS_set_foreground = default_set_foreground;
+      tty->TS_set_background = default_set_background;
+      tty->TN_max_colors = default_max_colors;
+      tty->TN_max_pairs = default_max_pairs;
+      tty->TN_no_color_video = default_no_color_video;
     }
 }
 
@@ -2149,8 +2106,7 @@ tty_default_color_capabilities (save)
    support; zero means set up for the default capabilities, the ones
    we saw at term_init time; -1 means turn off color support.  */
 void
-tty_setup_colors (mode)
-     int mode;
+tty_setup_colors (struct tty_display_info *tty, int mode)
 {
   /* Canonicalize all negative values of MODE.  */
   if (mode < -1)
@@ -2159,27 +2115,27 @@ tty_setup_colors (mode)
   switch (mode)
     {
       case -1:  /* no colors at all */
-       TN_max_colors = 0;
-       TN_max_pairs = 0;
-       TN_no_color_video = 0;
-       TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
+       tty->TN_max_colors = 0;
+       tty->TN_max_pairs = 0;
+       tty->TN_no_color_video = 0;
+       tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
        break;
       case 0:   /* default colors, if any */
       default:
-       tty_default_color_capabilities (0);
+       tty_default_color_capabilities (tty, 0);
        break;
       case 8:  /* 8 standard ANSI colors */
-       TS_orig_pair = "\033[0m";
+       tty->TS_orig_pair = "\033[0m";
 #ifdef TERMINFO
-       TS_set_foreground = "\033[3%p1%dm";
-       TS_set_background = "\033[4%p1%dm";
+       tty->TS_set_foreground = "\033[3%p1%dm";
+       tty->TS_set_background = "\033[4%p1%dm";
 #else
-       TS_set_foreground = "\033[3%dm";
-       TS_set_background = "\033[4%dm";
+       tty->TS_set_foreground = "\033[3%dm";
+       tty->TS_set_background = "\033[4%dm";
 #endif
-       TN_max_colors = 8;
-       TN_max_pairs = 64;
-       TN_no_color_video = 0;
+       tty->TN_max_colors = 8;
+       tty->TN_max_pairs = 64;
+       tty->TN_no_color_video = 0;
        break;
     }
 }
@@ -2230,7 +2186,7 @@ set_tty_color_mode (f, val)
 
   if (mode != old_mode)
     {
-      tty_setup_colors (mode);
+      tty_setup_colors (FRAME_TTY (f), mode);
       /*  This recomputes all the faces given the new color
          definitions.  */
       call0 (intern ("tty-set-up-initial-frame-faces"));
@@ -2240,14 +2196,160 @@ set_tty_color_mode (f, val)
 
 #endif /* !WINDOWSNT */
 
+\f
+
+/* Return the termcap display with the given name.  If NAME is null,
+   return the display corresponding to our controlling terminal.
+
+   Returns NULL if the named terminal device is not opened.  */
+struct display *
+get_named_tty_display (name)
+     char *name;
+{
+  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;
+}
+
+\f
+
+DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
+       doc: /* Return the name of the TTY device that FRAME is displayed on. */)
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+
+  if (NILP (frame))
+    {
+      f = XFRAME (selected_frame);
+    }
+  else
+    {
+      CHECK_LIVE_FRAME (frame);
+      f = XFRAME (frame);
+    }
+
+  if (f->output_method != output_termcap)
+    wrong_type_argument (Qframe_tty_name, frame);
+
+  if (FRAME_TTY (f)->name)
+    return build_string (FRAME_TTY (f)->name);
+  else
+    return Qnil;
+}
+
+DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
+       doc: /* Return the type of the TTY device that FRAME is displayed on. */)
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+
+  if (NILP (frame))
+    {
+      f = XFRAME (selected_frame);
+    }
+  else
+    {
+      CHECK_LIVE_FRAME (frame);
+      f = XFRAME (frame);
+    }
+
+  if (f->output_method != output_termcap)
+    wrong_type_argument (Qframe_tty_type, frame);
+
+  if (FRAME_TTY (f)->type)
+    return build_string (FRAME_TTY (f)->type);
+  else
+    return Qnil;
+}
+
 \f
 /***********************************************************************
                            Initialization
  ***********************************************************************/
 
+/* Create the bootstrap display device for the initial frame.
+   Returns a display of type output_initial. */
+
+struct display *
+init_initial_display (void)
+{
+  if (initialized || display_list || tty_list)
+    abort ();
+
+  initial_display = create_display ();
+  initial_display->type = output_initial;
+  
+  initial_display->delete_display_hook = &delete_initial_display;
+  /* All other hooks are NULL. */
+  
+  return initial_display;
+}
+
+/* Deletes the bootstrap display device.
+   Called through delete_display_hook. */
+
+void
+delete_initial_display (struct display *display)
+{
+  if (display != initial_display)
+    abort ();
+
+  delete_display (display);
+  initial_display = NULL;
+}
+
+/* Drop the controlling terminal if fd is the same device. */
 void
-term_init (terminal_type)
-     char *terminal_type;
+dissociate_if_controlling_tty (int fd)
+{
+#if defined (USG) && !defined (BSD_PGRPS)
+  int pgid;
+  EMACS_GET_TTY_PGRP (fd, &pgid);
+  if (pgid != -1)
+    {
+      setpgrp ();
+      no_controlling_tty = 1;
+    }
+#else
+#ifdef TIOCNOTTY                /* Try BSD ioctls. */
+  sigblock (sigmask (SIGTTOU));
+  if (ioctl (fd, TIOCNOTTY, 0) != -1)
+    {
+      no_controlling_tty = 1;
+    }
+  sigunblock (sigmask (SIGTTOU));
+#else
+  /* Unknown system. */
+  croak ();
+#endif  /* ! TIOCNOTTY */
+#endif  /* ! USG */
+}
+
+/* Create a termcap display on the tty device with the given name and
+   type.
+
+   If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
+   Otherwise NAME should be a path to the tty device file,
+   e.g. "/dev/pts/7".
+
+   TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
+
+   If MUST_SUCCEED is true, then all errors are fatal. */
+
+struct display *
+term_init (char *name, char *terminal_type, int must_succeed)
 {
   char *area;
   char **address = &area;
@@ -2255,69 +2357,208 @@ term_init (terminal_type)
   int buffer_size = 4096;
   register char *p;
   int status;
-  struct frame *sf = XFRAME (selected_frame);
+  struct tty_display_info *tty;
+  struct display *display;
+
+  static void maybe_fatal();
+
+  if (!terminal_type)
+    maybe_fatal (must_succeed, 0, 0,
+                 "Unknown terminal type",
+                 "Unknown terminal type");
+  
+  display = get_named_tty_display (name);
+  if (display)
+    {
+      /* XXX We would be able to support multiple emacsclients from
+         the same terminal if display devices were Lisp objects.
+         (Lisp code must know the difference between two separate
+         displays on the same terminal device.) -- lorentey */
+      if (! display->display_info.tty->input)
+        error ("%s already has a suspended frame on it, can't open it twice", name);
+      return display;
+    }
+
+  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->display = display;
+
+  tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+  Wcm_clear (tty);
+
+  display->rif = 0; /* ttys don't support window-based redisplay. */
+
+  display->cursor_to_hook = &tty_cursor_to;
+  display->raw_cursor_to_hook = &tty_raw_cursor_to;
+
+  display->clear_to_end_hook = &tty_clear_to_end;
+  display->clear_frame_hook = &tty_clear_frame;
+  display->clear_end_of_line_hook = &tty_clear_end_of_line;
+
+  display->ins_del_lines_hook = &tty_ins_del_lines;
+
+  display->insert_glyphs_hook = &tty_insert_glyphs;
+  display->write_glyphs_hook = &tty_write_glyphs;
+  display->delete_glyphs_hook = &tty_delete_glyphs;
+
+  display->ring_bell_hook = &tty_ring_bell;
+  
+  display->reset_terminal_modes_hook = &tty_reset_terminal_modes;
+  display->set_terminal_modes_hook = &tty_set_terminal_modes;
+  display->update_begin_hook = 0; /* Not needed. */
+  display->update_end_hook = &tty_update_end;
+  display->set_terminal_window_hook = &tty_set_terminal_window;
+
+  display->mouse_position_hook = 0; /* Not needed. */
+  display->frame_rehighlight_hook = 0; /* Not needed. */
+  display->frame_raise_lower_hook = 0; /* Not needed. */
+
+  display->set_vertical_scroll_bar_hook = 0; /* Not needed. */
+  display->condemn_scroll_bars_hook = 0; /* Not needed. */
+  display->redeem_scroll_bar_hook = 0; /* Not needed. */
+  display->judge_scroll_bars_hook = 0; /* Not needed. */
+
+  display->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
+  display->frame_up_to_date_hook = 0; /* Not needed. */
+  
+  display->delete_frame_hook = &delete_tty_output;
+  display->delete_display_hook = &delete_tty;
+  
+  if (name)
+    {
+      int fd;
+      FILE *file;
+
+#ifdef O_IGNORE_CTTY
+      /* Open the terminal device.  Don't recognize it as our
+         controlling terminal, and don't make it the controlling tty
+         if we don't have one at the moment.  */
+      fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
+#else
+      /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
+         defined on Hurd.  On other systems, we need to dissociate
+         ourselves from the controlling tty when we want to open a
+         frame on the same terminal.  */
+
+      fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
+
+#endif /* O_IGNORE_CTTY */
+
+      if (fd < 0)
+        {
+          delete_tty (display);
+          error ("Could not open file: %s", name);
+        }
+      if (! isatty (fd))
+        {
+          close (fd);
+          error ("Not a tty device: %s", name);
+        }
+
+      dissociate_if_controlling_tty (fd);
+      
+      file = fdopen (fd, "w+");
+      tty->name = xstrdup (name);
+      tty->input = file;
+      tty->output = file;
+    }
+  else
+    {
+      if (no_controlling_tty)
+        {
+          /* Opening a frame on stdout is unsafe if we have
+             disconnected our controlling terminal. */
+          error ("There is no controlling terminal any more");
+        }
+      tty->name = 0;
+      tty->input = stdin;
+      tty->output = stdout;
+    }
+
+  tty->type = xstrdup (terminal_type);
+
+  add_keyboard_wait_descriptor (fileno (tty->input));
 
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
-  Wcm_clear ();
+  Wcm_clear (tty);
 
   area = (char *) xmalloc (2044);
 
-  FrameRows = FRAME_LINES (sf);
-  FrameCols = FRAME_COLS (sf);
-  specified_window = FRAME_LINES (sf);
+  FrameRows (tty) = FRAME_LINES (f); /* XXX */
+  FrameCols (tty) = FRAME_COLS (f);  /* XXX */
+  tty->specified_window = FRAME_LINES (f); /* XXX */
 
-  delete_in_insert_mode = 1;
+  tty->display->delete_in_insert_mode = 1;
 
-  UseTabs = 0;
-  scroll_region_ok = 0;
+  UseTabs (tty) = 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.  */
-
-  line_ins_del_ok = 0;
-  char_ins_del_ok = 1;
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 1;
 
   baud_rate = 19200;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = 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;
+  return display;
 #else  /* not WINDOWSNT */
 
-  Wcm_clear ();
+  Wcm_clear (tty);
 
   buffer = (char *) xmalloc (buffer_size);
+  
+  /* On some systems, tgetent tries to access the controlling
+     terminal. */
+  sigblock (sigmask (SIGTTOU));
   status = tgetent (buffer, terminal_type);
+  sigunblock (sigmask (SIGTTOU));
+  
   if (status < 0)
     {
 #ifdef TERMINFO
-      fatal ("Cannot open terminfo database file");
+      maybe_fatal (must_succeed, buffer, display,
+                   "Cannot open terminfo database file",
+                   "Cannot open terminfo database file");
 #else
-      fatal ("Cannot open termcap database file");
+      maybe_fatal (must_succeed, buffer, display,
+                   "Cannot open termcap database file",
+                   "Cannot open termcap database file");
 #endif
     }
   if (status == 0)
     {
 #ifdef TERMINFO
-      fatal ("Terminal type %s is not defined.\n\
+      maybe_fatal (must_succeed, buffer, display,
+                   "Terminal type %s is not defined",
+                   "Terminal type %s is not defined.\n\
 If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
-            terminal_type);
+                   terminal_type);
 #else
-      fatal ("Terminal type %s is not defined.\n\
+      maybe_fatal (must_succeed, buffer, display,
+                   "Terminal type %s is not defined",
+                   "Terminal type %s is not defined.\n\
 If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
-            terminal_type);
+                   terminal_type);
 #endif
     }
 
@@ -2328,219 +2569,221 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
 #endif
   area = (char *) xmalloc (buffer_size);
 
-  TS_ins_line = tgetstr ("al", address);
-  TS_ins_multi_lines = tgetstr ("AL", address);
-  TS_bell = tgetstr ("bl", address);
-  BackTab = tgetstr ("bt", address);
-  TS_clr_to_bottom = tgetstr ("cd", address);
-  TS_clr_line = tgetstr ("ce", address);
-  TS_clr_frame = tgetstr ("cl", address);
-  ColPosition = NULL; /* tgetstr ("ch", address); */
-  AbsPosition = tgetstr ("cm", address);
-  CR = tgetstr ("cr", address);
-  TS_set_scroll_region = tgetstr ("cs", address);
-  TS_set_scroll_region_1 = tgetstr ("cS", address);
-  RowPosition = tgetstr ("cv", address);
-  TS_del_char = tgetstr ("dc", address);
-  TS_del_multi_chars = tgetstr ("DC", address);
-  TS_del_line = tgetstr ("dl", address);
-  TS_del_multi_lines = tgetstr ("DL", address);
-  TS_delete_mode = tgetstr ("dm", address);
-  TS_end_delete_mode = tgetstr ("ed", address);
-  TS_end_insert_mode = tgetstr ("ei", address);
-  Home = tgetstr ("ho", address);
-  TS_ins_char = tgetstr ("ic", address);
-  TS_ins_multi_chars = tgetstr ("IC", address);
-  TS_insert_mode = tgetstr ("im", address);
-  TS_pad_inserted_char = tgetstr ("ip", address);
-  TS_end_keypad_mode = tgetstr ("ke", address);
-  TS_keypad_mode = tgetstr ("ks", address);
-  LastLine = tgetstr ("ll", address);
-  Right = tgetstr ("nd", address);
-  Down = tgetstr ("do", address);
-  if (!Down)
-    Down = tgetstr ("nl", address); /* Obsolete name for "do" */
+  tty->TS_ins_line = tgetstr ("al", address);
+  tty->TS_ins_multi_lines = tgetstr ("AL", address);
+  tty->TS_bell = tgetstr ("bl", address);
+  BackTab (tty) = tgetstr ("bt", address);
+  tty->TS_clr_to_bottom = tgetstr ("cd", address);
+  tty->TS_clr_line = tgetstr ("ce", address);
+  tty->TS_clr_frame = tgetstr ("cl", address);
+  ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
+  AbsPosition (tty) = tgetstr ("cm", address);
+  CR (tty) = tgetstr ("cr", address);
+  tty->TS_set_scroll_region = tgetstr ("cs", address);
+  tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
+  RowPosition (tty) = tgetstr ("cv", address);
+  tty->TS_del_char = tgetstr ("dc", address);
+  tty->TS_del_multi_chars = tgetstr ("DC", address);
+  tty->TS_del_line = tgetstr ("dl", address);
+  tty->TS_del_multi_lines = tgetstr ("DL", address);
+  tty->TS_delete_mode = tgetstr ("dm", address);
+  tty->TS_end_delete_mode = tgetstr ("ed", address);
+  tty->TS_end_insert_mode = tgetstr ("ei", address);
+  Home (tty) = tgetstr ("ho", address);
+  tty->TS_ins_char = tgetstr ("ic", address);
+  tty->TS_ins_multi_chars = tgetstr ("IC", address);
+  tty->TS_insert_mode = tgetstr ("im", address);
+  tty->TS_pad_inserted_char = tgetstr ("ip", address);
+  tty->TS_end_keypad_mode = tgetstr ("ke", address);
+  tty->TS_keypad_mode = tgetstr ("ks", address);
+  LastLine (tty) = tgetstr ("ll", address);
+  Right (tty) = tgetstr ("nd", address);
+  Down (tty) = tgetstr ("do", address);
+  if (!Down (tty))
+    Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
 #ifdef VMS
   /* VMS puts a carriage return before each linefeed,
      so it is not safe to use linefeeds.  */
-  if (Down && Down[0] == '\n' && Down[1] == '\0')
-    Down = 0;
+  if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
+    Down (tty) = 0;
 #endif /* VMS */
   if (tgetflag ("bs"))
-    Left = "\b";                 /* can't possibly be longer! */
+    Left (tty) = "\b";           /* can't possibly be longer! */
   else                           /* (Actually, "bs" is obsolete...) */
-    Left = tgetstr ("le", address);
-  if (!Left)
-    Left = tgetstr ("bc", address); /* Obsolete name for "le" */
-  TS_pad_char = tgetstr ("pc", address);
-  TS_repeat = tgetstr ("rp", address);
-  TS_end_standout_mode = tgetstr ("se", address);
-  TS_fwd_scroll = tgetstr ("sf", address);
-  TS_standout_mode = tgetstr ("so", address);
-  TS_rev_scroll = tgetstr ("sr", address);
-  Wcm.cm_tab = tgetstr ("ta", address);
-  TS_end_termcap_modes = tgetstr ("te", address);
-  TS_termcap_modes = tgetstr ("ti", address);
-  Up = tgetstr ("up", address);
-  TS_visible_bell = tgetstr ("vb", address);
-  TS_cursor_normal = tgetstr ("ve", address);
-  TS_cursor_visible = tgetstr ("vs", address);
-  TS_cursor_invisible = tgetstr ("vi", address);
-  TS_set_window = tgetstr ("wi", address);
-
-  TS_enter_underline_mode = tgetstr ("us", address);
-  TS_exit_underline_mode = tgetstr ("ue", address);
-  TS_enter_bold_mode = tgetstr ("md", address);
-  TS_enter_dim_mode = tgetstr ("mh", address);
-  TS_enter_blink_mode = tgetstr ("mb", address);
-  TS_enter_reverse_mode = tgetstr ("mr", address);
-  TS_enter_alt_charset_mode = tgetstr ("as", address);
-  TS_exit_alt_charset_mode = tgetstr ("ae", address);
-  TS_exit_attribute_mode = tgetstr ("me", address);
-
-  MultiUp = tgetstr ("UP", address);
-  MultiDown = tgetstr ("DO", address);
-  MultiLeft = tgetstr ("LE", address);
-  MultiRight = tgetstr ("RI", address);
+    Left (tty) = tgetstr ("le", address);
+  if (!Left (tty))
+    Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
+  tty->TS_pad_char = tgetstr ("pc", address);
+  tty->TS_repeat = tgetstr ("rp", address);
+  tty->TS_end_standout_mode = tgetstr ("se", address);
+  tty->TS_fwd_scroll = tgetstr ("sf", address);
+  tty->TS_standout_mode = tgetstr ("so", address);
+  tty->TS_rev_scroll = tgetstr ("sr", address);
+  tty->Wcm->cm_tab = tgetstr ("ta", address);
+  tty->TS_end_termcap_modes = tgetstr ("te", address);
+  tty->TS_termcap_modes = tgetstr ("ti", address);
+  Up (tty) = tgetstr ("up", address);
+  tty->TS_visible_bell = tgetstr ("vb", address);
+  tty->TS_cursor_normal = tgetstr ("ve", address);
+  tty->TS_cursor_visible = tgetstr ("vs", address);
+  tty->TS_cursor_invisible = tgetstr ("vi", address);
+  tty->TS_set_window = tgetstr ("wi", address);
+
+  tty->TS_enter_underline_mode = tgetstr ("us", address);
+  tty->TS_exit_underline_mode = tgetstr ("ue", address);
+  tty->TS_enter_bold_mode = tgetstr ("md", address);
+  tty->TS_enter_dim_mode = tgetstr ("mh", address);
+  tty->TS_enter_blink_mode = tgetstr ("mb", address);
+  tty->TS_enter_reverse_mode = tgetstr ("mr", address);
+  tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
+  tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
+  tty->TS_exit_attribute_mode = tgetstr ("me", address);
+
+  MultiUp (tty) = tgetstr ("UP", address);
+  MultiDown (tty) = tgetstr ("DO", address);
+  MultiLeft (tty) = tgetstr ("LE", address);
+  MultiRight (tty) = tgetstr ("RI", address);
 
   /* SVr4/ANSI color suppert.  If "op" isn't available, don't support
      color because we can't switch back to the default foreground and
      background.  */
-  TS_orig_pair = tgetstr ("op", address);
-  if (TS_orig_pair)
+  tty->TS_orig_pair = tgetstr ("op", address);
+  if (tty->TS_orig_pair)
     {
-      TS_set_foreground = tgetstr ("AF", address);
-      TS_set_background = tgetstr ("AB", address);
-      if (!TS_set_foreground)
+      tty->TS_set_foreground = tgetstr ("AF", address);
+      tty->TS_set_background = tgetstr ("AB", address);
+      if (!tty->TS_set_foreground)
        {
          /* SVr4.  */
-         TS_set_foreground = tgetstr ("Sf", address);
-         TS_set_background = tgetstr ("Sb", address);
+         tty->TS_set_foreground = tgetstr ("Sf", address);
+         tty->TS_set_background = tgetstr ("Sb", address);
        }
 
-      TN_max_colors = tgetnum ("Co");
-      TN_max_pairs = tgetnum ("pa");
+      tty->TN_max_colors = tgetnum ("Co");
+      tty->TN_max_pairs = tgetnum ("pa");
 
-      TN_no_color_video = tgetnum ("NC");
-      if (TN_no_color_video == -1)
-       TN_no_color_video = 0;
+      tty->TN_no_color_video = tgetnum ("NC");
+      if (tty->TN_no_color_video == -1)
+        tty->TN_no_color_video = 0;
     }
 
-  tty_default_color_capabilities (1);
+  tty_default_color_capabilities (tty, 1);
 
-  MagicWrap = tgetflag ("xn");
+  MagicWrap (tty) = tgetflag ("xn");
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
-  AutoWrap = MagicWrap || tgetflag ("am");
-  memory_below_frame = tgetflag ("db");
-  TF_hazeltine = tgetflag ("hz");
-  must_write_spaces = tgetflag ("in");
-  meta_key = tgetflag ("km") || tgetflag ("MT");
-  TF_insmode_motion = tgetflag ("mi");
-  TF_standout_motion = tgetflag ("ms");
-  TF_underscore = tgetflag ("ul");
-  TF_teleray = tgetflag ("xt");
+  AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
+  display->memory_below_frame = tgetflag ("db");
+  tty->TF_hazeltine = tgetflag ("hz");
+  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");
+  tty->TF_underscore = tgetflag ("ul");
+  tty->TF_teleray = tgetflag ("xt");
 
   term_get_fkeys (address);
 
   /* Get frame size from system, or else from termcap.  */
   {
     int height, width;
-    get_frame_size (&width, &height);
-    FRAME_COLS (sf) = width;
-    FRAME_LINES (sf) = height;
+    get_tty_size (fileno (tty->input), &width, &height);
+    FrameCols (tty) = width;
+    FrameRows (tty) = height;
   }
 
-  if (FRAME_COLS (sf) <= 0)
-    SET_FRAME_COLS (sf, tgetnum ("co"));
-  else
-    /* Keep width and external_width consistent */
-    SET_FRAME_COLS (sf, FRAME_COLS (sf));
-  if (FRAME_LINES (sf) <= 0)
-    FRAME_LINES (sf) = tgetnum ("li");
+  if (FrameCols (tty) <= 0)
+    FrameCols (tty) = tgetnum ("co");
+  if (FrameRows (tty) <= 0)
+    FrameRows (tty) = tgetnum ("li");
+
+  if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
+    maybe_fatal (must_succeed, NULL, display,
+                 "Screen size %dx%d is too small"
+                 "Screen size %dx%d is too small",
+                 FrameCols (tty), FrameRows (tty));
 
-  if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
-    fatal ("Screen size %dx%d is too small",
-          FRAME_LINES (sf), FRAME_COLS (sf));
+#if 0  /* This is not used anywhere. */
+  tty->display->min_padding_speed = tgetnum ("pb");
+#endif
 
-  min_padding_speed = tgetnum ("pb");
-  TabWidth = tgetnum ("tw");
+  TabWidth (tty) = tgetnum ("tw");
 
 #ifdef VMS
   /* These capabilities commonly use ^J.
      I don't know why, but sending them on VMS does not work;
      it causes following spaces to be lost, sometimes.
      For now, the simplest fix is to avoid using these capabilities ever.  */
-  if (Down && Down[0] == '\n')
-    Down = 0;
+  if (Down (tty) && Down (tty)[0] == '\n')
+    Down (tty) = 0;
 #endif /* VMS */
 
-  if (!TS_bell)
-    TS_bell = "\07";
+  if (!tty->TS_bell)
+    tty->TS_bell = "\07";
 
-  if (!TS_fwd_scroll)
-    TS_fwd_scroll = Down;
+  if (!tty->TS_fwd_scroll)
+    tty->TS_fwd_scroll = Down (tty);
 
-  PC = TS_pad_char ? *TS_pad_char : 0;
+  PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
 
-  if (TabWidth < 0)
-    TabWidth = 8;
+  if (TabWidth (tty) < 0)
+    TabWidth (tty) = 8;
 
 /* Turned off since /etc/termcap seems to have :ta= for most terminals
    and newer termcap doc does not seem to say there is a default.
-  if (!Wcm.cm_tab)
-    Wcm.cm_tab = "\t";
+  if (!tty->Wcm->cm_tab)
+    tty->Wcm->cm_tab = "\t";
 */
 
   /* We don't support standout modes that use `magic cookies', so
      turn off any that do.  */
-  if (TS_standout_mode && tgetnum ("sg") >= 0)
+  if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
     {
-      TS_standout_mode = 0;
-      TS_end_standout_mode = 0;
+      tty->TS_standout_mode = 0;
+      tty->TS_end_standout_mode = 0;
     }
-  if (TS_enter_underline_mode && tgetnum ("ug") >= 0)
+  if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
     {
-      TS_enter_underline_mode = 0;
-      TS_exit_underline_mode = 0;
+      tty->TS_enter_underline_mode = 0;
+      tty->TS_exit_underline_mode = 0;
     }
 
   /* If there's no standout mode, try to use underlining instead.  */
-  if (TS_standout_mode == 0)
+  if (tty->TS_standout_mode == 0)
     {
-      TS_standout_mode = TS_enter_underline_mode;
-      TS_end_standout_mode = TS_exit_underline_mode;
+      tty->TS_standout_mode = tty->TS_enter_underline_mode;
+      tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
     }
 
   /* If no `se' string, try using a `me' string instead.
      If that fails, we can't use standout mode at all.  */
-  if (TS_end_standout_mode == 0)
+  if (tty->TS_end_standout_mode == 0)
     {
       char *s = tgetstr ("me", address);
       if (s != 0)
-       TS_end_standout_mode = s;
+        tty->TS_end_standout_mode = s;
       else
-       TS_standout_mode = 0;
+        tty->TS_standout_mode = 0;
     }
 
-  if (TF_teleray)
+  if (tty->TF_teleray)
     {
-      Wcm.cm_tab = 0;
+      tty->Wcm->cm_tab = 0;
       /* We can't support standout mode, because it uses magic cookies.  */
-      TS_standout_mode = 0;
+      tty->TS_standout_mode = 0;
       /* But that means we cannot rely on ^M to go to column zero! */
-      CR = 0;
+      CR (tty) = 0;
       /* LF can't be trusted either -- can alter hpos */
       /* if move at column 0 thru a line with TS_standout_mode */
-      Down = 0;
+      Down (tty) = 0;
     }
 
   /* Special handling for certain terminal types known to need it */
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      memory_below_frame = 1;
-      Wcm.cm_losewrap = 1;
+      display->memory_below_frame = 1;
+      tty->Wcm->cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
       || !strcmp (terminal_type, "perq"))
@@ -2557,102 +2800,152 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
         It would be simpler if the :wi string could go in the termcap
         entry, but it can't because it is not fully valid.
         If it were in the termcap entry, it would confuse other programs.  */
-      if (!TS_set_window)
+      if (!tty->TS_set_window)
        {
-         p = TS_termcap_modes;
+         p = tty->TS_termcap_modes;
          while (*p && strcmp (p, "\033v  "))
            p++;
          if (*p)
-           TS_set_window = "\033v%C %C %C %C ";
+           tty->TS_set_window = "\033v%C %C %C %C ";
        }
       /* Termcap entry often fails to have :in: flag */
-      must_write_spaces = 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, TS_termcap_modes);
+      strcpy (area, tty->TS_termcap_modes);
       strcat (area, "\033\007!");
-      TS_termcap_modes = area;
+      tty->TS_termcap_modes = area;
       area += strlen (area) + 1;
-      p = AbsPosition;
+      p = AbsPosition (tty);
       /* Change all %+ parameters to %C, to handle
-        values above 96 correctly for the C100.  */
+         values above 96 correctly for the C100.  */
       while (*p)
-       {
-         if (p[0] == '%' && p[1] == '+')
-           p[1] = 'C';
-         p++;
-       }
+        {
+          if (p[0] == '%' && p[1] == '+')
+            p[1] = 'C';
+          p++;
+        }
     }
 
-  FrameRows = FRAME_LINES (sf);
-  FrameCols = FRAME_COLS (sf);
-  specified_window = FRAME_LINES (sf);
+  tty->specified_window = FrameRows (tty);
 
-  if (Wcm_init () == -1)       /* can't do cursor motion */
+  if (Wcm_init (tty) == -1)    /* can't do cursor motion */
+    {
+      maybe_fatal (must_succeed, NULL, display,
+                   "Terminal type \"%s\" is not powerful enough to run Emacs",
 #ifdef VMS
-    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have, use either the\n\
 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
-           terminal_type);
 #else /* not VMS */
 # ifdef TERMINFO
-    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
-          terminal_type);
 # else /* TERMCAP */
-    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
-          terminal_type);
 # endif /* TERMINFO */
 #endif /*VMS */
-  if (FRAME_LINES (sf) <= 0
-      || FRAME_COLS (sf) <= 0)
-    fatal ("The frame size has not been specified");
+                   terminal_type);
+    }
 
-  delete_in_insert_mode
-    = TS_delete_mode && TS_insert_mode
-      && !strcmp (TS_delete_mode, TS_insert_mode);
+  if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
+    maybe_fatal (must_succeed, NULL, display,
+                 "Could not determine the frame size",
+                 "Could not determine the frame size");
 
-  se_is_so = (TS_standout_mode
-             && TS_end_standout_mode
-             && !strcmp (TS_standout_mode, TS_end_standout_mode));
+  tty->delete_in_insert_mode
+    = tty->TS_delete_mode && tty->TS_insert_mode
+    && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
 
-  UseTabs = tabs_safe_p () && TabWidth == 8;
+  tty->se_is_so = (tty->TS_standout_mode
+              && tty->TS_end_standout_mode
+              && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
 
-  scroll_region_ok
-    = (Wcm.cm_abs
-       && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
+  UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
 
-  line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
-                     && (TS_del_line || TS_del_multi_lines))
-                    || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
+  display->scroll_region_ok
+    = (tty->Wcm->cm_abs
+       && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
-  char_ins_del_ok = ((TS_ins_char || TS_insert_mode
-                     || TS_pad_inserted_char || TS_ins_multi_chars)
-                    && (TS_del_char || TS_del_multi_chars));
+  display->line_ins_del_ok
+    = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
+        && (tty->TS_del_line || tty->TS_del_multi_lines))
+       || (display->scroll_region_ok
+           && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
-  fast_clear_end_of_line = TS_clr_line != 0;
+  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));
 
-  init_baud_rate ();
-  if (read_socket_hook)                /* Baudrate is somewhat */
-                               /* meaningless in this case */
-    baud_rate = 9600;
+  display->fast_clear_end_of_line = tty->TS_clr_line != 0;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
-#endif /* WINDOWSNT */
+  init_baud_rate (fileno (tty->input));
+
+#ifdef AIXHFT
+  /* The HFT system on AIX doesn't optimize for scrolling, so it's
+     really ugly at times.  */
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 0;
+#endif
 
-  xfree (buffer);
+#ifdef MULTI_KBOARD
+  tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (tty->kboard);
+  tty->kboard->next_kboard = all_kboards;
+  all_kboards = tty->kboard;
+  /* Don't let the initial kboard remain current longer than necessary.
+     That would cause problems if a file loaded on startup tries to
+     prompt in the mini-buffer.  */
+  if (current_kboard == initial_kboard)
+    current_kboard = tty->kboard;
+  tty->kboard->reference_count++;
+#endif
+
+  /* Don't do this.  I think termcap may still need the buffer. */
+  /* xfree (buffer); */
+
+  /* Init system terminal modes (RAW or CBREAK, etc.).  */
+  init_sys_modes (tty);
+
+  return display;
+#endif /* not WINDOWSNT */
+}
+
+/* Auxiliary error-handling function for term_init.
+   Free BUFFER and delete DISPLAY, then call error or fatal
+   with str1 or str2, respectively, according to MUST_SUCCEED.  */
+
+static void
+maybe_fatal (must_succeed, buffer, display, str1, str2, arg1, arg2)
+     int must_succeed;
+     char *buffer;
+     struct display *display;
+     char *str1, *str2, *arg1, *arg2;
+{
+  if (buffer)
+    xfree (buffer);
+
+  if (display)
+    delete_tty (display);
+  
+  if (must_succeed)
+    fatal (str2, arg1, arg2);
+  else
+    error (str1, arg1, arg2);
+
+  abort ();
 }
 
 /* VARARGS 1 */
@@ -2667,6 +2960,376 @@ fatal (str, arg1, arg2)
   exit (1);
 }
 
+\f
+
+DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
+       doc: /* Delete all frames on the terminal named TTY, and close the device.
+If omitted, TTY defaults to the controlling terminal.
+
+This function runs `delete-tty-after-functions' after closing the
+tty.  The functions are run with one arg, the frame to be deleted.  */)
+  (tty)
+     Lisp_Object tty;
+{
+  struct display *d;
+  char *name = 0;
+
+  CHECK_STRING (tty);
+
+  if (SBYTES (tty) > 0)
+    {
+      name = (char *) alloca (SBYTES (tty) + 1);
+      strncpy (name, SDATA (tty), SBYTES (tty));
+      name[SBYTES (tty)] = 0;
+    }
+
+  d = get_named_tty_display (name);
+
+  if (! d)
+    error ("No such terminal device: %s", name);
+
+  delete_tty (d);
+
+  return Qnil;
+}
+
+static int deleting_tty = 0;
+
+
+/* Delete the given terminal device, closing all frames on it. */
+
+void
+delete_tty (struct display *display)
+{
+  struct tty_display_info *tty;
+  Lisp_Object tail, frame;
+  char *tty_name;
+  int last_display;
+  
+  if (deleting_tty)
+    /* We get a recursive call when we delete the last frame on this
+       display. */
+    return;
+
+  if (display->type != output_termcap)
+    abort ();
+
+  tty = display->display_info.tty;
+  
+  last_display = 1;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty))
+        {
+          last_display = 0;
+          break;
+        }
+    }
+  if (last_display)
+      error ("Attempt to delete the sole display with live frames");
+  
+  if (tty == tty_list)
+    tty_list = tty->next;
+  else
+    {
+      struct tty_display_info *p;
+      for (p = tty_list; p && p->next != tty; p = p->next)
+        ;
+
+      if (! p)
+        /* This should not happen. */
+        abort ();
+
+      p->next = tty->next;
+      tty->next = 0;
+    }
+
+  deleting_tty = 1;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
+        {
+          Fdelete_frame (frame, Qt);
+        }
+    }
+
+  /* reset_sys_modes needs a valid display, so this call needs to be
+     before delete_display. */
+  reset_sys_modes (tty);
+
+  delete_display (display);
+
+  tty_name = tty->name;
+  if (tty->type)
+    xfree (tty->type);
+
+  if (tty->input)
+    {
+      delete_keyboard_wait_descriptor (fileno (tty->input));
+      if (tty->input != stdin)
+        fclose (tty->input);
+    }
+  if (tty->output && tty->output != stdout && tty->output != tty->input)
+    fclose (tty->output);
+  if (tty->termscript)
+    fclose (tty->termscript);
+
+  if (tty->old_tty)
+    xfree (tty->old_tty);
+
+  if (tty->Wcm)
+    xfree (tty->Wcm);
+
+#ifdef MULTI_KBOARD
+  if (tty->kboard && --tty->kboard->reference_count > 0)
+    abort ();
+  if (tty->kboard)
+    delete_kboard (tty->kboard);
+#endif
+  
+  bzero (tty, sizeof (struct tty_display_info));
+  xfree (tty);
+  deleting_tty = 0;
+
+  /* Run `delete-tty-after-functions'.  */
+  if (!NILP (Vrun_hooks))
+    {
+      Lisp_Object args[2];
+      args[0] = intern ("delete-tty-after-functions");
+      if (tty_name)
+        {
+          args[1] = build_string (tty_name);
+          xfree (tty_name);
+        }
+      else
+        args[1] = Qnil;
+      Frun_hook_with_args (2, args);
+    }
+}
+
+\f
+
+/* Initialize the tty-dependent part of frame F.  The frame must
+   already have its display initialized. */
+
+void
+create_tty_output (struct frame *f)
+{
+  struct tty_output *t;
+
+  if (! FRAME_TERMCAP_P (f))
+    abort ();
+
+  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);
+}
+
+
+\f
+
+/* Mark the pointers in the tty_display_info objects.
+   Called by the Fgarbage_collector.  */
+
+void
+mark_ttys ()
+{
+  struct tty_display_info *tty;
+
+  for (tty = tty_list; tty; tty = tty->next)
+    {
+      if (tty->top_frame)
+        mark_object (tty->top_frame);
+    }
+}
+
+\f
+
+/* 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;
+  Lisp_Object tail, frame;
+  
+  /* Check for and close live frames that are still on this
+     display. */
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_LIVE_P (f) && f->display == dev)
+        {
+          Fdelete_frame (frame, Qt);
+        }
+    }
+
+  for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
+    if (! *dp)
+      abort ();
+  *dp = dev->next_display;
+
+  bzero (dev, sizeof (struct display));
+  xfree (dev);
+}
+
+\f
+
+DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
+       doc: /* Suspend the terminal device TTY.
+The terminal is restored to its default state, and Emacs closes all
+access to the terminal device.  Frames that use the device are not
+deleted, but input is not read from them and if they change, their
+display is not updated.
+
+TTY may a string (a device name), a frame, or nil for the display
+device of the currently selected frame.
+
+This function runs `suspend-tty-functions' after suspending the
+device.  The functions are run with one arg, the name of the terminal
+device.
+
+`suspend-tty' does nothing if it is called on an already suspended
+device.
+
+A suspended terminal device may be resumed by calling `resume-tty' on
+it. */)
+  (tty)
+     Lisp_Object tty;
+{
+  struct display *d = get_tty_display (tty);
+  FILE *f;
+  
+  if (!d)
+    error ("Unknown tty device");
+
+  f = d->display_info.tty->input;
+  
+  if (f)
+    {
+      reset_sys_modes (d->display_info.tty);
+
+      delete_keyboard_wait_descriptor (fileno (f));
+      
+      fclose (f);
+      if (f != d->display_info.tty->output)
+        fclose (d->display_info.tty->output);
+      
+      d->display_info.tty->input = 0;
+      d->display_info.tty->output = 0;
+
+      if (FRAMEP (d->display_info.tty->top_frame))
+        FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 0);
+      
+      /* Run `suspend-tty-functions'.  */
+      if (!NILP (Vrun_hooks))
+        {
+          Lisp_Object args[2];
+          args[0] = intern ("suspend-tty-functions");
+          if (d->display_info.tty->name)
+            {
+              args[1] = build_string (d->display_info.tty->name);
+            }
+          else
+            args[1] = Qnil;
+          Frun_hook_with_args (2, args);
+        }
+    }
+
+  return Qnil;
+}
+
+
+DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
+       doc: /* Resume the previously suspended terminal device TTY.
+The terminal is opened and reinitialized.  Frames that used the
+suspended device are revived.
+
+This function runs `resume-tty-functions' after resuming the device.
+The functions are run with one arg, the name of the terminal device.
+
+`resume-tty' does nothing if it is called on a device that is not
+suspended.
+
+TTY may a string (a device name), a frame, or nil for the display
+device of the currently selected frame. */)
+  (tty)
+     Lisp_Object tty;
+{
+  struct display *d = get_tty_display (tty);
+  int fd;
+
+  if (!d)
+    error ("Unknown tty device");
+
+  if (!d->display_info.tty->input)
+    {
+      fd = emacs_open (d->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
+
+      /* XXX What if open fails? */
+
+      dissociate_if_controlling_tty (fd);
+      
+      d->display_info.tty->output = fdopen (fd, "w+");
+      d->display_info.tty->input = d->display_info.tty->output;
+    
+      add_keyboard_wait_descriptor (fd);
+
+      if (FRAMEP (d->display_info.tty->top_frame))
+        FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 1);
+
+      init_sys_modes (d->display_info.tty);
+
+      /* Run `suspend-tty-functions'.  */
+      if (!NILP (Vrun_hooks))
+        {
+          Lisp_Object args[2];
+          args[0] = intern ("resume-tty-functions");
+          if (d->display_info.tty->name)
+            {
+              args[1] = build_string (d->display_info.tty->name);
+            }
+          else
+            args[1] = Qnil;
+          Frun_hook_with_args (2, args);
+        }
+    }
+
+  return Qnil;
+}
+
+\f
 void
 syms_of_term ()
 {
@@ -2684,9 +3347,45 @@ This variable can be used by terminal emulator packages.  */);
 The function should accept no arguments.  */);
   Vring_bell_function = Qnil;
 
+  DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions,
+    doc: /* Functions to be run after deleting a tty.
+The functions are run with one argument, the name of the tty to be deleted.
+See `delete-tty'.  */);
+  Vdelete_tty_after_functions = Qnil;
+
+
+  DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
+    doc: /* Functions to be run after suspending a tty.
+The functions are run with one argument, the name of the tty to be suspended.
+See `suspend-tty'.  */);
+  Vsuspend_tty_functions = Qnil;
+
+
+  DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
+    doc: /* Functions to be run after resuming a tty.
+The functions are run with one argument, the name of the tty that was revived.
+See `resume-tty'.  */);
+  Vresume_tty_functions = Qnil;
+
+  Qframe_tty_name = intern ("frame-tty-name");
+  staticpro (&Qframe_tty_name);
+
+  Qframe_tty_type = intern ("frame-tty-type");
+  staticpro (&Qframe_tty_type);
+
   defsubr (&Stty_display_color_p);
   defsubr (&Stty_display_color_cells);
+  defsubr (&Sframe_tty_name);
+  defsubr (&Sframe_tty_type);
+  defsubr (&Sdelete_tty);
+  defsubr (&Ssuspend_tty);
+  defsubr (&Sresume_tty);
+
+  Fprovide (intern ("multi-tty"), Qnil);
+
 }
 
+
+
 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
    (do not change this comment) */
index b1d941adc27be46539fc628086374ef05b99a267..3053061c1b7048501e8caf27804005c0bde27723 100644 (file)
@@ -1,5 +1,5 @@
 /* Flags and parameters describing terminal's characteristics.
-   Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,32 +18,189 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
+/* Each termcap frame points to its own struct tty_output object in
+   the output_data.tty field.  The tty_output structure contains the
+   information that is specific to termcap frames. */
 
-/* extern EMACS_INT baud_rate; */              /* Output speed in baud */
-extern 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.  */
-extern int min_padding_speed;  /* Speed below which no padding necessary */
-extern int fast_clear_end_of_line; /* Nonzero means terminal has
-                                     command for this */
-
-extern int line_ins_del_ok;    /* Terminal can insert and delete lines */
-extern int char_ins_del_ok;    /* Terminal can insert and delete chars */
-extern int scroll_region_ok;   /* Terminal supports setting the scroll
-                                  window */
-extern int scroll_region_cost; /* Cost of setting the scroll window,
-                                  measured in characters */
-extern int memory_below_frame; /* Terminal remembers lines scrolled
-                                  off bottom */
-extern int fast_clear_end_of_line; /* Terminal has a `ce' string */
-
-extern int dont_calculate_costs; /* Nonzero means don't bother computing
-                                   various cost tables; we won't use them. */
-
-/* Nonzero means no need to redraw the entire frame on resuming
-   a suspended Emacs.  This is useful on terminals with multiple pages,
-   where one page is used for Emacs and another for all else. */
-extern int no_redraw_on_reenter;
+struct tty_output
+{
+  /* The Emacs structure for the tty device this frame is on. */
+  struct tty_display_info *display_info;
+
+  /* There is nothing else here at the moment... */
+};
+
+/* Parameters that are shared between frames on the same tty device. */
+
+struct tty_display_info
+{
+  struct tty_display_info *next; /* Chain of all tty devices. */
+  
+  char *name;                   /* The name of the device file or 0 if
+                                   stdin/stdout. */
+  char *type;                   /* The type of the tty. */
+  
+  /* Input/output */
+  
+  FILE *input;                  /* The stream to be used for terminal input.
+                                   NULL if the terminal is suspended. */
+  FILE *output;                 /* The stream to be used for terminal output.
+                                   NULL if the terminal is suspended. */
+  
+  FILE *termscript;             /* If nonzero, send all terminal output
+                                   characters to this stream also.  */
+
+  struct emacs_tty *old_tty;    /* The initial tty mode bits */
+
+  int term_initted;             /* 1 if we have been through init_sys_modes. */
+
+
+  int reference_count;          /* Number of frames that are on this display. */
+
+  struct display *display;      /* Points back to the generic display
+                                   structure.  This is sometimes handy. */
+  
+  /* Info on cursor positioning.  */
+  struct cm *Wcm;
+
+  /* Redisplay. */
+
+  Lisp_Object top_frame;        /* The topmost frame on this tty. */
+  
+  /* The previous terminal frame we displayed on this tty.  */
+  struct frame *previous_terminal_frame;
+
+  /* Strings, numbers and flags taken from the termcap entry.  */
+
+  char *TS_ins_line;           /* "al" */
+  char *TS_ins_multi_lines;    /* "AL" (one parameter, # lines to insert) */
+  char *TS_bell;                /* "bl" */
+  char *TS_clr_to_bottom;       /* "cd" */
+  char *TS_clr_line;           /* "ce", clear to end of line */
+  char *TS_clr_frame;          /* "cl" */
+  char *TS_set_scroll_region;  /* "cs" (2 params, first line and last line) */
+  char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
+                                   lines above scroll region, lines below it,
+                                   total lines again) */
+  char *TS_del_char;           /* "dc" */
+  char *TS_del_multi_chars;    /* "DC" (one parameter, # chars to delete) */
+  char *TS_del_line;           /* "dl" */
+  char *TS_del_multi_lines;    /* "DL" (one parameter, # lines to delete) */
+  char *TS_delete_mode;                /* "dm", enter character-delete mode */
+  char *TS_end_delete_mode;    /* "ed", leave character-delete mode */
+  char *TS_end_insert_mode;    /* "ei", leave character-insert mode */
+  char *TS_ins_char;           /* "ic" */
+  char *TS_ins_multi_chars;    /* "IC" (one parameter, # chars to insert) */
+  char *TS_insert_mode;                /* "im", enter character-insert mode */
+  char *TS_pad_inserted_char;  /* "ip".  Just padding, no commands.  */
+  char *TS_end_keypad_mode;    /* "ke" */
+  char *TS_keypad_mode;                /* "ks" */
+  char *TS_pad_char;           /* "pc", char to use as padding */
+  char *TS_repeat;             /* "rp" (2 params, # times to repeat
+                                  and character to be repeated) */
+  char *TS_end_standout_mode;  /* "se" */
+  char *TS_fwd_scroll;         /* "sf" */
+  char *TS_standout_mode;       /* "so" */
+  char *TS_rev_scroll;          /* "sr" */
+  char *TS_end_termcap_modes;   /* "te" */
+  char *TS_termcap_modes;       /* "ti" */
+  char *TS_visible_bell;        /* "vb" */
+  char *TS_cursor_normal;       /* "ve" */
+  char *TS_cursor_visible;      /* "vs" */
+  char *TS_cursor_invisible;    /* "vi" */
+  char *TS_set_window;          /* "wi" (4 params, start and end of window,
+                                   each as vpos and hpos) */
+
+  char *TS_enter_bold_mode;     /* "md" -- turn on bold (extra bright mode).  */
+  char *TS_enter_dim_mode;      /* "mh" -- turn on half-bright mode.  */
+  char *TS_enter_blink_mode;    /* "mb" -- enter blinking mode.  */
+  char *TS_enter_reverse_mode;  /* "mr" -- enter reverse video mode.  */
+  char *TS_exit_underline_mode; /* "us" -- start underlining.  */
+  char *TS_enter_underline_mode; /* "ue" -- end underlining.  */
+
+  /* "as"/"ae" -- start/end alternate character set.  Not really
+     supported, yet.  */
+  char *TS_enter_alt_charset_mode;
+  char *TS_exit_alt_charset_mode;
+
+  char *TS_exit_attribute_mode; /* "me" -- switch appearances off.  */
+
+  /* Value of the "NC" (no_color_video) capability, or 0 if not present.  */
+  int TN_no_color_video;
+
+  int TN_max_colors;            /* "Co" -- number of colors.  */
+
+  /* "pa" -- max. number of color pairs on screen.  Not handled yet.
+     Could be a problem if not equal to TN_max_colors * TN_max_colors.  */
+  int TN_max_pairs;
+
+  /* "op" -- SVr4 set default pair to its original value.  */
+  char *TS_orig_pair;
+
+  /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color.
+     1 param, the color index.  */
+  char *TS_set_foreground;
+  char *TS_set_background;
+
+  int TF_hazeltine;             /* termcap hz flag. */
+  int TF_insmode_motion;        /* termcap mi flag: can move while in insert mode. */
+  int TF_standout_motion;       /* termcap mi flag: can move while in standout mode. */
+  int TF_underscore;            /* termcap ul flag: _ underlines if over-struck on
+                                   non-blank position.  Must clear before writing _.  */
+  int TF_teleray;               /* termcap xt flag: many weird consequences.
+                                   For t1061. */
+
+  int RPov;                     /* # chars to start a TS_repeat */
+
+  int delete_in_insert_mode;    /* delete mode == insert mode */
+  
+  int se_is_so;                 /* 1 if same string both enters and leaves
+                                   standout mode */
+  
+  int costs_set;                /* Nonzero if costs have been calculated. */
+  
+  int insert_mode;              /* Nonzero when in insert mode.  */
+  int standout_mode;            /* Nonzero when in standout mode.  */
+
+
+
+  /* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
+     keep 0200 bit in input chars.  0 to ignore the 0200 bit.  */
+
+  int meta_key;
+
+  /* Size of window specified by higher levels.
+   This is the number of lines, from the top of frame downwards,
+   which can participate in insert-line/delete-line operations.
+
+   Effectively it excludes the bottom frame_lines - specified_window_size
+   lines from those operations.  */
+
+  int specified_window;
+  
+  /* Flag used in tty_show/hide_cursor.  */
+
+  int cursor_hidden;
+
+  /* Nonzero means use ^S/^Q for flow control.  */
+  int flow_control;
+
+#ifdef MULTI_KBOARD
+  /* The terminal's keyboard object. */
+  struct kboard *kboard;
+#endif  
+};
+
+/* A chain of structures for all tty devices currently in use. */
+extern struct tty_display_info *tty_list;
+
+
+#define FRAME_TTY(f)                            \
+  ((f)->output_method == output_termcap         \
+   ? (f)->display->display_info.tty             \
+   : (abort(), (struct tty_display_info *) 0))
+
+#define CURTTY() FRAME_TTY (SELECTED_FRAME())
 
 /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193
    (do not change this comment) */
index 83721f659122aabdb33661316d4bbe5c14f114b3..49a0cbac85b77da149acd0d425f6cff93892c387 100644 (file)
@@ -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.
@@ -25,40 +24,11 @@ Boston, MA 02111-1307, USA.  */
 struct glyph;
 struct frame;
 
-/* If nonzero, send all terminal output characters to this stream also.  */
-extern FILE *termscript;
-
 /* Only use prototypes when lisp.h has been included.  */
 #ifndef P_
 #define P_(X) ()
 #endif
 \f
-/* 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));
-
-
-\f
-/* Multi-frame and mouse support hooks.  */
 
 enum scroll_bar_part {
   scroll_bar_above_handle,
@@ -72,125 +42,6 @@ enum scroll_bar_part {
   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));
-
-\f
-/* 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));
-
 \f
 /* Input queue declarations and hooks.  */
 
@@ -373,13 +224,6 @@ struct input_event
 
 #define EVENT_INIT(event) bzero (&(event), sizeof (struct input_event))
 
-/* Called to read input events.  */
-extern int (*read_socket_hook) P_ ((int, int, struct input_event *));
-
-/* Called when a frame's display becomes entirely up to date.  */
-extern void (*frame_up_to_date_hook) P_ ((struct frame *));
-\f
-
 /* Bits in the modifiers member of the input_event structure.
    Note that reorder_modifiers assumes that the bits are in canonical
    order.
@@ -429,7 +273,287 @@ enum {
   meta_modifier        =  CHAR_META    /* Under X, the XK_Meta_[LR] keysyms.  */
 };
 
+#endif /* CONSP */
+
+\f
+/* 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;
+
+\f
+  /* 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
 
+\f
+  /* 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_ ((struct display *));
+  void (*set_terminal_modes_hook) P_ ((struct display *));
+  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));
+
+  \f
+  /* 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));
+
+\f
+  /* Called to read input events.
+
+     DISPLAY indicates which display to read from.  Input events
+     should be read into BUF, the size of which is given in SIZE.
+     EXPECTED is non-zero if the caller suspects that new input is
+     available.
+
+     A positive return value indicates that that many input events
+     where read into BUF.
+     Zero means no events were immediately available.
+     A value of -1 means a transient read error, while -2 indicates
+     that the display was closed (hangup), and it should be deleted.
+
+     XXX Please note that a non-zero value of EXPECTED only means that
+     there is available input on at least one of the currently opened
+     display devices -- but not necessarily on this device.
+     Therefore, in most cases EXPECTED should be simply ignored.
+
+     XXX This documentation needs to be updated.  */
+  int (*read_socket_hook) P_ ((struct display *display,
+                               int expected,
+                               struct input_event *hold_quit));
+
+  /* Called when a frame's display becomes entirely up to date.  */
+  void (*frame_up_to_date_hook) P_ ((struct frame *));
+
+\f
+  /* 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, or when
+     the display device was closed (hangup).
+     
+     If this is NULL, then the generic delete_display() is called
+     instead.
+
+     The hook must check for and close any live frames that are still
+     on the display.  Fdelete_frame ensures that there are no live
+     frames on the display when it calls this hook, so infinite
+     recursion is prevented.  */
+  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 *));
+
+/* The initial display device, created by initial_term_init. */
+extern struct display *initial_display;
+
 /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d
    (do not change this comment) */
index 2dc798ea2c4a3e1e0eb6aeab70ece84132e153ff..10f0083a667e61249a0652bdedaba5f68157135e 100644 (file)
@@ -40,5 +40,10 @@ extern int meta_key;
 /* Nonzero means truncate lines in all windows less wide than the frame */
 extern int truncate_partial_width_windows;
 
+/* Nonzero means no need to redraw the entire frame on resuming a suspended
+   Emacs.  This is useful on terminals with multiple pages, where one page is
+   used for Emacs and another for all else. */
+extern int no_redraw_on_reenter;
+
 /* arch-tag: 35d4d284-dc1a-4fff-97fa-0154a21aebdb
    (do not change this comment) */
index 5e81afc7724957c6028cf029cbfd6f2addcafbb5..7f3b6b626de11475b8329b1bd9633e1338474547 100644 (file)
@@ -6340,12 +6340,13 @@ w32_initialize ()
   redeem_scroll_bar_hook = w32_redeem_scroll_bar;
   judge_scroll_bars_hook = w32_judge_scroll_bars;
 
-  scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;          /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;   /* X does this well */
-  memory_below_frame = 0;       /* we don't remember what scrolls
-                                  off the bottom */
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
+                                                            scrolls off the
+                                                            bottom */
   baud_rate = 19200;
 
   w32_system_caret_hwnd = NULL;
index de28620c7b93391eabd4737c4d93ea4fc7281b13..68967ad7d244ff8464039db63f19e06fcd7c7440 100644 (file)
@@ -389,8 +389,6 @@ extern struct w32_output w32term_display;
 #define FRAME_W32_WINDOW(f) ((f)->output_data.w32->window_desc)
 #define FRAME_X_WINDOW(f) ((f)->output_data.w32->window_desc)
 
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
 #define FRAME_FONT(f) ((f)->output_data.w32->font)
 #define FRAME_FONTSET(f) ((f)->output_data.w32->fontset)
 #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset)
index 626de53e21e8ee6f6c0f9d0b20209e04da189dd0..0192aa4edf606cc9f95e3de31a9b2c6b9bd4e537 100644 (file)
@@ -21,6 +21,8 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
+#include <stdio.h>
+
 #include "lisp.h"
 #include "buffer.h"
 #include "keyboard.h"
@@ -6402,7 +6404,7 @@ and scrolling positions.  */)
 void
 init_window_once ()
 {
-  struct frame *f = make_terminal_frame ();
+  struct frame *f = make_initial_frame ();
   XSETFRAME (selected_frame, f);
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
index c665e9921c6d374d08470aee0b4c3fdb842d6aff..ef81da43b4d78b4a20ffe3f8d5c590e7987af648 100644 (file)
@@ -747,7 +747,7 @@ extern Lisp_Object Vminibuf_scroll_window;
 /* Nil or a symbol naming the window system under which emacs is
    running ('x is the only current possibility) */
 
-extern Lisp_Object Vwindow_system;
+extern Lisp_Object Vinitial_window_system;
 
 /* Version number of X windows: 10, 11 or nil.  */
 
index 9c0434a681dcbe59c334bc256215298b934aea8f..0f5cde82cbd9b81972de231113f68cfa1783fb74 100644 (file)
@@ -770,10 +770,6 @@ enum move_it_result
 #define CLEAR_FACE_CACHE_COUNT 500
 static int clear_face_cache_count;
 
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
 /* Non-zero while redisplay_internal is in progress.  */
 
 int redisplaying_p;
@@ -2046,7 +2042,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   XSETWINDOW (it->window, w);
   it->w = w;
   it->f = XFRAME (w->frame);
-
+  
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
       && FRAME_WINDOW_P (it->f))
@@ -2059,9 +2055,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If realized faces have been removed, e.g. because of face
      attribute changes of named faces, recompute them.  When running
-     in batch mode, the face cache of Vterminal_frame is null.  If
+     in batch mode, the face cache of the initial frame is null.  If
      we happen to get called, make a dummy face cache.  */
-  if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
+  if (FRAME_FACE_CACHE (it->f) == NULL)
     init_frame_faces (it->f);
   if (FRAME_FACE_CACHE (it->f)->used == 0)
     recompute_basic_faces (it->f);
@@ -6590,8 +6586,8 @@ message2_nolog (m, nbytes, multibyte)
       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);
     }
 }
 
@@ -6676,8 +6672,8 @@ message3_nolog (m, nbytes, multibyte)
       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);
     }
 }
 
@@ -7700,11 +7696,11 @@ clear_garbaged_frames ()
     {
       Lisp_Object tail, frame;
       int changed_count = 0;
-
+      
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-
+         
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
@@ -7718,7 +7714,7 @@ clear_garbaged_frames ()
              f->resized_p = 0;
            }
        }
-
+      
       frame_garbaged = 0;
       if (changed_count)
        ++windows_or_buffers_changed;
@@ -7751,11 +7747,11 @@ echo_area_display (update_frame_p)
 /* 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 (EQ (selected_frame, Vterminal_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
@@ -7806,7 +7802,7 @@ echo_area_display (update_frame_p)
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
              update_single_window (w, 1);
-             rif->flush_display (f);
+             FRAME_RIF (f)->flush_display (f);
            }
          else
            update_frame (f, 1, 1);
@@ -8267,8 +8263,8 @@ x_cursor_to (vpos, hpos, y, x)
     {
       BLOCK_INPUT;
       display_and_set_cursor (w, 1, hpos, vpos, x, y);
-      if (rif->flush_display_optional)
-       rif->flush_display_optional (SELECTED_FRAME ());
+      if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+       FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
       UNBLOCK_INPUT;
     }
 }
@@ -9689,17 +9685,16 @@ redisplay_internal (preserve_echo_area)
   if (face_change_count)
     ++windows_or_buffers_changed;
 
-  if (! FRAME_WINDOW_P (sf)
-      && previous_terminal_frame != sf)
+  if (FRAME_TERMCAP_P (sf)
+      && FRAME_TTY (sf)->previous_terminal_frame != sf)
     {
-      /* Since frames on an ASCII terminal share the same display
-        area, displaying a different frame means redisplay the whole
-        thing.  */
+      /* Since frames on a single ASCII terminal share the same
+        display area, displaying a different frame means redisplay
+        the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-      XSETFRAME (Vterminal_frame, sf);
+      FRAME_TTY (sf)->previous_terminal_frame = sf;
     }
-  previous_terminal_frame = sf;
 
   /* Set the visible flags for all frames.  Do this before checking
      for resized or garbaged frames; they want to know if their frames
@@ -9721,6 +9716,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+  
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -10080,7 +10076,7 @@ redisplay_internal (preserve_echo_area)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_WINDOW_P (f) || f == sf)
+         if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
              if (! EQ (frame, selected_frame))
                /* Select the frame, for the sake of frame-local
@@ -10095,16 +10091,16 @@ redisplay_internal (preserve_echo_area)
 
              /* 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
@@ -10156,8 +10152,8 @@ redisplay_internal (preserve_echo_area)
            {
              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);
            }
        }
     }
@@ -10242,8 +10238,8 @@ redisplay_internal (preserve_echo_area)
          /* Say overlay arrows are up to date.  */
          update_overlay_arrows (1);
 
-         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;
@@ -11378,7 +11374,9 @@ set_vertical_scroll_bar (w)
     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);
 }
 
 
@@ -12098,7 +12096,8 @@ redisplay_window (window, just_this_one_p)
 
       /* 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.  */
@@ -12307,10 +12306,10 @@ try_window_reusing_current_matrix (w)
          if (run.height > 0 && run.current_y != run.desired_y)
            {
              update_begin (f);
-             rif->update_window_begin_hook (w);
-             rif->clear_window_mouse_face (w);
-             rif->scroll_run_hook (w, &run);
-             rif->update_window_end_hook (w, 0, 0);
+             FRAME_RIF (f)->update_window_begin_hook (w);
+             FRAME_RIF (f)->clear_window_mouse_face (w);
+             FRAME_RIF (f)->scroll_run_hook (w, &run);
+             FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
              update_end (f);
            }
 
@@ -12480,10 +12479,10 @@ try_window_reusing_current_matrix (w)
       if (run.height)
        {
          update_begin (f);
-         rif->update_window_begin_hook (w);
-         rif->clear_window_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
          update_end (f);
        }
 
@@ -12908,7 +12907,7 @@ try_window_id (w)
 
   /* Window must either use window-based redisplay or be full width.  */
   if (!FRAME_WINDOW_P (f)
-      && (!line_ins_del_ok
+      && (!FRAME_LINE_INS_DEL_OK (f)
          || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
@@ -13315,10 +13314,10 @@ try_window_id (w)
 
       if (FRAME_WINDOW_P (f))
        {
-         rif->update_window_begin_hook (w);
-         rif->clear_window_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
        }
       else
        {
@@ -13340,7 +13339,7 @@ try_window_id (w)
 
              /* On dumb terminals delete dvpos lines at the end
                 before inserting dvpos empty lines.  */
-             if (!scroll_region_ok)
+             if (!FRAME_SCROLL_REGION_OK (f))
                ins_del_lines (end - dvpos, -dvpos);
 
              /* Insert dvpos empty lines in front of
@@ -13361,7 +13360,7 @@ try_window_id (w)
 
              /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
-             if (!scroll_region_ok)
+             if (!FRAME_SCROLL_REGION_OK (f))
                ins_del_lines (end + dvpos, -dvpos);
            }
 
@@ -17135,7 +17134,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
            glyph->font_type
-             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+             = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
        }
     }
 
@@ -17365,7 +17364,7 @@ x_get_glyph_overhangs (glyph, f, left, right)
       font = face->font;
       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
       if (font  /* ++KFS: Should this be font_info ?  */
-         && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+         && (pcm = FRAME_RIF (f)->per_char_metric (font, &char2b, glyph->font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
@@ -17533,7 +17532,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
          struct font_info *font_info
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
-           rif->encode_char (c, char2b, font_info, 0);
+           FRAME_RIF (f)->encode_char (c, char2b, font_info, 0);
        }
     }
 
@@ -17600,8 +17599,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          x -= s->width;
          s->x = x;
          s = s->prev;
@@ -17611,8 +17610,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          s->x = x;
          x += s->width;
          s = s->next;
@@ -17893,9 +17892,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       struct glyph_string *h, *t;
 
       /* Compute overhangs for all glyph strings.  */
-      if (rif->compute_glyph_string_overhangs)
+      if (FRAME_RIF (f)->compute_glyph_string_overhangs)
        for (s = head; s; s = s->next)
-         rif->compute_glyph_string_overhangs (s);
+         FRAME_RIF (f)->compute_glyph_string_overhangs (s);
 
       /* Prepend glyph strings for glyphs in front of the first glyph
         string that are overwritten because of the first glyph
@@ -17963,7 +17962,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
 
   /* Draw all strings.  */
   for (s = head; s; s = s->next)
-    rif->draw_glyph_string (s);
+    FRAME_RIF (f)->draw_glyph_string (s);
 
   if (area == TEXT_AREA
       && !row->full_width_p
@@ -18471,8 +18470,8 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
+         pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                    FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
          it->ascent = FONT_BASE (font) + boff;
          it->descent = FONT_DESCENT (font) - boff;
 
@@ -18596,8 +18595,8 @@ x_produce_glyphs (it)
             from the charset width; this is what old redisplay code
             did.  */
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+         pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                    FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 
          if (font_not_found_p || !pcm)
            {
@@ -18728,8 +18727,8 @@ x_produce_glyphs (it)
 
          /* Initialize the bounding box.  */
          if (font_info
-             && (pcm = rif->per_char_metric (font, &char2b,
-                                             FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
+             && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                            FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
            {
              width = pcm->width;
              ascent = pcm->ascent;
@@ -18787,8 +18786,8 @@ x_produce_glyphs (it)
                }
 
              if (font_info
-                 && (pcm = rif->per_char_metric (font, &char2b,
-                                                 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
+                 && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                                FONT_TYPE_FOR_MULTIBYTE (font, ch))))
                {
                  width = pcm->width;
                  ascent = pcm->ascent;
@@ -19023,8 +19022,8 @@ x_insert_glyphs (start, len)
   frame_x = window_box_left (w, updated_area) + output_cursor.x;
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
 
-  rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
-                               line_height, shift_by_width);
+  FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
+                                          line_height, shift_by_width);
 
   /* Write the glyphs.  */
   hpos = start - row->glyphs[updated_area];
@@ -19106,8 +19105,8 @@ x_clear_end_of_line (to_x)
   if (to_x > from_x && to_y > from_y)
     {
       BLOCK_INPUT;
-      rif->clear_frame_area (f, from_x, from_y,
-                            to_x - from_x, to_y - from_y);
+      FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
+                                       to_x - from_x, to_y - from_y);
       UNBLOCK_INPUT;
     }
 }
@@ -19569,8 +19568,8 @@ erase_phys_cursor (w)
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
 
-      rif->clear_frame_area (f, x, y,
-                            cursor_glyph->pixel_width, cursor_row->visible_height);
+      FRAME_RIF (f)->clear_frame_area (f, x, y,
+                                       cursor_glyph->pixel_width, cursor_row->visible_height);
     }
 
   /* Erase the cursor by redrawing the character underneath it.  */
@@ -19667,9 +19666,9 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
       w->phys_cursor.vpos = vpos;
     }
 
-  rif->draw_window_cursor (w, glyph_row, x, y,
-                          new_cursor_type, new_cursor_width,
-                          on, active_cursor);
+  FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
+                                     new_cursor_type, new_cursor_width,
+                                     on, active_cursor);
 }
 
 
@@ -19814,11 +19813,11 @@ show_mouse_face (dpyinfo, draw)
 
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
   else if (draw == DRAW_MOUSE_FACE)
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
   else
-    rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
 }
 
 /* EXPORT:
@@ -20232,8 +20231,7 @@ on_hot_spot_p (hot_spot, x, y)
          return inside;
        }
     }
-  else
-    return 0;
+  return 0;
 }
 
 Lisp_Object
@@ -20268,7 +20266,6 @@ Returns the alist element for the first matching AREA in MAP.  */)
      Lisp_Object map;
      Lisp_Object x, y;
 {
-  int ix, iy;
   if (NILP (map))
     return Qnil;
 
@@ -20313,7 +20310,7 @@ define_frame_cursor1 (f, cursor, pointer)
 #else
   if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
 #endif
-    rif->define_frame_cursor (f, cursor);
+    FRAME_RIF (f)->define_frame_cursor (f, cursor);
 }
 
 /* Take proper action when mouse has moved to the mode or header line
@@ -20334,7 +20331,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   Lisp_Object pointer = Qnil;
   int charpos, dx, dy, width, height;
   Lisp_Object string, object = Qnil;
-  Lisp_Object pos, help, image;
+  Lisp_Object pos, help;
 
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
     string = mode_line_string (w, area, &x, &y, &charpos,
@@ -21151,6 +21148,8 @@ void
 x_draw_vertical_border (w)
      struct window *w;
 {
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  
   /* We could do better, if we knew what type of scroll-bar the adjacent
      windows (on either side) have...  But we don't :-(
      However, I think this works ok.  ++KFS 2003-04-25 */
@@ -21167,7 +21166,7 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
-      rif->draw_vertical_window_border (w, x1, y0, y1);
+      FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
     }
   else if (!WINDOW_LEFTMOST_P (w)
           && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
@@ -21177,7 +21176,7 @@ x_draw_vertical_border (w)
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
-      rif->draw_vertical_window_border (w, x0, y0, y1);
+      FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
     }
 }
 
index b96dd18ec4d5a638a25a7d63f3531137afeb1f97..2e6d43a54b722a7e682122ab64211f339721e4e1 100644 (file)
@@ -195,11 +195,13 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdio.h>              /* This needs to be before termchar.h */
 
 #include "lisp.h"
 #include "charset.h"
 #include "keyboard.h"
 #include "frame.h"
+#include "termhooks.h"
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
@@ -242,6 +244,7 @@ Boston, MA 02111-1307, USA.  */
 #include "blockinput.h"
 #include "window.h"
 #include "intervals.h"
+#include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -5410,7 +5413,7 @@ substitution of a `dim' face for italic.  */)
   /* See if the capabilities we selected above are supported, with the
      given colors.  */
   if (test_caps != 0 &&
-      ! tty_capable_p (f, 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;
 
 
@@ -6642,7 +6645,8 @@ realize_basic_faces (f)
        {
          FRAME_FACE_CACHE (f)->menu_face_changed_p = 0;
 #ifdef USE_X_TOOLKIT
-         x_update_menu_appearance (f);
+          if (FRAME_WINDOW_P (f))
+            x_update_menu_appearance (f);
 #endif
        }
 
@@ -6729,7 +6733,7 @@ realize_default_face (f)
        LFACE_FOREGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
        return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
        LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
       else
        abort ();
@@ -6744,7 +6748,7 @@ realize_default_face (f)
        LFACE_BACKGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
        return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
        LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
       else
        abort ();
@@ -6833,6 +6837,11 @@ realize_face (cache, attrs, c, base_face, former_face_id)
     face = realize_x_face (cache, attrs, c, base_face);
   else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
     face = realize_tty_face (cache, attrs, c);
+  else if (FRAME_INITIAL_P (cache->f))
+    {
+      /* Create a dummy face. */
+      face = make_realized_face (attrs);
+    }
   else
     abort ();
 
index c422e3ad9942511fb952afe501482dff9ea52d7d..8528229c087fd550dceed4e514e63e3707d05150 100644 (file)
@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA.  */
 #include "systime.h"
 #include "termhooks.h"
 #include "atimer.h"
+#include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -1419,10 +1420,10 @@ x_set_scroll_bar_foreground (f, value, oldval)
   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);
@@ -1468,10 +1469,10 @@ x_set_scroll_bar_background (f, value, oldval)
   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);
@@ -2846,8 +2847,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
   Lisp_Object parent;
   struct kboard *kb;
 
-  check_x ();
-
   /* Use this general default value to start with
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
@@ -2902,6 +2901,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Note that X Windows does support scroll bars.  */
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
 
+  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));
@@ -2991,6 +2993,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
       specbind (Qx_resource_name, name);
     }
 
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
+
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
   {
@@ -3788,8 +3792,10 @@ x_display_info_for_name (name)
 
   CHECK_STRING (name);
 
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
+#if 0
+  if (! EQ (Vinitial_window_system, intern ("x")))
+    error ("Not using X Windows"); /* That doesn't stop us anymore. */
+#endif
 
   for (dpyinfo = x_display_list, names = x_display_name_list;
        dpyinfo;
@@ -3836,8 +3842,10 @@ terminate Emacs if we can't open the connection.  */)
   if (! NILP (xrm_string))
     CHECK_STRING (xrm_string);
 
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
+#if 0
+  if (! EQ (Vinitial_window_system, intern ("x")))
+    error ("Not using X Windows"); /* That doesn't stop us anymore. */
+#endif
 
   if (! NILP (xrm_string))
     xrm_option = (unsigned char *) SDATA (xrm_string);
@@ -4448,6 +4456,9 @@ x_create_tip_frame (dpyinfo, parms, text)
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
+  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
      from this point on, x_destroy_window might screw up reference
@@ -4671,6 +4682,8 @@ x_create_tip_frame (dpyinfo, parms, text)
                                              Qnil));
   }
 
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
+
   f->no_split = 1;
 
   UNGCPRO;
index 473e29de88d37e0e5f39b9bd244c02ad0afe0c66..2ca6e247e1203c6c8c2847db332aaabc6322ffad 100644 (file)
@@ -39,10 +39,10 @@ Boston, MA 02111-1307, USA.  */
 #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"
index b4d61f7c9a97d7a5b70029939cf2dd94a14c84df..637b39272b799c90a16ba7d99ec5dce962d8f4c4 100644 (file)
@@ -308,13 +308,20 @@ x_own_selection (selection_name, selection_value)
      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);
 
@@ -578,7 +585,8 @@ some_frame_on_display (dpyinfo)
 
   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;
     }
 
@@ -1225,17 +1233,26 @@ x_get_foreign_selection (selection_symbol, target_type, time_stamp)
      Lisp_Object selection_symbol, target_type, time_stamp;
 {
   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
@@ -2009,6 +2026,9 @@ Disowning it means there is no such selection.  */)
   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);
@@ -2172,6 +2192,10 @@ DEFUN ("x-get-cut-buffer-internal", Fx_get_cut_buffer_internal,
   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 */
@@ -2213,6 +2237,10 @@ DEFUN ("x-store-cut-buffer-internal", Fx_store_cut_buffer_internal,
   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 */
 
@@ -2269,8 +2297,12 @@ Positive means shift the values forward, negative means backward.  */)
   Atom props[8];
   Display *display;
   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 */
   CHECK_NUMBER (n);
index e486e5c6e322384003af36bd3129ea3436b35294..35c7429b66b543a9df51ee4181caa58c46a23c94 100644 (file)
@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA.  */
 #include "systime.h"
 #include "sysselect.h"
 #include "lisp.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "xterm.h"
index da875b6156fa5dc91e4d6bcf39a99289b787ffb8..350c68ca20f40b277ea71f767130458e4cd23041 100644 (file)
@@ -54,7 +54,6 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/ioctl.h>
 #endif /* ! defined (BSD_SYSTEM) */
 
-#include "systty.h"
 #include "systime.h"
 
 #ifndef INCLUDED_FCNTL
@@ -336,13 +335,15 @@ void x_raise_frame P_ ((struct frame *));
 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 *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
+static void XTset_terminal_modes P_ ((struct display *));
+static void XTreset_terminal_modes P_ ((struct display *));
 static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
@@ -384,7 +385,8 @@ x_flush (f)
     {
       Lisp_Object rest, frame;
       FOR_EACH_FRAME (rest, frame)
-       x_flush (XFRAME (frame));
+        if (FRAME_X_P (XFRAME (frame)))
+          x_flush (XFRAME (frame));
     }
   else if (FRAME_X_P (f))
     XFlush (FRAME_X_DISPLAY (f));
@@ -471,7 +473,6 @@ x_update_begin (f)
   /* Nothing to do.  */
 }
 
-
 /* Start update of window W.  Set the global variable updated_window
    to the window being updated and set output_cursor to the cursor
    position of W.  */
@@ -791,7 +792,7 @@ x_draw_fringe_bitmap (w, row, p)
    rarely happens).  */
 
 static void
-XTset_terminal_modes ()
+XTset_terminal_modes (struct display *display)
 {
 }
 
@@ -799,7 +800,7 @@ XTset_terminal_modes ()
    the X-windows go away, and suspending requires no action.  */
 
 static void
-XTreset_terminal_modes ()
+XTreset_terminal_modes (struct display *display)
 {
 }
 
@@ -1410,7 +1411,8 @@ x_frame_of_widget (widget)
   for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     if (GC_FRAMEP (XCAR (tail))
        && (f = XFRAME (XCAR (tail)),
-           (f->output_data.nothing != 1
+           (FRAME_X_P (f)
+             && f->output_data.nothing != 1
             && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
        && f->output_data.x->widget == widget)
       return f;
@@ -3233,7 +3235,6 @@ x_detect_focus_change (dpyinfo, event, bufp)
      struct input_event *bufp;
 {
   struct frame *frame;
-  int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
   if (! frame)
@@ -3692,7 +3693,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
       /* Clear the mouse-moved flag for every frame on this display.  */
       FOR_EACH_FRAME (tail, frame)
-       if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+       if (FRAME_X_P (XFRAME (frame))
+            && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
          XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
@@ -3906,6 +3908,9 @@ x_window_to_scroll_bar (display, window_id)
       if (! GC_FRAMEP (frame))
        abort ();
 
+      if (! FRAME_X_P (XFRAME (frame)))
+        continue;
+      
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -3940,11 +3945,14 @@ x_window_to_menu_bar (window)
        XGCTYPE (tail) == Lisp_Cons;
        tail = XCDR (tail))
     {
-      Lisp_Object frame = XCAR (tail);
-      Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+      if (FRAME_X_P (XFRAME (XCAR (tail))))
+        {
+          Lisp_Object frame = XCAR (tail);
+          Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
 
-      if (menu_bar && xlwmenu_window_p (menu_bar, window))
-       return menu_bar;
+          if (menu_bar && xlwmenu_window_p (menu_bar, window))
+            return menu_bar;
+        }
     }
 
   return NULL;
@@ -6330,37 +6338,37 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
           orig_keysym = keysym;
 
-         /* Common for all keysym input events.  */
-         XSETFRAME (inev.frame_or_window, f);
-         inev.modifiers
-           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
-         inev.timestamp = event.xkey.time;
-
-         /* First deal with keysyms which have defined
-            translations to characters.  */
-         if (keysym >= 32 && keysym < 128)
-           /* Avoid explicitly decoding each ASCII character.  */
-           {
-             inev.kind = ASCII_KEYSTROKE_EVENT;
-             inev.code = keysym;
-             goto done_keysym;
-           }
-
-         /* Now non-ASCII.  */
-         if (HASH_TABLE_P (Vx_keysym_table)
-             && (NATNUMP (c = Fgethash (make_number (keysym),
-                                        Vx_keysym_table,
-                                        Qnil))))
-           {
-             inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                           ? ASCII_KEYSTROKE_EVENT
-                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-             inev.code = XFASTINT (c);
-             goto done_keysym;
-           }
-
-         /* Random non-modifier sorts of keysyms.  */
-         if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+         /* Common for all keysym input events.  */
+         XSETFRAME (inev.frame_or_window, f);
+         inev.modifiers
+           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+         inev.timestamp = event.xkey.time;
+
+         /* First deal with keysyms which have defined
+            translations to characters.  */
+         if (keysym >= 32 && keysym < 128)
+           /* Avoid explicitly decoding each ASCII character.  */
+           {
+             inev.kind = ASCII_KEYSTROKE_EVENT;
+             inev.code = keysym;
+             goto done_keysym;
+           }
+         /* Now non-ASCII.  */
+         if (HASH_TABLE_P (Vx_keysym_table)
+             && (NATNUMP (c = Fgethash (make_number (keysym),
+                                        Vx_keysym_table,
+                                        Qnil))))
+           {
+             inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                           ? ASCII_KEYSTROKE_EVENT
+                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+             inev.code = XFASTINT (c);
+             goto done_keysym;
+           }
+         /* Random non-modifier sorts of keysyms.  */
+         if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
                         || (keysym >= XK_ISO_Left_Tab
@@ -6993,8 +7001,8 @@ x_dispatch_event (event, display)
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, expected, hold_quit)
-     register int sd;
+XTread_socket (display, expected, hold_quit)
+     struct display *display;
      int expected;
      struct input_event *hold_quit;
 {
@@ -7582,7 +7590,11 @@ x_catch_errors_unwind (old_val)
 
   first = XCAR (old_val);
 
+#if 0  /* XXX This has dumped core on me several times when my X
+          server crashed.  If this call is important, maybe we should
+          check that the display is still alive. -- lorentey */
   XSync (XSAVE_VALUE (first)->pointer, False);
+#endif
 
   x_error_message_string = XCDR (old_val);
   return Qnil;
@@ -7775,7 +7787,7 @@ x_connection_closed (dpy, error_message)
 
   x_uncatch_errors (dpy, count);
 
-  if (x_display_list == 0)
+  if (display_list == 0)
     {
       fprintf (stderr, "%s\n", error_msg);
       shut_down_emacs (0, 0, Qnil);
@@ -7972,7 +7984,7 @@ xim_destroy_callback (xim, client_data, call_data)
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
          if (FRAME_XIC_FONTSET (f))
@@ -8075,7 +8087,8 @@ xim_instantiate_callback (display, client_data, call_data)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+         if (FRAME_X_P (f)
+              && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
            if (FRAME_XIC (f) == NULL)
              {
                create_frame_xic (f);
@@ -8172,7 +8185,6 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   int win_x = 0, win_y = 0;
   int flags = f->size_hint_flags;
 
@@ -10116,6 +10128,7 @@ x_term_init (display_name, xrm_option, resource_name)
 {
   int connection;
   Display *dpy;
+  struct display *display;
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
 
@@ -10250,6 +10263,8 @@ x_term_init (display_name, xrm_option, resource_name)
   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;
@@ -10600,7 +10615,18 @@ x_delete_display (dpyinfo)
      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.
@@ -10698,70 +10724,97 @@ x_process_timeouts (timer)
 extern frame_parm_handler x_frame_parm_handlers[];
 
 static struct redisplay_interface x_redisplay_interface =
-{
-  x_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
+  {
+    x_frame_parm_handlers,
+    x_produce_glyphs,
+    x_write_glyphs,
+    x_insert_glyphs,
+    x_clear_end_of_line,
+    x_scroll_run,
+    x_after_update_window_line,
+    x_update_window_begin,
+    x_update_window_end,
+    x_cursor_to,
+    x_flush,
 #ifndef XFlush
-  x_flush,
+    x_flush,
 #else
-  0,  /* flush_display_optional */
+    0,  /* flush_display_optional */
 #endif
-  x_clear_window_mouse_face,
-  x_get_glyph_overhangs,
-  x_fix_overlapping_area,
-  x_draw_fringe_bitmap,
-  0, /* define_fringe_bitmap */
-  0, /* destroy_fringe_bitmap */
-  x_per_char_metric,
-  x_encode_char,
-  x_compute_glyph_string_overhangs,
-  x_draw_glyph_string,
-  x_define_frame_cursor,
-  x_clear_frame_area,
-  x_draw_window_cursor,
-  x_draw_vertical_window_border,
-  x_shift_glyphs_for_insert
-};
+    x_clear_window_mouse_face,
+    x_get_glyph_overhangs,
+    x_fix_overlapping_area,
+    x_draw_fringe_bitmap,
+    0, /* define_fringe_bitmap */
+    0, /* destroy_fringe_bitmap */
+    x_per_char_metric,
+    x_encode_char,
+    x_compute_glyph_string_overhangs,
+    x_draw_glyph_string,
+    x_define_frame_cursor,
+    x_clear_frame_area,
+    x_draw_window_cursor,
+    x_draw_vertical_window_border,
+    x_shift_glyphs_for_insert
+  };
+
+
+/* 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 ()
 {
-  rif = &x_redisplay_interface;
-
-  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;
-
-  scroll_region_ok = 1;                /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;         /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;  /* X does this well */
-  memory_below_frame = 0;      /* we don't remember what scrolls
-                                  off the bottom */
   baud_rate = 19200;
 
   x_noop_count = 0;
index 1d43414cf547150ef042d20bd196afce1a61d439..a350567cd4693f8447ec9abe3d9877e60ba648bb 100644 (file)
@@ -382,6 +382,9 @@ struct x_display_info
       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