register struct frame *f;
Lisp_Object frame;
char name[20];
-
+
+ if (terminal->deleted)
+ error ("Terminal is being deleted, can't create new frames on it");
+
f = make_frame (1);
XSETFRAME (frame, f);
struct tty_display_info *tty = terminal->display_info.tty;
int nread = 0;
+ if (terminal->deleted) /* Don't read from a deleted terminal. */
+ return;
+
if (terminal->type != output_termcap)
abort ();
return t;
}
-/* Return the active termcap device that uses the tty device with the
- given name. If NAME is NULL, return the device corresponding to
- our controlling terminal.
+/* Return an active termcap device that uses the tty device with the
+ given name.
This function ignores suspended devices.
{
struct terminal *t;
- for (t = terminal_list; t; t = t->next_terminal) {
- if (t->type == output_termcap
- && ((t->display_info.tty->name == 0 && name == 0)
- || (name && t->display_info.tty->name
- && !strcmp (t->display_info.tty->name, name)))
- && TERMINAL_ACTIVE_P (t))
- return t;
- };
+ if (!name)
+ abort ();
+
+ for (t = terminal_list; t; t = t->next_terminal)
+ {
+ if (t->type == output_termcap
+ && !strcmp (t->display_info.tty->name, name)
+ && TERMINAL_ACTIVE_P (t))
+ return t;
+ }
return 0;
}
\f
DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
doc: /* Return the type of the tty device that TERMINAL uses.
+Returns nil if TERMINAL is not on a tty device.
TERMINAL can be a terminal id, a frame or nil (meaning the selected
frame's terminal). */)
struct terminal *t = get_terminal (terminal, 1);
if (t->type != output_termcap)
- error ("Terminal %d is not a termcap terminal", t->id);
-
+ return Qnil;
+
if (t->display_info.tty->type)
return build_string (t->display_info.tty->type);
else
/* 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.
+ If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
Otherwise NAME should be a path to the tty device file,
e.g. "/dev/pts/7".
"Unknown terminal type",
"Unknown terminal type");
+ if (name == NULL)
+ name = "/dev/tty";
+ if (!strcmp (name, "/dev/tty"))
+ ctty = 1;
+
/* If we already have a terminal on the given device, use that. If
all such terminals are suspended, create a new one instead. */
/* XXX Perhaps this should be made explicit by having init_tty
set_tty_hooks (terminal);
- if (name == NULL)
- name = "/dev/tty";
- if (!strcmp (name, "/dev/tty"))
- ctty = 1;
-
{
int fd;
FILE *file;
{
struct tty_display_info *tty;
Lisp_Object tail, frame;
- char *tty_name;
int last_terminal;
- /* Protect against recursive calls. Fdelete_frame calls us back
- when we delete our last frame. */
+ /* Protect against recursive calls. Fdelete_frame in
+ delete_terminal calls us back when it deletes our last frame. */
if (terminal->deleted)
return;
tty->next = 0;
}
- /* We must not throw any errors below this line. */
- terminal->deleted = 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 device, so this call needs to be
before delete_terminal. */
reset_sys_modes (tty);
delete_terminal (terminal);
- tty_name = tty->name;
+ if (tty->name)
+ xfree (tty->name);
+
if (tty->type)
xfree (tty->type);
bzero (tty, sizeof (struct tty_display_info));
xfree (tty);
- deleting_tty = 0;
}
\f
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.
+The functions are run with one argument, the terminal id 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.
+The functions are run with one argument, the terminal id that was revived.
See `resume-tty'. */);
Vresume_tty_functions = Qnil;
/* The type of the terminal device. */
enum output_method type;
- /* The name of the terminal device. Do not use this to identify the device. */
+ /* The name of the terminal device. Do not use this to uniquely
+ identify a terminal; the same device may be opened multiple
+ times. */
char *name;
#ifdef MULTI_KBOARD
}
-/* Remove a terminal from the terminal list and free its memory. */
+/* Low-level function to close all frames on a terminal, remove it
+ from the terminal list and free its memory. */
void
delete_terminal (struct terminal *terminal)
struct terminal **tp;
Lisp_Object tail, frame;
- /* Protect against recursive calls. Fdelete_frame calls us back
- when we delete our last frame. */
+ /* Protect against recursive calls. Fdelete_frame calls the
+ delete_terminal_hook when we delete our last frame. */
if (terminal->deleted)
return;
terminal->deleted = 1;
- /* Check for and close live frames that are still on this
- terminal. */
+ /* Check for live frames that are still on this terminal. */
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
kb = &the_only_kboard;
#endif
+ if (dpyinfo->terminal->deleted)
+ error ("Terminal is being deleted, can't create new frames on it");
+
name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
if (!STRINGP (name)
&& ! EQ (name, Qunbound)
check_x ();
+ if (dpyinfo->terminal->deleted)
+ error ("Terminal is being deleted, can't create new frames on it");
+
parms = Fcopy_alist (parms);
/* Get the name of the frame to use for resource lookup. */
++handling_signal;
+#ifdef HAVE_X_SM
+ /* Only check session manager input for the primary display. */
+ if (terminal->id == 1 && x_session_have_connection ())
+ {
+ struct input_event inev;
+ BLOCK_INPUT;
+ /* We don't need to EVENT_INIT (inev) here, as
+ x_session_check_input copies an entire input_event. */
+ if (x_session_check_input (&inev))
+ {
+ kbd_buffer_store_event_hold (&inev, hold_quit);
+ count++;
+ }
+ UNBLOCK_INPUT;
+ }
+#endif
+
+ /* For debugging, this gives a way to fake an I/O error. */
+ if (terminal->display_info.x == XTread_socket_fake_io_error)
+ {
+ XTread_socket_fake_io_error = 0;
+ x_io_error_quitter (dpyinfo->display);
+ }
+
+#if 0 /* This loop is a noop now. */
/* Find the display we are supposed to read input for.
It's the one communicating on descriptor SD. */
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
#endif /* HAVE_SELECT */
#endif /* SIGIO */
#endif
-
- /* For debugging, this gives a way to fake an I/O error. */
- if (dpyinfo == XTread_socket_fake_io_error)
- {
- XTread_socket_fake_io_error = 0;
- x_io_error_quitter (dpyinfo->display);
- }
-
-#ifdef HAVE_X_SM
- /* Only check session manager input for the primary display. */
- if (terminal->id == 1 && x_session_have_connection ())
- {
- struct input_event inev;
- BLOCK_INPUT;
- /* We don't need to EVENT_INIT (inev) here, as
- x_session_check_input copies an entire input_event. */
- if (x_session_check_input (&inev))
- {
- kbd_buffer_store_event_hold (&inev, hold_quit);
- count++;
- }
- UNBLOCK_INPUT;
- }
+ }
#endif
#ifndef USE_GTK
- while (XPending (dpyinfo->display))
- {
- int finish;
+ while (XPending (terminal->display_info.x->display))
+ {
+ int finish;
- XNextEvent (dpyinfo->display, &event);
+ XNextEvent (terminal->display_info.x->display, &event);
#ifdef HAVE_X_I18N
- /* Filter events for the current X input method. */
- if (x_filter_event (dpyinfo, &event))
- break;
+ /* Filter events for the current X input method. */
+ if (x_filter_event (terminal->display_info.x, &event))
+ break;
#endif
- event_found = 1;
+ event_found = 1;
- count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
+ count += handle_one_xevent (terminal->display_info.x,
+ &event, &finish, hold_quit);
- if (finish == X_EVENT_GOTO_OUT)
- goto out;
- }
-#endif /* not USE_GTK */
+ if (finish == X_EVENT_GOTO_OUT)
+ goto out;
}
-#ifdef USE_GTK
+#else /* USE_GTK */
/* For GTK we must use the GTK event loop. But XEvents gets passed
to our filter function above, and then to the big event switch.
return dpyinfo;
}
\f
-/* Get rid of display DPYINFO, assuming all frames are already gone,
+/* Get rid of display DPYINFO, deleting all frames on it,
and without sending any more commands to the X server. */
void
int i;
struct terminal *t;
- /* Delete the generic struct terminal for this X display. */
+ /* Close all frames and delete the generic struct terminal for this
+ X display. */
for (t = terminal_list; t; t = t->next_terminal)
if (t->type == output_x_window && t->display_info.x == dpyinfo)
{
- /* Close X session management when we close its display. */
+ /* Close X session management when we close its display. */
if (t->id == 1 && x_session_have_connection ())
x_session_close();
{
struct x_display_info *dpyinfo = terminal->display_info.x;
int i;
- Lisp_Object tail, frame;
- /* Protect against recursive calls. Fdelete_frame calls us back
- when we delete our last frame. */
+ /* Protect against recursive calls. Fdelete_frame in
+ delete_terminal calls us back when it deletes our last frame. */
if (terminal->deleted)
return;
- terminal->deleted = 1;
-
- /* Check for and close live frames that are still on this
- terminal. */
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- if (FRAME_LIVE_P (f) && f->terminal == terminal)
- {
- Fdelete_frame (frame, Qt);
- }
- }
BLOCK_INPUT;
/* Free the fonts in the font table. */
/* Chain of all x_display_info structures. */
struct x_display_info *next;
+ /* The generic display parameters corresponding to this X display. */
+ struct terminal *terminal;
+
/* Connection number (normally a file descriptor number). */
int connection;
X_WMTYPE_A,
X_WMTYPE_B
} wm_type;
-
- /* The generic display parameters corresponding to this X display. */
- struct terminal *terminal;
};
#ifdef HAVE_X_I18N