summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaroly Lorentey <lorentey@elte.hu>2004-07-04 04:48:55 +0000
committerKaroly Lorentey <lorentey@elte.hu>2004-07-04 04:48:55 +0000
commitb6660415b3094d37b27e8d303f2c57c4c2a60700 (patch)
tree715ac1a52f92c0e5d6d25bd089ba9c048b012339
parent91b726f0f87d0adcec194642256375f4302c52a8 (diff)
downloademacs-b6660415b3094d37b27e8d303f2c57c4c2a60700.tar.gz
Implemented display ids for multiple emacsclients on the same tty. Plus assorted bugfixes.
* lisp/frame.el (make-frame-on-display): Update doc. (make-frame): Handle display-id parameter. Update doc. (frames-on-display-list): Update for display ids. (framep-on-display): Ditto. (suspend-frame): Use display-name, not frame-tty-name. (selected-display): New function. * lisp/server.el (server-delete-client): Use delete-display, not delete-tty. (server-tty-live-p, server-handle-delete-tty): Removed. (server-handle-delete-frame): Delete tty clients, if needed. (server-process-filter): Set the display parameter, and use it when appropriate. (server-handle-suspend-tty): Use the display parameter. (server-start, server-unload-hook): Removed obsolete delete-tty hook. * lisp/talk.el (talk): Always use talk-add-display. (talk-add-tty-frame, talk-handle-delete-tty): Removed. (talk-handle-delete-frame): New function. (talk-add-display): Open a new frame only if parameter was not a frame. * src/dispextern.h (get_display, Fdisplay_tty_type): New prototypes. (Fframe_tty_type): Removed. * src/dispnew.c (init_display): Use Fdisplay_tty_type, not Fframe_tty_type. * src/frame.c (Qdisplay_id, Qdisplay_live_p): New symbols. (make_terminal_frame): Get display as a parameter. (Fmake_terminal_frame): Get/create display here; pass it to make_terminal_frame. (Fframe_display): New function. (Fdelete_frame): Stop if the hook deleted the frame. (syms_of_frame): Register new stuff. * src/frame.h (Qdisplay_id, Qdisplay_live_p, make_terminal_frame): Updated prototypes. * src/keyboard.c (interrupt_signal): Updated comment. * src/term.c (Vdelete_tty_after_functions): Removed variable. (Qframe_tty_name, Qframe_tty_type): Removed. (next_display_id): New var. (tty_ring_bell): Don't do anything on suspended frames. (Ftty_display_color_p, Ftty_display_color_cells): Doc update. (get_display): New function. (get_tty_display): Use it. (get_named_tty_display): Ignore suspended displays. (Fframe_tty_name): Renamed to Fdisplay_name. Handle all kinds of displays. (Fframe_tty_type): Renamed to Fdisplay_tty_type. (init_initial_display): Set display name. (term_init): Allow more displays on the same device. Set display name. (Fdelete_tty): Removed. (delete_tty): Don't run hooks. (create_display): Set display id. (delete_display): Free display name. (Fdelete_display, Fdisplay_live_p, Fdisplay_list): New functions. (Fsuspend_tty): Call hook with display id. Doc update. (Fresume_tty): Refuse to resume when there is already an active display on the same device. Call hook with display id. Doc update. (syms_of_term): Reflect above changes. * src/termhooks.h (struct display): Added `id' and `name' members. (DISPLAY_ACTIVE_P): New macro. * src/xfns.c (check_x_display_info): Handle display ids. (Fx_create_frame): Try to get display from `display-id' parameter. * src/xterm.c (x_term_init): Set display name. (x_delete_display): Handle the case when `font_table' is NULL. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-207
-rw-r--r--README.multi-tty93
-rw-r--r--lisp/frame.el40
-rw-r--r--lisp/server.el56
-rw-r--r--lisp/talk.el54
-rw-r--r--src/dispextern.h3
-rw-r--r--src/dispnew.c2
-rw-r--r--src/frame.c150
-rw-r--r--src/frame.h3
-rw-r--r--src/keyboard.c2
-rw-r--r--src/term.c421
-rw-r--r--src/termhooks.h13
-rw-r--r--src/xfns.c15
-rw-r--r--src/xterm.c10
13 files changed, 497 insertions, 365 deletions
diff --git a/README.multi-tty b/README.multi-tty
index 2d020d3abb2..c692411e757 100644
--- a/README.multi-tty
+++ b/README.multi-tty
@@ -206,6 +206,9 @@ See arch logs.
THINGS TO DO
------------
+** Hunt down display-related functions in frame.el and extend them all
+ to accept display ids.
+
** Have a look at fatal_error_hook.
** Check if we got term-setup-hook right.
@@ -255,45 +258,6 @@ THINGS TO DO
** Miles Bader suggests that C-x C-c on an emacsclient frame should
only close the frame, not exit the entire Emacs session.
-** 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.
-
- (Update: The consensus on emacs-devel seems to be to do this via
- integer identifiers. That's fine by me.)
-
-** The following needs to be supported:
-
- $ emacsclient -t
- C-z
- $ 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.
-
** 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.
@@ -813,4 +777,55 @@ DIARY OF CHANGES
(Fixed. Emacs now uses the locale settings as seen by the
emacsclient process for server tty frames.)
+
+-- Make `struct display' accessible to Lisp programs. Accessor functions:
+
+ (displayp OBJECT): Returns t if OBJECT is a display.
+ => Implemented as display-live-p.
+
+ (display-list): Returns list of currently active displays.
+ => Implemented.
+
+ (selected-display): Returns the display object of the selected frame.
+ => Not strictly necessary, but implemented anyway.
+
+ (frame-display FRAME): Returns the display object of FRAME.
+ => Implemented.
+
+ (display-frames DISPLAY): Returns a list of frames on DISPLAY.
+ => Already implemented, see frames-on-display-list.
+
+ (display-type DISPLAY): Returns the type of DISPLAY, as a
+ symbol. (See `framep'.)
+ => Implemented as display-live-p.
+
+ (display-device DISPLAY): Returns the name of the device that
+ DISPLAY uses, as a string. (E.g: "/dev/pts/16", or
+ ":0.0")
+ => Implemented as display-name.
+
+ etc.
+
+ See next issue why this is necessary.
+
+ (Update: The consensus on emacs-devel seems to be to do this via
+ integer identifiers. That's fine by me.)
+
+ (Done.)
+
+-- The following needs to be supported:
+
+ $ emacsclient -t
+ C-z
+ $ 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.
+
+ (Done.)
+
;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
diff --git a/lisp/frame.el b/lisp/frame.el
index ad88102af65..13a1ca50adf 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -577,7 +577,7 @@ is not considered (see `next-frame')."
(select-frame-set-input-focus (selected-frame)))
(defun make-frame-on-display (display &optional parameters)
- "Make a frame on display DISPLAY.
+ "Make a frame on X display DISPLAY.
The optional second argument PARAMETERS specifies additional frame parameters."
(interactive "sMake frame on display: ")
(or (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" display)
@@ -638,13 +638,22 @@ You cannot specify either `width' or `height', you must use neither or both.
(window-system . nil) The frame should be displayed on a terminal device.
(window-system . x) The frame should be displayed in an X window.
+ (display-id . ID) The frame should use the display identified by ID.
+
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)
- (let* ((w (if (assq 'window-system parameters)
- (cdr (assq 'window-system parameters))
- window-system))
+ (let* ((w (cond
+ ((assq 'display-id parameters)
+ (let ((type (display-live-p (cdr (assq 'display-id parameters)))))
+ (cond
+ ((eq type t) nil)
+ ((eq type nil) (error "Display %s does not exist" (cdr (assq 'display-id parameters))))
+ (t type))))
+ ((assq 'window-system parameters)
+ (cdr (assq 'window-system parameters)))
+ (t window-system)))
(frame-creation-function (cdr (assq w frame-creation-function-alist)))
frame)
(unless frame-creation-function
@@ -674,20 +683,25 @@ on `after-make-frame-functions' are run with one arg, the newly created frame."
(defun frames-on-display-list (&optional display)
"Return a list of all frames on DISPLAY.
-DISPLAY is a name of a display, a string of the form HOST:SERVER.SCREEN.
+
+DISPLAY should be a display identifier (an integer), but it may
+also be a name of a display, a string of the form HOST:SERVER.SCREEN.
+
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
- (let* ((display (or display (frame-parameter nil 'display)))
+ (let* ((display (or display (frame-display)))
(func #'(lambda (frame)
- (equal (frame-parameter frame 'display) display))))
+ (or (eq (frame-display frame) display)
+ (equal (frame-parameter frame 'display) display)))))
(filtered-frame-list func)))
(defun framep-on-display (&optional display)
"Return the type of frames on DISPLAY.
-DISPLAY may be a display name or a frame. If it is a frame, its type is
-returned.
+DISPLAY may be a display id, a display name or a frame. If it is
+a frame, its type is returned.
If DISPLAY is omitted or nil, it defaults to the selected frame's display.
All frames on a given display are of the same type."
- (or (framep display)
+ (or (display-live-p display)
+ (framep display)
(framep (car (frames-on-display-list display)))))
(defun frame-remove-geometry-params (param-list)
@@ -774,7 +788,7 @@ Calls `suspend-emacs' if invoked from the controlling terminal,
(cond
((eq type 'x) (iconify-or-deiconify-frame))
((eq type t)
- (if (frame-tty-name)
+ (if (display-name)
(suspend-tty)
(suspend-emacs)))
(t (suspend-emacs)))))
@@ -1023,6 +1037,10 @@ bars (top, bottom, or nil)."
(cons vert hor)))
;;;; Frame/display capabilities.
+(defun selected-display ()
+ "Return the display that is now selected."
+ (frame-display (selected-frame)))
+
(defun display-mouse-p (&optional display)
"Return non-nil if DISPLAY has a mouse available.
DISPLAY can be a display name, a frame, or nil (meaning the selected
diff --git a/lisp/server.el b/lisp/server.el
index 1bf276a26d0..009b82b1016 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -234,9 +234,9 @@ If NOFRAME is non-nil, let the frames live. (To be used from
(kill-buffer (current-buffer))))))
;; Delete the client's tty.
- (let ((tty (server-client-get client 'tty)))
- (when (and tty (server-tty-live-p tty))
- (delete-tty tty)))
+ (let ((display-id (server-client-get client 'display)))
+ (when (eq (display-live-p display-id) t)
+ (delete-display display-id)))
;; Delete the client's frames.
(unless noframe
@@ -264,38 +264,32 @@ If NOFRAME is non-nil, let the frames live. (To be used from
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)
"The process sentinel for Emacs server connections."
(server-log (format "Status changed to %s: %s" (process-status proc) msg) proc)
(server-delete-client proc))
-(defun server-handle-delete-tty (tty)
- "Delete the client connection when the emacsclient terminal device is closed."
- (dolist (proc (server-clients-with 'tty tty))
- (server-log (format "server-handle-delete-tty, tty %s" tty) proc)
- (server-delete-client proc)))
-
(defun server-handle-delete-frame (frame)
"Delete the client connection when the emacsclient frame is deleted."
(let ((proc (frame-parameter frame 'client)))
- (when (and proc (window-system frame))
- ;; (Closing a terminal frame must not trigger a delete;
- ;; we must wait for delete-tty-after-functions.)
+ (when (and proc
+ (or (window-system frame)
+ ;; A terminal display must not yet be deleted if
+ ;; there are other frames on it.
+ (< 0 (let ((frame-num 0))
+ (mapc (lambda (f)
+ (when (eq (frame-display f)
+ (frame-display frame))
+ (setq frame-num (1+ frame-num))))
+ (frame-list))
+ frame-num))))
(server-log (format "server-handle-delete-frame, frame %s" frame) proc)
(server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
-(defun server-handle-suspend-tty (tty)
+(defun server-handle-suspend-tty (display)
"Notify the emacsclient process to suspend itself when its tty device is suspended."
- (dolist (proc (server-clients-with 'tty tty))
- (server-log (format "server-handle-suspend-tty, tty %s" tty) proc)
+ (dolist (proc (server-clients-with 'display display))
+ (server-log (format "server-handle-suspend-tty, display %s" display) proc)
(process-send-string proc "-suspend \n")))
(defun server-select-display (display)
@@ -395,7 +389,6 @@ Prefix arg means just kill any existing server communications subprocess."
(server-log (message "Restarting server"))
(server-log (message "Starting server")))
(letf (((default-file-modes) ?\700))
- (add-hook 'delete-tty-after-functions 'server-handle-delete-tty)
(add-hook 'suspend-tty-functions 'server-handle-suspend-tty)
(add-hook 'delete-frame-functions 'server-handle-delete-frame)
(add-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
@@ -496,21 +489,24 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(modify-frame-parameters frame (list (cons 'client proc)))
(select-frame frame)
(server-client-set client 'frame frame)
+ (server-client-set client 'display (frame-display frame))
(setq dontkill t))
;; -resume: Resume a suspended tty frame.
((equal "-resume" arg)
- (let ((tty (server-client-get client 'tty)))
+ (let ((display-id (server-client-get client 'display)))
(setq dontkill t)
- (when tty (resume-tty tty))))
+ (when (eq (display-live-p display-id) t)
+ (resume-tty display-id))))
;; -suspend: 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 (server-client-get client 'tty)))
+ (let ((display-id (server-client-get client 'display)))
(setq dontkill t)
- (when tty (suspend-tty tty))))
+ (when (eq (display-live-p display-id) t)
+ (suspend-tty display-id))))
;; -ignore COMMENT: Noop; useful for debugging emacsclient.
;; (The given comment appears in the server log.)
@@ -528,7 +524,8 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(setq frame (make-frame-on-tty tty type (list (cons 'client proc))))
(select-frame frame)
(server-client-set client 'frame frame)
- (server-client-set client 'tty (frame-tty-name frame))
+ (server-client-set client 'tty (display-name frame))
+ (server-client-set client 'display (frame-display frame))
;; Set up display for the remote locale.
(configure-display-for-locale)
;; Reply with our pid.
@@ -912,7 +909,6 @@ If FRAME is nil or missing, then the selected frame is used."
(defun server-unload-hook ()
(server-start t)
- (remove-hook 'delete-tty-after-functions 'server-handle-delete-tty)
(remove-hook 'suspend-tty-functions 'server-handle-suspend-tty)
(remove-hook 'delete-frame-functions 'server-handle-delete-frame)
(remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
diff --git a/lisp/talk.el b/lisp/talk.el
index 6d542b0f99b..56549431aab 100644
--- a/lisp/talk.el
+++ b/lisp/talk.el
@@ -49,41 +49,39 @@ Each element has the form (DISPLAY FRAME BUFFER).")
(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"))))
+ (let ((type (frame-live-p (selected-frame)))
+ (display (frame-display (selected-frame))))
+ (cond
+ ((eq type t)
+ (talk-add-display (selected-frame)))
+ ((eq type 'x)
+ (talk-add-display (frame-display (selected-frame))))
+ (t
+ (error "Unknown frame type"))))
(talk-update-buffers))
-(defun talk-add-display (display)
- (let* ((elt (assoc display talk-display-alist))
- (name (concat "*talk-" display "*"))
- buffer frame)
- (if (not (and elt (frame-live-p (setq frame (nth 1 elt)))))
- (setq frame (make-frame-on-display display (list (cons 'name name)))))
- (if (not (and elt (buffer-name (get-buffer (setq buffer (nth 2 elt))))))
- (setq buffer (get-buffer-create name)))
- (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) "*"))
+(defun talk-add-display (frame)
+ (let* ((display (if (frame-live-p frame)
+ (frame-display frame)
+ frame))
+ (elt (assoc display talk-display-alist))
+ (name (concat "*talk-" (display-name display) "*"))
buffer)
+ (unless (frame-live-p frame)
+ (setq frame (make-frame-on-display display (list (cons 'name name)))))
+ (if (and elt (frame-live-p (nth 1 elt)))
+ (setq frame (nth 1 elt)))
(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)
+ (add-to-list 'delete-frame-functions 'talk-handle-delete-frame)
(setq talk-display-alist
- (cons (list (frame-tty-name frame) frame buffer) (delq elt talk-display-alist)))))
+ (cons (list display 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-handle-delete-frame (frame)
+ (dolist (d talk-display-alist)
+ (when (eq (nth 1 d) frame)
+ (setq talk-display-alist (delq d talk-display-alist))
+ (talk-update-buffers))))
(defun talk-disconnect ()
"Disconnect this display from the Emacs talk group."
diff --git a/src/dispextern.h b/src/dispextern.h
index f48cdbbe273..c438ad0f9dd 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2859,8 +2859,9 @@ 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_ ((struct tty_display_info *, int));
+extern struct display *get_display P_ ((Lisp_Object display));
extern struct display *get_named_tty_display P_ ((char *));
-extern Lisp_Object Fframe_tty_type P_ ((Lisp_Object));
+EXFUN (Fdisplay_tty_type, 1);
extern struct display *init_initial_display P_ ((void));
extern struct display *term_init P_ ((char *, char *, int));
extern void delete_tty P_ ((struct display *));
diff --git a/src/dispnew.c b/src/dispnew.c
index 8d64a954619..b519dfa0752 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -6757,7 +6757,7 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\
/* Update frame parameters to reflect the new type. */
Fmodify_frame_parameters
(selected_frame, Fcons (Fcons (Qtty_type,
- Fframe_tty_type (selected_frame)), Qnil));
+ Fdisplay_tty_type (selected_frame)), Qnil));
}
{
diff --git a/src/frame.c b/src/frame.c
index 7917b9ecdd6..41ee5a64bd5 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -76,6 +76,8 @@ Lisp_Object Qinhibit_default_face_x_resources;
Lisp_Object Qx_frame_parameter;
Lisp_Object Qx_resource_name;
+Lisp_Object Qdisplay_id;
+Lisp_Object Qdisplay_live_p;
/* Frame parameters (set or reported). */
@@ -558,19 +560,12 @@ make_initial_frame (void)
struct frame *
-make_terminal_frame (tty_name, tty_type)
- char *tty_name;
- char *tty_type;
+make_terminal_frame (struct display *display)
{
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);
@@ -673,6 +668,7 @@ affects all frames on the same terminal device. */)
Lisp_Object parms;
{
struct frame *f;
+ struct display *d = NULL;
Lisp_Object frame, tem;
struct frame *sf = SELECTED_FRAME ();
@@ -692,53 +688,70 @@ affects all frames on the same terminal device. */)
#endif
#endif
#endif /* not MSDOS */
+
+ {
+ Lisp_Object display_device;
- {
- 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))
+ display_device = Fassq (Qdisplay_id, parms);
+ if (!NILP (display_device))
{
- type = (char *) alloca (SBYTES (tty_type) + 1);
- strncpy (type, SDATA (tty_type), SBYTES (tty_type));
- type[SBYTES (tty_type)] = 0;
+ display_device = XCDR (display_device);
+ CHECK_NUMBER (display_device);
+ d = get_display (XINT (display_device));
+ if (!d)
+ wrong_type_argument (Qdisplay_live_p, display_device);
}
-
- f = make_terminal_frame (name, type);
}
+
+ if (!d)
+ {
+ 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;
+ }
+
+ d = term_init (name, type, 0); /* Errors are not fatal. */
+ }
+
+ f = make_terminal_frame (d);
{
int width, height;
@@ -1046,6 +1059,31 @@ If FRAME is the selected frame, this makes WINDOW the selected window. */)
return XFRAME (frame)->selected_window = window;
}
+
+DEFUN ("frame-display", Fframe_display, Sframe_display, 0, 1, 0,
+ doc: /* Return the display device that FRAME is displayed on.
+If FRAME is nil, the selected frame is used.
+
+The display device is represented by its integer identifier. */)
+ (frame)
+ Lisp_Object frame;
+{
+ struct display *d;
+
+ if (NILP (frame))
+ frame = selected_frame;
+
+ CHECK_LIVE_FRAME (frame);
+
+ d = get_display (frame);
+
+ if (!d)
+ return Qnil;
+ else
+ return make_number (d->id);
+}
+
+
DEFUN ("frame-list", Fframe_list, Sframe_list,
0, 0, 0,
doc: /* Return a list of all frames. */)
@@ -1387,6 +1425,10 @@ The functions are run with one arg, the frame to be deleted. */)
Frun_hook_with_args (2, args);
}
+ /* The hook may sometimes (indirectly) cause the frame to be deleted. */
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+
minibuffer_selected = EQ (minibuf_window, selected_window);
/* Don't let the frame remain selected. */
@@ -4154,6 +4196,11 @@ syms_of_frame ()
Qx_frame_parameter = intern ("x-frame-parameter");
staticpro (&Qx_frame_parameter);
+ Qdisplay_id = intern ("display-id");
+ staticpro (&Qdisplay_id);
+ Qdisplay_live_p = intern ("display-live-p");
+ staticpro (&Qdisplay_live_p);
+
{
int i;
@@ -4286,6 +4333,7 @@ This variable is local to the current terminal and cannot be buffer-local. */);
defsubr (&Sframe_first_window);
defsubr (&Sframe_selected_window);
defsubr (&Sset_frame_selected_window);
+ defsubr (&Sframe_display);
defsubr (&Sframe_list);
defsubr (&Snext_frame);
defsubr (&Sprevious_frame);
diff --git a/src/frame.h b/src/frame.h
index 2d87913309f..044aa6e90f0 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -775,11 +775,12 @@ typedef struct frame *FRAME_PTR;
extern Lisp_Object Qframep, Qframe_live_p;
extern Lisp_Object Qtty, Qtty_type;
+extern Lisp_Object Qdisplay_id, Qdisplay_live_p;
extern struct frame *last_nonminibuf_frame;
extern struct frame *make_initial_frame P_ ((void));
-extern struct frame *make_terminal_frame P_ ((char *, char *));
+extern struct frame *make_terminal_frame P_ ((struct display *));
extern struct frame *make_frame P_ ((int));
#ifdef HAVE_WINDOW_SYSTEM
extern struct frame *make_minibuffer_frame P_ ((void));
diff --git a/src/keyboard.c b/src/keyboard.c
index e9c9edbd239..0ac88f80805 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -10317,7 +10317,7 @@ interrupt_signal (signalnum) /* If we don't have an argument, */
signal (SIGQUIT, interrupt_signal);
#endif /* USG */
- /* See if we have a display on our controlling terminal. */
+ /* See if we have an active display on our controlling terminal. */
display = get_named_tty_display (NULL);
if (!display)
{
diff --git a/src/term.c b/src/term.c
index ae659e422ff..1628de01045 100644
--- a/src/term.c
+++ b/src/term.c
@@ -85,6 +85,8 @@ static void turn_off_face P_ ((struct frame *, int face_id));
static void tty_show_cursor P_ ((struct tty_display_info *));
static void tty_hide_cursor P_ ((struct tty_display_info *));
+static struct display *get_tty_display (Lisp_Object display);
+
void delete_initial_display P_ ((struct display *));
void create_tty_output P_ ((struct frame *));
void delete_tty_output P_ ((struct frame *));
@@ -117,9 +119,6 @@ extern Lisp_Object Qspace, QCalign_to, QCwidth;
Lisp_Object Vring_bell_function;
-/* Functions to call after deleting a tty. */
-Lisp_Object Vdelete_tty_after_functions;
-
/* Functions to call after suspending a tty. */
Lisp_Object Vsuspend_tty_functions;
@@ -141,9 +140,6 @@ struct tty_display_info *tty_list;
else. */
int no_redraw_on_reenter;
-Lisp_Object Qframe_tty_name, Qframe_tty_type;
-
-
/* Meaning of bits in no_color_video. Each bit set means that the
corresponding attribute cannot be combined with colors. */
@@ -175,6 +171,9 @@ int max_frame_lines;
should not open a frame on stdout. */
static int no_controlling_tty;
+/* The first unallocated display id. */
+static int next_display_id;
+
/* Provided for lisp packages. */
static int system_uses_terminfo;
@@ -228,10 +227,13 @@ tty_ring_bell (struct frame *f)
{
struct tty_display_info *tty = FRAME_TTY (f);
- OUTPUT (tty, (tty->TS_visible_bell && visible_bell
- ? tty->TS_visible_bell
- : tty->TS_bell));
- fflush (tty->output);
+ if (tty->output)
+ {
+ OUTPUT (tty, (tty->TS_visible_bell && visible_bell
+ ? tty->TS_visible_bell
+ : tty->TS_bell));
+ fflush (tty->output);
+ }
}
/* Set up termcap modes for Emacs. */
@@ -1925,58 +1927,11 @@ tty_capable_p (tty, caps, fg, bg)
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. */
DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
0, 1, 0,
- doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
+ doc: /* Return non-nil if the tty device that DISPLAY uses can display colors. */)
(display)
Lisp_Object display;
{
@@ -1990,7 +1945,7 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
/* Return the number of supported colors. */
DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
Stty_display_color_cells, 0, 1, 0,
- doc: /* Return the number of colors supported by TTY on DISPLAY. */)
+ doc: /* Return the number of colors supported by the tty device that DISPLAY uses. */)
(display)
Lisp_Object display;
{
@@ -2140,8 +2095,62 @@ set_tty_color_mode (f, val)
-/* Return the termcap display with the given name. If NAME is null,
- return the display corresponding to our controlling terminal.
+/* Return the display object specified by DISPLAY. DISPLAY may be a
+ display id, a frame, or nil for the display device of the current
+ frame. */
+
+struct display *
+get_display (Lisp_Object display)
+{
+ if (NILP (display))
+ display = selected_frame;
+
+ if (! INTEGERP (display) && ! FRAMEP (display))
+ return NULL;
+
+ if (INTEGERP (display))
+ {
+ struct display *d;
+
+ for (d = display_list; d; d = d->next_display)
+ {
+ if (d->id == XINT (display))
+ return d;
+ }
+ return NULL;
+ }
+ else if (FRAMEP (display))
+ {
+ return FRAME_DISPLAY (XFRAME (display));
+ }
+ return NULL;
+}
+
+/* Return the tty display object specified by DISPLAY. */
+
+static struct display *
+get_tty_display (Lisp_Object display)
+{
+ struct display *d = get_display (display);
+
+ if (d && d->type != output_termcap)
+ {
+#if 0 /* XXX We need a predicate as the first argument; find one. */
+ wrong_type_argument ("Not a termcap display", display);
+#else /* Until we fix the wrong_type_argument call above, simply throw
+ a dumb error. */
+ error ("DISPLAY is not a termcap display");
+#endif
+ }
+
+ return d;
+}
+
+/* Return the active termcap display that uses the tty device with the
+ given name. If NAME is NULL, return the display corresponding to
+ our controlling terminal.
+
+ This function ignores suspended displays.
Returns NULL if the named terminal device is not opened. */
@@ -2155,7 +2164,8 @@ get_named_tty_display (name)
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))))
+ && !strcmp (d->display_info.tty->name, name)))
+ && DISPLAY_ACTIVE_P (d))
return d;
};
@@ -2164,54 +2174,41 @@ get_named_tty_display (name)
-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;
+DEFUN ("display-name", Fdisplay_name, Sdisplay_name, 0, 1, 0,
+ doc: /* Return the name of the device that DISPLAY uses.
+It is not guaranteed that the returned value is unique among opened displays.
- if (NILP (frame))
- {
- f = XFRAME (selected_frame);
- }
- else
- {
- CHECK_LIVE_FRAME (frame);
- f = XFRAME (frame);
- }
+DISPLAY can be a display, a frame, or nil (meaning the selected
+frame's display). */)
+ (display)
+ Lisp_Object display;
+{
+ struct display *d = get_display (display);
- if (f->output_method != output_termcap)
- wrong_type_argument (Qframe_tty_name, frame);
+ if (!d)
+ wrong_type_argument (Qdisplay_live_p, display);
- if (FRAME_TTY (f)->name)
- return build_string (FRAME_TTY (f)->name);
+ if (d->name)
+ return build_string (d->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);
+DEFUN ("display-tty-type", Fdisplay_tty_type, Sdisplay_tty_type, 0, 1, 0,
+ doc: /* Return the type of the TTY device that DISPLAY uses. */)
+ (display)
+ Lisp_Object display;
+{
+ struct display *d = get_display (display);
- if (FRAME_TTY (f)->type)
- return build_string (FRAME_TTY (f)->type);
+ if (!d)
+ wrong_type_argument (Qdisplay_live_p, display);
+ if (d->type != output_termcap)
+ error ("Display %d is not a termcap display", d->id);
+
+ if (d->display_info.tty->type)
+ return build_string (d->display_info.tty->type);
else
return Qnil;
}
@@ -2232,7 +2229,8 @@ init_initial_display (void)
initial_display = create_display ();
initial_display->type = output_initial;
-
+ initial_display->name = xstrdup ("initial_display");
+
initial_display->delete_display_hook = &delete_initial_display;
/* All other hooks are NULL. */
@@ -2311,18 +2309,15 @@ term_init (char *name, char *terminal_type, int must_succeed)
maybe_fatal (must_succeed, 0, 0,
"Unknown terminal type",
"Unknown terminal type");
-
+
+ /* If we already have an active display on the given device, use that.
+ If all displays are suspended, create a new one instead. */
+ /* XXX Perhaps this should be made explicit by having term_init
+ always create a new display and separating display and frame
+ creation on Lisp level. */
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;
- }
+ return display;
display = create_display ();
tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
@@ -2410,6 +2405,7 @@ term_init (char *name, char *terminal_type, int must_succeed)
file = fdopen (fd, "w+");
tty->name = xstrdup (name);
+ display->name = xstrdup (name);
tty->input = file;
tty->output = file;
}
@@ -2422,6 +2418,7 @@ term_init (char *name, char *terminal_type, int must_succeed)
error ("There is no controlling terminal any more");
}
tty->name = 0;
+ display->name = xstrdup (ttyname (0));
tty->input = stdin;
tty->output = stdout;
}
@@ -2907,37 +2904,6 @@ fatal (str, arg1, arg2)
-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;
@@ -3038,21 +3004,6 @@ delete_tty (struct display *display)
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);
- }
}
@@ -3118,6 +3069,8 @@ create_display (void)
display->next_display = display_list;
display_list = display;
+ display->id = next_display_id++;
+
display->keyboard_coding =
(struct coding_system *) xmalloc (sizeof (struct coding_system));
display->terminal_coding =
@@ -3157,26 +3110,114 @@ delete_display (struct display *display)
xfree (display->keyboard_coding);
if (display->terminal_coding)
xfree (display->terminal_coding);
-
+ if (display->name)
+ xfree (display->name);
+
bzero (display, sizeof (struct display));
xfree (display);
}
+DEFUN ("delete-display", Fdelete_display, Sdelete_display, 0, 2, 0,
+ doc: /* Delete DISPLAY by deleting all frames on it and closing the device.
+DISPLAY may be a display id, a frame, or nil for the display
+device of the current frame.
+
+Normally, you may not delete a display if all other displays are suspended,
+but if the second argument FORCE is non-nil, you may do so. */)
+ (display, force)
+ Lisp_Object display, force;
+{
+ struct display *d, *p;
+
+ d = get_display (display);
+
+ if (!d)
+ return Qnil;
+
+ p = display_list;
+ while (p && (p == d || !DISPLAY_ACTIVE_P (p)))
+ p = p->next_display;
+
+ if (NILP (force) && !p)
+ error ("Attempt to delete the sole active display");
+
+ if (d->delete_display_hook)
+ (*d->delete_display_hook) (d);
+ else
+ delete_display (d);
+
+ return Qnil;
+}
+
+DEFUN ("display-live-p", Fdisplay_live_p, Sdisplay_live_p, 1, 1, 0,
+ doc: /* Return non-nil if OBJECT is a display which has not been deleted.
+Value is nil if OBJECT is not a live display.
+If object is a live display, the return value indicates what sort of
+output device it uses. See the documentation of `framep' for possible
+return values.
+
+Displays are represented by their integer identifiers. */)
+ (object)
+ Lisp_Object object;
+{
+ struct display *d;
+
+ if (!INTEGERP (object))
+ return Qnil;
+
+ d = get_display (object);
+
+ if (!d)
+ return Qnil;
+
+ switch (d->type)
+ {
+ case output_initial: /* The initial frame is like a termcap frame. */
+ case output_termcap:
+ return Qt;
+ case output_x_window:
+ return Qx;
+ case output_w32:
+ return Qw32;
+ case output_msdos_raw:
+ return Qpc;
+ case output_mac:
+ return Qmac;
+ default:
+ abort ();
+ }
+}
+
+DEFUN ("display-list", Fdisplay_list, Sdisplay_list, 0, 0, 0,
+ doc: /* Return a list of all displays.
+Displays are represented by their integer identifiers. */)
+ ()
+{
+ Lisp_Object displays = Qnil;
+ struct display *d;
+
+ for (d = display_list; d; d = d->next_display)
+ displays = Fcons (make_number (d->id), displays);
+
+ return displays;
+}
+
+
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
+The terminal is restored to its default state, and Emacs ceases 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.
+TTY may be a display id, 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.
+device. The functions are run with one arg, the id of the suspended
+display device.
`suspend-tty' does nothing if it is called on an already suspended
device.
@@ -3215,12 +3256,7 @@ it. */)
{
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;
+ args[1] = make_number (d->id);
Frun_hook_with_args (2, args);
}
}
@@ -3231,17 +3267,21 @@ it. */)
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.
+The terminal is opened and reinitialized. Frames that are on the
+suspended display are revived.
+
+It is an error to resume a display while another display is active on
+the same device.
This function runs `resume-tty-functions' after resuming the device.
-The functions are run with one arg, the name of the terminal device.
+The functions are run with one arg, the id of the resumed display
+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 may be a display id, a frame, or nil for the display device of the
+currently selected frame. */)
(tty)
Lisp_Object tty;
{
@@ -3253,6 +3293,9 @@ device of the currently selected frame. */)
if (!d->display_info.tty->input)
{
+ if (get_named_tty_display (d->display_info.tty->name))
+ error ("Cannot resume display while another display is active on the same device");
+
fd = emacs_open (d->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
/* XXX What if open fails? */
@@ -3274,12 +3317,7 @@ device of the currently selected frame. */)
{
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;
+ args[1] = make_number (d->id);
Frun_hook_with_args (2, args);
}
}
@@ -3305,13 +3343,6 @@ 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.
@@ -3325,17 +3356,13 @@ 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 (&Sdisplay_name);
+ defsubr (&Sdisplay_tty_type);
+ defsubr (&Sdelete_display);
+ defsubr (&Sdisplay_live_p);
+ defsubr (&Sdisplay_list);
defsubr (&Ssuspend_tty);
defsubr (&Sresume_tty);
diff --git a/src/termhooks.h b/src/termhooks.h
index 227ec21372e..9aedede55bf 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -282,12 +282,18 @@ struct display
/* Chain of all displays. */
struct display *next_display;
+ /* Unique id for this display. */
+ int id;
+
/* The number of frames that are on this display. */
int reference_count;
/* The type of the display. */
enum output_method type;
+ /* The name of the display device. Do not use this to identify the display. */
+ char *name;
+
/* Display-type dependent data shared amongst all frames on this display. */
union display_info
{
@@ -518,8 +524,8 @@ struct display
/* 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.
+ If this is NULL, then the generic delete_display is called
+ instead. Otherwise the hook must call delete_display itself.
The hook must check for and close any live frames that are still
on the display. Fdelete_frame ensures that there are no live
@@ -563,6 +569,9 @@ extern struct display *display_list;
#define FRAME_WINDOW_P(f) (0)
#endif
+/* Return true if the display is not suspended. */
+#define DISPLAY_ACTIVE_P(d) ((d)->type != output_termcap || (d)->display_info.tty->input)
+
extern struct display *create_display P_ ((void));
extern void delete_display P_ ((struct display *));
diff --git a/src/xfns.c b/src/xfns.c
index 56593453b2c..dbb7548650c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -257,6 +257,17 @@ check_x_display_info (frame)
else
error ("X windows are not in use or not initialized");
}
+ else if (INTEGERP (frame))
+ {
+ struct display *d = get_display (XINT (frame));
+
+ if (!d)
+ wrong_type_argument (Qdisplay_live_p, frame);
+ if (d->type != output_x_window)
+ error ("Display %d is not an X display", XINT (frame));
+
+ dpyinfo = d->display_info.x;
+ }
else if (STRINGP (frame))
dpyinfo = x_display_info_for_name (frame);
else
@@ -2849,7 +2860,9 @@ This function is an internal primitive--use `make-frame' instead. */)
until we know if this frame has a specified name. */
Vx_resource_name = Vinvocation_name;
- display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
+ display = x_get_arg (dpyinfo, parms, Qdisplay_id, 0, 0, RES_TYPE_NUMBER);
+ if (NILP (display))
+ display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING);
if (EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_x_display_info (display);
diff --git a/src/xterm.c b/src/xterm.c
index c17146bde1d..c8b5921a3b5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -10336,6 +10336,11 @@ x_term_init (display_name, xrm_option, resource_name)
dpyinfo->display = dpy;
+ /* Set the name of the display. */
+ display->name = (char *) xmalloc (SBYTES (display_name) + 1);
+ strncpy (display->name, SDATA (display_name), SBYTES (display_name));
+ display->name[SBYTES (display_name)] = 0;
+
#if 0
XSetAfterFunction (x_current_display, x_trace_wire);
#endif /* ! 0 */
@@ -10709,10 +10714,11 @@ x_delete_display (dpyinfo)
xfree (dpyinfo->font_table[i].name);
}
- if (dpyinfo->font_table->font_encoder)
+ if (dpyinfo->font_table && dpyinfo->font_table->font_encoder)
xfree (dpyinfo->font_table->font_encoder);
- xfree (dpyinfo->font_table);
+ if (dpyinfo->font_table)
+ xfree (dpyinfo->font_table);
xfree (dpyinfo->x_id_name);
xfree (dpyinfo->color_cells);
xfree (dpyinfo);