Mercurial > emacs
changeset 9704:39b34bbe59c9
(x_catch_errors, x_check_errors, x_had_errors_p)
(x_uncatch_errors): Make the argument a display, not a frame.
(XTread_socket_fake_io_error): New variable.
(XTread_socket): Obey XTread_socket_fake_io_error.
(x_initialize): Init x_noop_count, x_focus_frame
and x_highlight_frame here.
(x_term_init): Not here.
(x_term_init): Open the connection first thing;
if that fails, don't allocate dpyinfo.
(x_delete_display): New function.
(x_connection_closed): New args dpyinfo and error_message.
Delete all frames on the dead display
and all frames using them for minibuffers.
Call x_delete_display.
Maybe signal a Lisp error.
(x_term_init): Don't report error here--just return 0.
(x_scroll_bar_report_motion): Store proper value in
*bar_window (the Emacs window, not the X window number).
(x_scroll_bar_report_motion): Don't clear *fp.
(x_wm_set_icon_pixmap): Use x_bitmap_pixmap.
(show_mouse_face): New arg dpyinfo. All callers changed.
(clear_mouse_face): New arg dpyinfo. All callers changed.
(scratch_cursor_gc): Variable deleted.
(dumpglyphs): Use scratch_cursor_gc in x_display_info.
(syms_of_xterm): Don't staticpro mouse_face_window.
(expose_all_windows, expose_all_icons): Variables deleted.
(BLOCK_INPUT_mask): Variable deleted.
(x_term_init): Set up x_id_name field.
(x_id_name): Variable deleted.
(x_font_table, x_font_table_size, x_n_fonts): Vars deleted.
(x_new_font): Use new fields.
(warp_mouse_on_deiconify): Unused variable deleted.
(x_term_init): Set up dpyinfo->xrdb.
Set up dpyinfo->vertical_scroll_bar_cursor.
(x_scroll_bar_create): Use vertical_scroll_bar_cursor slot.
(x_vertical_scroll_bar_cursor): Variable deleted.
(x_term_init): Really return dpyinfo.
(x_term_init): Call add_keyboard_wait_descriptor,
not change_keyboard_wait_descriptor.
(x_term_init): Pass new arg to init_sigio.
Don't set old_fcntl_owner.
Don't call change_input_fd.
(XTread_socket): Loop over displays and process input from each.
(x_display_name_list): New variable.
(syms_of_xterm): staticpro it.
Don't staticpro slots in the_x_screen.
(x_term_init): Update x_display_name_list along with x_display_list.
Actually malloc the x_display_info.
(the_x_screen): Variable deleted.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Wed, 26 Oct 1994 09:26:40 +0000 |
parents | 85ac0e4030d4 |
children | f7535deb913a |
files | src/xterm.c |
diffstat | 1 files changed, 977 insertions(+), 913 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xterm.c Wed Oct 26 09:19:57 1994 +0000 +++ b/src/xterm.c Wed Oct 26 09:26:40 1994 +0000 @@ -66,6 +66,7 @@ #include <sys/stat.h> #include <sys/param.h> +#include "frame.h" #include "dispextern.h" #include "termhooks.h" #include "termopts.h" @@ -75,7 +76,6 @@ #include "sinkmask.h" #endif /* ! 0 */ #include "gnu.h" -#include "frame.h" #include "disptab.h" #include "buffer.h" #include "window.h" @@ -129,39 +129,18 @@ #define min(a,b) ((a)<(b) ? (a) : (b)) #define max(a,b) ((a)>(b) ? (a) : (b)) -/* Nonzero means we must reprint all windows - because 1) we received an ExposeWindow event - or 2) we received too many ExposeRegion events to record. - - This is never needed under X11. */ -static int expose_all_windows; - -/* Nonzero means we must reprint all icon windows. */ - -static int expose_all_icons; - -#if defined (SIGIO) && defined (FIONREAD) -int BLOCK_INPUT_mask; -#endif /* ! defined (SIGIO) && defined (FIONREAD) */ - /* Stuff for dealing with the main icon title. */ -extern Lisp_Object Vcommand_line_args, Vsystem_name; char *x_id_name; -/* Initial values of argv and argc. */ -extern char **initial_argv; -extern int initial_argc; - -/* For now, we have just one x_display structure since we only support - one X display. */ -static struct x_display_info the_x_screen; - /* This is a chain of structures for all the X displays currently in use. */ struct x_display_info *x_display_list; -/* The cursor to use for vertical scroll bars on x_current_display. */ -static Cursor x_vertical_scroll_bar_cursor; +/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE), + one for each element of x_display_list and in the same order. + NAME is the name of the frame. + FONT-LIST-CACHE records previous values returned by x-list-fonts. */ +Lisp_Object x_display_name_list; /* Frame being updated by update_frame. This is declared in term.c. This is set by update_begin and looked at by all the @@ -193,11 +172,6 @@ minibuffer. */ static struct frame *x_highlight_frame; -/* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero, - mouse is moved to inside of frame when frame is de-iconified. */ - -static int warp_mouse_on_deiconify; - /* During an update, maximum vpos for ins/del line operations to affect. */ static int flexlines; @@ -212,9 +186,6 @@ static int curs_x; static int curs_y; -/* Reusable Graphics Context for drawing a cursor in a non-default face. */ -static GC scratch_cursor_gc; - /* Mouse movement. In order to avoid asking for motion events and then throwing most @@ -256,28 +227,6 @@ it's somewhat accurate. */ static Time last_mouse_movement_time; -/* These variables describe the range of text currently shown - in its mouse-face, together with the window they apply to. - As long as the mouse stays within this range, we need not - redraw anything on its account. */ -static int mouse_face_beg_row, mouse_face_beg_col; -static int mouse_face_end_row, mouse_face_end_col; -static int mouse_face_past_end; -static Lisp_Object mouse_face_window; -static int mouse_face_face_id; - -/* 1 if a mouse motion event came and we didn't handle it right away because - gc was in progress. */ -static int mouse_face_deferred_gc; - -/* FRAME and X, Y position of mouse when last checked for - highlighting. X and Y can be negative or out of range for the frame. */ -static FRAME_PTR mouse_face_mouse_frame; -static int mouse_face_mouse_x, mouse_face_mouse_y; - -/* Nonzero means defer mouse-motion highlighting. */ -static int mouse_face_defer; - /* Incremented by XTread_socket whenever it really tries to read events. */ #ifdef __STDC__ static int volatile input_signal_count; @@ -285,35 +234,33 @@ static int input_signal_count; #endif +/* Used locally within XTread_socket. */ +static int x_noop_count; + +/* Initial values of argv and argc. */ +extern char **initial_argv; +extern int initial_argc; + +extern Lisp_Object Vcommand_line_args, Vsystem_name; + /* Tells if a window manager is present or not. */ extern Lisp_Object Vx_no_window_manager; -/* Timestamp that we requested selection data was made. */ -extern Time requestor_time; - -/* ID of the window requesting selection data. */ -extern Window requestor_window; - /* Nonzero enables some debugging for the X interface code. */ extern int _Xdebug; extern Lisp_Object Qface, Qmouse_face; -static int x_noop_count; - extern int errno; /* A mask of extra modifier bits to put into every keyboard char. */ extern int extra_keyboard_modifiers; -extern Display *XOpenDisplay (); -extern Window XCreateWindow (); - -extern Cursor XCreateCursor (); -extern XFontStruct *XOpenFont (); extern XrmDatabase x_load_resources (); +void x_delete_display (); + static void flashback (); static void redraw_previous_char (); static void redraw_following_char (); @@ -325,9 +272,9 @@ static void show_mouse_face (); static void do_line_dance (); -void dumpborder (); static int XTcursor_to (); static int XTclear_end_of_line (); +static int x_io_error_quitter (); /* Return the struct x_display_info corresponding to DPY. */ @@ -353,8 +300,6 @@ should never be called except during an update, the only exceptions being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */ -extern int mouse_track_top, mouse_track_left, mouse_track_width; - static XTupdate_begin (f) struct frame *f; @@ -369,14 +314,14 @@ BLOCK_INPUT; - if (f == mouse_face_mouse_frame) + if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) { /* Don't do highlighting for mouse motion during the update. */ - mouse_face_defer = 1; - if (!NILP (mouse_face_window)) + FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1; + if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window)) { int firstline, lastline, i; - struct window *w = XWINDOW (mouse_face_window); + struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window); /* Find the first, and the last+1, lines affected by redisplay. */ for (firstline = 0; firstline < f->height; firstline++) @@ -397,7 +342,7 @@ if (! (firstline > (XFASTINT (w->top) + window_internal_height (w)) || lastline < XFASTINT (w->top))) /* Otherwise turn off the mouse highlight now. */ - clear_mouse_face (); + clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); } } @@ -415,8 +360,8 @@ do_line_dance (); x_display_cursor (f, 1); - if (f == mouse_face_mouse_frame) - mouse_face_defer = 0; + if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) + FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0; #if 0 /* This fails in the case of having updated only the echo area if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS @@ -424,8 +369,9 @@ have no relation to the contents of the window-buffer. I don't know a clean way to check for that case. window_end_valid isn't set up yet. */ - if (f == mouse_face_mouse_frame) - note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y); + if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) + note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x, + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y); #endif XFlush (FRAME_X_DISPLAY (f)); @@ -438,11 +384,13 @@ XTframe_up_to_date (f) FRAME_PTR f; { - if (mouse_face_deferred_gc || f == mouse_face_mouse_frame) + if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc + || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) { - note_mouse_highlight (mouse_face_mouse_frame, - mouse_face_mouse_x, mouse_face_mouse_y); - mouse_face_deferred_gc = 0; + note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame, + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x, + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y); + FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0; } } @@ -583,7 +531,7 @@ /* HL = 3 means use a mouse face previously chosen. */ if (hl == 3) - cf = mouse_face_face_id; + cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id; /* First look at the face of the text itself. */ if (cf != 0) @@ -658,12 +606,14 @@ xgcv.font = face->font->fid; xgcv.graphics_exposures = 0; mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; - if (scratch_cursor_gc) - XChangeGC (FRAME_X_DISPLAY (f), scratch_cursor_gc, mask, &xgcv); + if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc) + XChangeGC (FRAME_X_DISPLAY (f), + FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc, + mask, &xgcv); else - scratch_cursor_gc + FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv); - gc = scratch_cursor_gc; + gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc; #if 0 /* If this code is restored, it must also reset to the default stipple if necessary. */ @@ -1241,6 +1191,11 @@ flexlines = n; } +/* These variables need not be per frame + because redisplay is done on a frame-by-frame basis + and the line dance for one frame is finished before + anything is done for anoter frame. */ + /* Array of line numbers from cached insert/delete operations. line_dance[i] is the old position of the line that we want to move to line i, or -1 if we want a blank line there. */ @@ -1896,16 +1851,16 @@ if (disable_mouse_highlight) return; - mouse_face_mouse_x = x; - mouse_face_mouse_y = y; - mouse_face_mouse_frame = f; - - if (mouse_face_defer) + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x; + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y; + FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f; + + if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer) return; if (gc_in_progress) { - mouse_face_deferred_gc = 1; + FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1; return; } @@ -1918,8 +1873,8 @@ w = XWINDOW (window); /* If we were displaying active text in another window, clear that. */ - if (! EQ (window, mouse_face_window)) - clear_mouse_face (); + if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)) + clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); /* Are we in a window whose display is up to date? And verify the buffer's text has not changed. */ @@ -1938,13 +1893,15 @@ pos = ptr[i]; /* Is it outside the displayed active region (if any)? */ if (pos <= 0) - clear_mouse_face (); - else if (! (EQ (window, mouse_face_window) - && row >= mouse_face_beg_row - && row <= mouse_face_end_row - && (row > mouse_face_beg_row || column >= mouse_face_beg_col) - && (row < mouse_face_end_row || column < mouse_face_end_col - || mouse_face_past_end))) + clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); + else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window) + && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col) + && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col + || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end))) { Lisp_Object mouse_face, overlay, position; Lisp_Object *overlay_vec; @@ -1966,7 +1923,7 @@ ZV = Z; /* Yes. Clear the display of the old active region, if any. */ - clear_mouse_face (); + clear_mouse_face (FRAME_X_DISPLAY_INFO (f)); /* Is this char mouse-active? */ XSETINT (position, pos); @@ -2007,17 +1964,20 @@ before = Foverlay_start (overlay); after = Foverlay_end (overlay); /* Record this as the current active region. */ - fast_find_position (window, before, &mouse_face_beg_col, - &mouse_face_beg_row); - mouse_face_past_end - = !fast_find_position (window, after, &mouse_face_end_col, - &mouse_face_end_row); - mouse_face_window = window; - mouse_face_face_id = compute_char_face (f, w, pos, 0, 0, - &ignore, pos + 1, 1); + fast_find_position (window, before, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row); + FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end + = !fast_find_position (window, after, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row); + FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window; + FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id + = compute_char_face (f, w, pos, 0, 0, + &ignore, pos + 1, 1); /* Display it as active. */ - show_mouse_face (1); + show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1); } /* Handle the text property case. */ else if (! NILP (mouse_face)) @@ -2038,18 +1998,20 @@ = Fnext_single_property_change (position, Qmouse_face, w->buffer, end); /* Record this as the current active region. */ - fast_find_position (window, before, &mouse_face_beg_col, - &mouse_face_beg_row); - mouse_face_past_end - = !fast_find_position (window, after, &mouse_face_end_col, - &mouse_face_end_row); - mouse_face_window = window; - mouse_face_face_id + fast_find_position (window, before, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row); + FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end + = !fast_find_position (window, after, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col, + &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row); + FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window; + FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id = compute_char_face (f, w, pos, 0, 0, &ignore, pos + 1, 1); /* Display it as active. */ - show_mouse_face (1); + show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1); } BEGV = obegv; ZV = ozv; @@ -2122,10 +2084,11 @@ in its mouse-face if HL > 0, in its normal face if HL = 0. */ static void -show_mouse_face (hl) +show_mouse_face (dpyinfo, hl) + struct x_display_info *dpyinfo; int hl; { - struct window *w = XWINDOW (mouse_face_window); + struct window *w = XWINDOW (dpyinfo->mouse_face_window); int width = window_internal_width (w); FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); int i; @@ -2139,16 +2102,22 @@ curs_x = f->phys_cursor_x; curs_y = f->phys_cursor_y; - for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++) + for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row; + i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++) { - int column = (i == mouse_face_beg_row ? mouse_face_beg_col : w->left); - int endcolumn = (i == mouse_face_end_row ? mouse_face_end_col : w->left + width); + int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col + : w->left); + int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col + : w->left + width); endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); /* If the cursor's in the text we are about to rewrite, turn the cursor off. */ if (i == curs_y - && curs_x >= mouse_face_beg_col - 1 && curs_x <= mouse_face_end_col) + && curs_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col - 1 + && curs_x <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col) { x_display_cursor (f, 0); cursor_off = 1; @@ -2183,14 +2152,15 @@ Redraw it unhighlighted first. */ static void -clear_mouse_face () +clear_mouse_face (dpyinfo) + struct x_display_info *dpyinfo; { - if (! NILP (mouse_face_window)) - show_mouse_face (0); - - mouse_face_beg_row = mouse_face_beg_col = -1; - mouse_face_end_row = mouse_face_end_col = -1; - mouse_face_window = Qnil; + if (! NILP (dpyinfo->mouse_face_window)) + show_mouse_face (dpyinfo, 0); + + dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; + dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; + dpyinfo->mouse_face_window = Qnil; } static struct scroll_bar *x_window_to_scroll_bar (); @@ -2422,7 +2392,7 @@ a.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask | ExposureMask); - a.cursor = x_vertical_scroll_bar_cursor; + a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; mask = (CWBackPixel | CWEventMask | CWCursor); @@ -2976,7 +2946,7 @@ /* Mouse buttons and modifier keys. */ &dummy_mask)) - *fp = 0; + ; else { int inside_height @@ -2995,7 +2965,7 @@ win_y = top_range; *fp = f; - *bar_window = w; + *bar_window = bar->window; if (! NILP (bar->dragging)) *part = scroll_bar_handle; @@ -3162,6 +3132,10 @@ int temp_index; short temp_buffer[100]; +/* Set this to nonzero to fake an "X I/O error" + on a particular display. */ +struct x_display_info *XTread_socket_fake_io_error; + /* Read events coming from the X server. This routine is called by the SIGIO handler. We return as soon as there are no more events to be read. @@ -3202,635 +3176,586 @@ interrupt_input_pending = 0; BLOCK_INPUT; - /* 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) - if (dpyinfo->connection == sd) - break; - if (dpyinfo == 0) - abort (); - /* So people can tell when we have read the available input. */ input_signal_count++; if (numchars <= 0) abort (); /* Don't think this happens. */ + /* 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) + { +#if 0 /* This ought to be unnecessary; let's verify it. */ #ifdef FIOSNBIO - /* If available, Xlib uses FIOSNBIO to make the socket - non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set, - FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK, - a read returns 0, which Xlib interprets as equivalent to EPIPE. */ - fcntl (sd, F_SETFL, 0); + /* If available, Xlib uses FIOSNBIO to make the socket + non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set, + FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK, + a read returns 0, which Xlib interprets as equivalent to EPIPE. */ + fcntl (dpyinfo->connection, F_SETFL, 0); #endif /* ! defined (FIOSNBIO) */ - +#endif + +#if 0 /* This code can't be made to work, with multiple displays, + and appears not to be used on any system any more. + Also keyboard.c doesn't turn O_NDELAY on and off + for X connections. */ #ifndef SIGIO #ifndef HAVE_SELECT - if (! (fcntl (sd, F_GETFL, 0) & O_NDELAY)) - { - extern int read_alarm_should_throw; - read_alarm_should_throw = 1; - XPeekEvent (dpyinfo->display, &event); - read_alarm_should_throw = 0; - } + if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY)) + { + extern int read_alarm_should_throw; + read_alarm_should_throw = 1; + XPeekEvent (dpyinfo->display, &event); + read_alarm_should_throw = 0; + } #endif /* HAVE_SELECT */ #endif /* SIGIO */ - - while (XPending (dpyinfo->display) != 0) - { - XNextEvent (dpyinfo->display, &event); - event_found = 1; - - switch (event.type) +#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); + } + + while (XPending (dpyinfo->display) != 0) { - case ClientMessage: - { - if (event.xclient.message_type - == dpyinfo->Xatom_wm_protocols - && event.xclient.format == 32) + XNextEvent (dpyinfo->display, &event); + event_found = 1; + + switch (event.type) + { + case ClientMessage: { - if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_take_focus) + if (event.xclient.message_type + == dpyinfo->Xatom_wm_protocols + && event.xclient.format == 32) { - f = x_window_to_frame (event.xclient.window); - /* Since we set WM_TAKE_FOCUS, we must call - XSetInputFocus explicitly. But not if f is null, - since that might be an event for a deleted frame. */ - if (f) - XSetInputFocus (event.xclient.display, - event.xclient.window, - RevertToPointerRoot, - event.xclient.data.l[1]); - /* Not certain about handling scroll bars here */ - } - else if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_save_yourself) - { - /* Save state modify the WM_COMMAND property to - something which can reinstate us. This notifies - the session manager, who's looking for such a - PropertyNotify. Can restart processing when - a keyboard or mouse event arrives. */ - if (numchars > 0) + if (event.xclient.data.l[0] + == dpyinfo->Xatom_wm_take_focus) + { + f = x_window_to_frame (event.xclient.window); + /* Since we set WM_TAKE_FOCUS, we must call + XSetInputFocus explicitly. But not if f is null, + since that might be an event for a deleted frame. */ + if (f) + XSetInputFocus (event.xclient.display, + event.xclient.window, + RevertToPointerRoot, + event.xclient.data.l[1]); + /* Not certain about handling scroll bars here */ + } + else if (event.xclient.data.l[0] + == dpyinfo->Xatom_wm_save_yourself) { - f = x_top_window_to_frame (event.xclient.window); - - /* This is just so we only give real data once - for a single Emacs process. */ - if (f == selected_frame) - XSetCommand (FRAME_X_DISPLAY (f), - event.xclient.window, - initial_argv, initial_argc); - else - XSetCommand (FRAME_X_DISPLAY (f), - event.xclient.window, - 0, 0); + /* Save state modify the WM_COMMAND property to + something which can reinstate us. This notifies + the session manager, who's looking for such a + PropertyNotify. Can restart processing when + a keyboard or mouse event arrives. */ + if (numchars > 0) + { + f = x_top_window_to_frame (event.xclient.window); + + /* This is just so we only give real data once + for a single Emacs process. */ + if (f == selected_frame) + XSetCommand (FRAME_X_DISPLAY (f), + event.xclient.window, + initial_argv, initial_argc); + else + XSetCommand (FRAME_X_DISPLAY (f), + event.xclient.window, + 0, 0); + } + } + else if (event.xclient.data.l[0] + == dpyinfo->Xatom_wm_delete_window) + { + struct frame *f = x_any_window_to_frame (event.xclient.window); + + if (f) + { + if (numchars == 0) + abort (); + + bufp->kind = delete_window_event; + XSETFRAME (bufp->frame_or_window, f); + bufp++; + + count += 1; + numchars -= 1; + } } } - else if (event.xclient.data.l[0] - == dpyinfo->Xatom_wm_delete_window) + else if (event.xclient.message_type + == dpyinfo->Xatom_wm_configure_denied) { - struct frame *f = x_any_window_to_frame (event.xclient.window); + } + else if (event.xclient.message_type + == dpyinfo->Xatom_wm_window_moved) + { + int new_x, new_y; + struct frame *f = x_window_to_frame (event.xclient.window); + + new_x = event.xclient.data.s[0]; + new_y = event.xclient.data.s[1]; if (f) { - if (numchars == 0) - abort (); - - bufp->kind = delete_window_event; - XSETFRAME (bufp->frame_or_window, f); - bufp++; - - count += 1; - numchars -= 1; + f->display.x->left_pos = new_x; + f->display.x->top_pos = new_y; } } - } - else if (event.xclient.message_type - == dpyinfo->Xatom_wm_configure_denied) - { - } - else if (event.xclient.message_type - == dpyinfo->Xatom_wm_window_moved) - { - int new_x, new_y; - struct frame *f = x_window_to_frame (event.xclient.window); - - new_x = event.xclient.data.s[0]; - new_y = event.xclient.data.s[1]; - - if (f) +#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5) + else if (event.xclient.message_type + == dpyinfo->Xatom_editres) { - f->display.x->left_pos = new_x; - f->display.x->top_pos = new_y; + struct frame *f = x_any_window_to_frame (event.xclient.window); + _XEditResCheckMessages (f->display.x->widget, NULL, &event, NULL); } +#endif /* USE_X_TOOLKIT and HAVE_X11R5 */ } -#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5) - else if (event.xclient.message_type - == dpyinfo->Xatom_editres) + break; + + case SelectionNotify: +#ifdef USE_X_TOOLKIT + if (! x_window_to_frame (event.xselection.requestor)) + goto OTHER; +#endif /* not USE_X_TOOLKIT */ + x_handle_selection_notify (&event); + break; + + case SelectionClear: /* Someone has grabbed ownership. */ +#ifdef USE_X_TOOLKIT + if (! x_window_to_frame (event.xselectionclear.window)) + goto OTHER; +#endif /* USE_X_TOOLKIT */ { - struct frame *f = x_any_window_to_frame (event.xclient.window); - _XEditResCheckMessages (f->display.x->widget, NULL, &event, NULL); + XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; + + if (numchars == 0) + abort (); + + bufp->kind = selection_clear_event; + SELECTION_EVENT_DISPLAY (bufp) = eventp->display; + SELECTION_EVENT_SELECTION (bufp) = eventp->selection; + SELECTION_EVENT_TIME (bufp) = eventp->time; + bufp++; + + count += 1; + numchars -= 1; } -#endif /* USE_X_TOOLKIT and HAVE_X11R5 */ - } - break; - - case SelectionNotify: + break; + + case SelectionRequest: /* Someone wants our selection. */ #ifdef USE_X_TOOLKIT - if (! x_window_to_frame (event.xselection.requestor)) - goto OTHER; -#endif /* not USE_X_TOOLKIT */ - x_handle_selection_notify (&event); - break; - - case SelectionClear: /* Someone has grabbed ownership. */ -#ifdef USE_X_TOOLKIT - if (! x_window_to_frame (event.xselectionclear.window)) - goto OTHER; + if (!x_window_to_frame (event.xselectionrequest.owner)) + goto OTHER; #endif /* USE_X_TOOLKIT */ - { - XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; - - if (numchars == 0) - abort (); - - bufp->kind = selection_clear_event; - SELECTION_EVENT_DISPLAY (bufp) = eventp->display; - SELECTION_EVENT_SELECTION (bufp) = eventp->selection; - SELECTION_EVENT_TIME (bufp) = eventp->time; - bufp++; - - count += 1; - numchars -= 1; - } - break; - - case SelectionRequest: /* Someone wants our selection. */ + if (x_queue_selection_requests) + x_queue_event (x_window_to_frame (event.xselectionrequest.owner), + &event); + else + { + XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; + + if (numchars == 0) + abort (); + + bufp->kind = selection_request_event; + SELECTION_EVENT_DISPLAY (bufp) = eventp->display; + SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor; + SELECTION_EVENT_SELECTION (bufp) = eventp->selection; + SELECTION_EVENT_TARGET (bufp) = eventp->target; + SELECTION_EVENT_PROPERTY (bufp) = eventp->property; + SELECTION_EVENT_TIME (bufp) = eventp->time; + bufp++; + + count += 1; + numchars -= 1; + } + break; + + case PropertyNotify: #ifdef USE_X_TOOLKIT - if (!x_window_to_frame (event.xselectionrequest.owner)) - goto OTHER; -#endif /* USE_X_TOOLKIT */ - if (x_queue_selection_requests) - x_queue_event (x_window_to_frame (event.xselectionrequest.owner), - &event); - else - { - XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; - - if (numchars == 0) - abort (); - - bufp->kind = selection_request_event; - SELECTION_EVENT_DISPLAY (bufp) = eventp->display; - SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor; - SELECTION_EVENT_SELECTION (bufp) = eventp->selection; - SELECTION_EVENT_TARGET (bufp) = eventp->target; - SELECTION_EVENT_PROPERTY (bufp) = eventp->property; - SELECTION_EVENT_TIME (bufp) = eventp->time; - bufp++; - - count += 1; - numchars -= 1; - } - break; - - case PropertyNotify: -#ifdef USE_X_TOOLKIT - if (!x_any_window_to_frame (event.xproperty.window)) - goto OTHER; + if (!x_any_window_to_frame (event.xproperty.window)) + goto OTHER; #endif /* not USE_X_TOOLKIT */ - x_handle_property_notify (&event); - break; - - case ReparentNotify: - f = x_top_window_to_frame (event.xreparent.window); - if (f) - { - int x, y; - f->display.x->parent_desc = event.xreparent.parent; - x_real_positions (f, &x, &y); - f->display.x->left_pos = x; - f->display.x->top_pos = y; - } - break; - - case Expose: - f = x_window_to_frame (event.xexpose.window); - if (f) - { - if (f->async_visible == 0) + x_handle_property_notify (&event); + break; + + case ReparentNotify: + f = x_top_window_to_frame (event.xreparent.window); + if (f) { - f->async_visible = 1; - f->async_iconified = 0; - SET_FRAME_GARBAGED (f); + int x, y; + f->display.x->parent_desc = event.xreparent.parent; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + } + break; + + case Expose: + f = x_window_to_frame (event.xexpose.window); + if (f) + { + if (f->async_visible == 0) + { + f->async_visible = 1; + f->async_iconified = 0; + SET_FRAME_GARBAGED (f); + } + else + dumprectangle (x_window_to_frame (event.xexpose.window), + event.xexpose.x, event.xexpose.y, + event.xexpose.width, event.xexpose.height); } else - dumprectangle (x_window_to_frame (event.xexpose.window), - event.xexpose.x, event.xexpose.y, - event.xexpose.width, event.xexpose.height); - } - else - { - struct scroll_bar *bar - = x_window_to_scroll_bar (event.xexpose.window); - - if (bar) - x_scroll_bar_expose (bar, &event); + { + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xexpose.window); + + if (bar) + x_scroll_bar_expose (bar, &event); +#ifdef USE_X_TOOLKIT + else + goto OTHER; +#endif /* USE_X_TOOLKIT */ + } + break; + + case GraphicsExpose: /* This occurs when an XCopyArea's + source area was obscured or not + available.*/ + f = x_window_to_frame (event.xgraphicsexpose.drawable); + if (f) + { + dumprectangle (f, + event.xgraphicsexpose.x, event.xgraphicsexpose.y, + event.xgraphicsexpose.width, + event.xgraphicsexpose.height); + } #ifdef USE_X_TOOLKIT else goto OTHER; #endif /* USE_X_TOOLKIT */ - } - break; - - case GraphicsExpose: /* This occurs when an XCopyArea's - source area was obscured or not - available.*/ - f = x_window_to_frame (event.xgraphicsexpose.drawable); - if (f) - { - dumprectangle (f, - event.xgraphicsexpose.x, event.xgraphicsexpose.y, - event.xgraphicsexpose.width, - event.xgraphicsexpose.height); - } + break; + + case NoExpose: /* This occurs when an XCopyArea's + source area was completely + available */ + break; + + case UnmapNotify: + f = x_any_window_to_frame (event.xunmap.window); + if (f) /* F may no longer exist if + the frame was deleted. */ + { + /* While a frame is unmapped, display generation is + disabled; you don't want to spend time updating a + display that won't ever be seen. */ + f->async_visible = 0; + /* We can't distinguish, from the event, whether the window + has become iconified or invisible. So assume, if it + was previously visible, than now it is iconified. + We depend on x_make_frame_invisible to mark it iconified. */ + if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)) + f->async_iconified = 1; + } #ifdef USE_X_TOOLKIT - else - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - break; - - case NoExpose: /* This occurs when an XCopyArea's - source area was completely - available */ - break; - - case UnmapNotify: - f = x_any_window_to_frame (event.xunmap.window); - if (f) /* F may no longer exist if - the frame was deleted. */ - { - /* While a frame is unmapped, display generation is - disabled; you don't want to spend time updating a - display that won't ever be seen. */ - f->async_visible = 0; - /* We can't distinguish, from the event, whether the window - has become iconified or invisible. So assume, if it - was previously visible, than now it is iconified. - We depend on x_make_frame_invisible to mark it iconified. */ - if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)) - f->async_iconified = 1; - } + break; + + case MapNotify: + /* We use x_top_window_to_frame because map events can come + for subwindows and they don't mean that the frame is visible. */ + f = x_top_window_to_frame (event.xmap.window); + if (f) + { + f->async_visible = 1; + f->async_iconified = 0; + + /* wait_reading_process_input will notice this and update + the frame's display structures. */ + SET_FRAME_GARBAGED (f); + } #ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - break; - - case MapNotify: - /* We use x_top_window_to_frame because map events can come - for subwindows and they don't mean that the frame is visible. */ - f = x_top_window_to_frame (event.xmap.window); - if (f) - { - f->async_visible = 1; - f->async_iconified = 0; - - /* wait_reading_process_input will notice this and update - the frame's display structures. */ - SET_FRAME_GARBAGED (f); - } -#ifdef USE_X_TOOLKIT - goto OTHER; -#endif /* USE_X_TOOLKIT */ - break; - - /* Turn off processing if we become fully obscured. */ - case VisibilityNotify: - break; - - case KeyPress: - f = x_any_window_to_frame (event.xkey.window); - - if (f != 0) - { - KeySym keysym, orig_keysym; - /* al%imercury@uunet.uu.net says that making this 81 instead of - 80 fixed a bug whereby meta chars made his Emacs hang. */ - unsigned char copy_buffer[81]; - int modifiers; - - event.xkey.state - |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), - extra_keyboard_modifiers); - modifiers = event.xkey.state; - - /* This will have to go some day... */ - - /* make_lispy_event turns chars into control chars. - Don't do it here because XLookupString is too eager. */ - event.xkey.state &= ~ControlMask; - nbytes = - XLookupString (&event.xkey, copy_buffer, 80, &keysym, - &compose_status); - - orig_keysym = keysym; - - if (numchars > 1) + break; + + /* Turn off processing if we become fully obscured. */ + case VisibilityNotify: + break; + + case KeyPress: + f = x_any_window_to_frame (event.xkey.window); + + if (f != 0) { - if (((keysym >= XK_BackSpace && keysym <= XK_Escape) - || keysym == XK_Delete - || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */ - || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */ + KeySym keysym, orig_keysym; + /* al%imercury@uunet.uu.net says that making this 81 instead of + 80 fixed a bug whereby meta chars made his Emacs hang. */ + unsigned char copy_buffer[81]; + int modifiers; + + event.xkey.state + |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), + extra_keyboard_modifiers); + modifiers = event.xkey.state; + + /* This will have to go some day... */ + + /* make_lispy_event turns chars into control chars. + Don't do it here because XLookupString is too eager. */ + event.xkey.state &= ~ControlMask; + nbytes = + XLookupString (&event.xkey, copy_buffer, 80, &keysym, + &compose_status); + + orig_keysym = keysym; + + if (numchars > 1) + { + if (((keysym >= XK_BackSpace && keysym <= XK_Escape) + || keysym == XK_Delete + || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */ + || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */ #ifdef HPUX - /* This recognizes the "extended function keys". - It seems there's no cleaner way. - Test IsModifierKey to avoid handling mode_switch - incorrectly. */ - || ((unsigned) (keysym) >= XK_Select - && (unsigned)(keysym) < XK_KP_Space) + /* This recognizes the "extended function keys". + It seems there's no cleaner way. + Test IsModifierKey to avoid handling mode_switch + incorrectly. */ + || ((unsigned) (keysym) >= XK_Select + && (unsigned)(keysym) < XK_KP_Space) #endif #ifdef XK_dead_circumflex - || orig_keysym == XK_dead_circumflex + || orig_keysym == XK_dead_circumflex #endif #ifdef XK_dead_grave - || orig_keysym == XK_dead_grave + || orig_keysym == XK_dead_grave #endif #ifdef XK_dead_tilde - || orig_keysym == XK_dead_tilde + || orig_keysym == XK_dead_tilde #endif #ifdef XK_dead_diaeresis - || orig_keysym == XK_dead_diaeresis + || orig_keysym == XK_dead_diaeresis #endif #ifdef XK_dead_macron - || orig_keysym == XK_dead_macron + || orig_keysym == XK_dead_macron #endif #ifdef XK_dead_degree - || orig_keysym == XK_dead_degree + || orig_keysym == XK_dead_degree #endif #ifdef XK_dead_acute - || orig_keysym == XK_dead_acute + || orig_keysym == XK_dead_acute #endif #ifdef XK_dead_cedilla - || orig_keysym == XK_dead_cedilla + || orig_keysym == XK_dead_cedilla #endif #ifdef XK_dead_breve - || orig_keysym == XK_dead_breve + || orig_keysym == XK_dead_breve #endif #ifdef XK_dead_ogonek - || orig_keysym == XK_dead_ogonek + || orig_keysym == XK_dead_ogonek #endif #ifdef XK_dead_caron - || orig_keysym == XK_dead_caron + || orig_keysym == XK_dead_caron #endif #ifdef XK_dead_doubleacute - || orig_keysym == XK_dead_doubleacute + || orig_keysym == XK_dead_doubleacute #endif #ifdef XK_dead_abovedot - || orig_keysym == XK_dead_abovedot + || orig_keysym == XK_dead_abovedot #endif - || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ - || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ - /* Any "vendor-specific" key is ok. */ - || (orig_keysym & (1 << 28))) - && ! (IsModifierKey (orig_keysym) + || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ + || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ + /* Any "vendor-specific" key is ok. */ + || (orig_keysym & (1 << 28))) + && ! (IsModifierKey (orig_keysym) #ifndef HAVE_X11R5 #ifdef XK_Mode_switch - || ((unsigned)(orig_keysym) == XK_Mode_switch) + || ((unsigned)(orig_keysym) == XK_Mode_switch) #endif #ifdef XK_Num_Lock - || ((unsigned)(orig_keysym) == XK_Num_Lock) + || ((unsigned)(orig_keysym) == XK_Num_Lock) #endif #endif /* not HAVE_X11R5 */ - )) - { - if (temp_index == sizeof temp_buffer / sizeof (short)) - temp_index = 0; - temp_buffer[temp_index++] = keysym; - bufp->kind = non_ascii_keystroke; - bufp->code = keysym; - XSETFRAME (bufp->frame_or_window, f); - bufp->modifiers - = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), - modifiers); - bufp->timestamp = event.xkey.time; - bufp++; - count++; - numchars--; - } - else if (numchars > nbytes) - { - register int i; - - for (i = 0; i < nbytes; i++) + )) { if (temp_index == sizeof temp_buffer / sizeof (short)) temp_index = 0; - temp_buffer[temp_index++] = copy_buffer[i]; - bufp->kind = ascii_keystroke; - bufp->code = copy_buffer[i]; + temp_buffer[temp_index++] = keysym; + bufp->kind = non_ascii_keystroke; + bufp->code = keysym; XSETFRAME (bufp->frame_or_window, f); bufp->modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers); bufp->timestamp = event.xkey.time; bufp++; + count++; + numchars--; } - - count += nbytes; - numchars -= nbytes; + else if (numchars > nbytes) + { + register int i; + + for (i = 0; i < nbytes; i++) + { + if (temp_index == sizeof temp_buffer / sizeof (short)) + temp_index = 0; + temp_buffer[temp_index++] = copy_buffer[i]; + bufp->kind = ascii_keystroke; + bufp->code = copy_buffer[i]; + XSETFRAME (bufp->frame_or_window, f); + bufp->modifiers + = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), + modifiers); + bufp->timestamp = event.xkey.time; + bufp++; + } + + count += nbytes; + numchars -= nbytes; + } + else + abort (); } else abort (); } - else - abort (); - } - break; - - /* Here's a possible interpretation of the whole - FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a - FocusIn event, you have to get a FocusOut event before you - relinquish the focus. If you haven't received a FocusIn event, - then a mere LeaveNotify is enough to free you. */ - - case EnterNotify: - f = x_any_window_to_frame (event.xcrossing.window); - - if (event.xcrossing.focus) /* Entered Window */ - { - /* Avoid nasty pop/raise loops. */ - if (f && (!(f->auto_raise) - || !(f->auto_lower) - || (event.xcrossing.time - enter_timestamp) > 500)) + break; + + /* Here's a possible interpretation of the whole + FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a + FocusIn event, you have to get a FocusOut event before you + relinquish the focus. If you haven't received a FocusIn event, + then a mere LeaveNotify is enough to free you. */ + + case EnterNotify: + f = x_any_window_to_frame (event.xcrossing.window); + + if (event.xcrossing.focus) /* Entered Window */ { - x_new_focus_frame (f); - enter_timestamp = event.xcrossing.time; + /* Avoid nasty pop/raise loops. */ + if (f && (!(f->auto_raise) + || !(f->auto_lower) + || (event.xcrossing.time - enter_timestamp) > 500)) + { + x_new_focus_frame (f); + enter_timestamp = event.xcrossing.time; + } } - } - else if (f == x_focus_frame) - x_new_focus_frame (0); - /* EnterNotify counts as mouse movement, - so update things that depend on mouse position. */ - if (f) - note_mouse_movement (f, &event.xmotion); + else if (f == x_focus_frame) + x_new_focus_frame (0); + /* EnterNotify counts as mouse movement, + so update things that depend on mouse position. */ + if (f) + note_mouse_movement (f, &event.xmotion); #ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - break; - - case FocusIn: - f = x_any_window_to_frame (event.xfocus.window); - if (event.xfocus.detail != NotifyPointer) - x_focus_event_frame = f; - if (f) - x_new_focus_frame (f); + break; + + case FocusIn: + f = x_any_window_to_frame (event.xfocus.window); + if (event.xfocus.detail != NotifyPointer) + x_focus_event_frame = f; + if (f) + x_new_focus_frame (f); #ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - break; - - - case LeaveNotify: - f = x_top_window_to_frame (event.xcrossing.window); - if (f) - { - if (f == mouse_face_mouse_frame) - /* If we move outside the frame, - then we're certainly no longer on any text in the frame. */ - clear_mouse_face (); - - if (event.xcrossing.focus) + break; + + + case LeaveNotify: + f = x_top_window_to_frame (event.xcrossing.window); + if (f) { - if (! x_focus_event_frame) - x_new_focus_frame (0); + if (f == dpyinfo->mouse_face_mouse_frame) + /* If we move outside the frame, + then we're certainly no longer on any text in the frame. */ + clear_mouse_face (dpyinfo); + + if (event.xcrossing.focus) + { + if (! x_focus_event_frame) + x_new_focus_frame (0); + else + x_new_focus_frame (f); + } else - x_new_focus_frame (f); + { + if (f == x_focus_event_frame) + x_focus_event_frame = 0; + if (f == x_focus_frame) + x_new_focus_frame (0); + } } - else - { - if (f == x_focus_event_frame) - x_focus_event_frame = 0; - if (f == x_focus_frame) - x_new_focus_frame (0); - } - } #ifdef USE_X_TOOLKIT - goto OTHER; -#endif /* USE_X_TOOLKIT */ - break; - - case FocusOut: - f = x_any_window_to_frame (event.xfocus.window); - if (event.xfocus.detail != NotifyPointer - && f == x_focus_event_frame) - x_focus_event_frame = 0; - if (f && f == x_focus_frame) - x_new_focus_frame (0); -#ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - break; - - case MotionNotify: - { - if (dpyinfo->grabbed && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) - f = last_mouse_frame; - else - f = x_window_to_frame (event.xmotion.window); - if (f) - note_mouse_movement (f, &event.xmotion); - else + break; + + case FocusOut: + f = x_any_window_to_frame (event.xfocus.window); + if (event.xfocus.detail != NotifyPointer + && f == x_focus_event_frame) + x_focus_event_frame = 0; + if (f && f == x_focus_frame) + x_new_focus_frame (0); +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ + break; + + case MotionNotify: { - struct scroll_bar *bar - = x_window_to_scroll_bar (event.xmotion.window); - - if (bar) - x_scroll_bar_note_movement (bar, &event); - - /* If we move outside the frame, - then we're certainly no longer on any text in the frame. */ - clear_mouse_face (); + if (dpyinfo->grabbed && last_mouse_frame + && FRAME_LIVE_P (last_mouse_frame)) + f = last_mouse_frame; + else + f = x_window_to_frame (event.xmotion.window); + if (f) + note_mouse_movement (f, &event.xmotion); + else + { + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xmotion.window); + + if (bar) + x_scroll_bar_note_movement (bar, &event); + + /* If we move outside the frame, + then we're certainly no longer on any text in the frame. */ + clear_mouse_face (dpyinfo); + } } - } #if 0 /* This should be unnecessary, since the toolkit has no use - for motion events that happen outside of the menu event loop, - and it seems to cause the bug that mouse events stop coming - after a while. */ + for motion events that happen outside of the menu event loop, + and it seems to cause the bug that mouse events stop coming + after a while. */ #ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ #endif - break; - - case ConfigureNotify: - f = x_any_window_to_frame (event.xconfigure.window); + break; + + case ConfigureNotify: + f = x_any_window_to_frame (event.xconfigure.window); #ifdef USE_X_TOOLKIT - if (f + if (f #if 0 - && ! event.xconfigure.send_event + && ! event.xconfigure.send_event #endif - && (event.xconfigure.window == XtWindow (f->display.x->widget))) - { - Window win, child; - int win_x, win_y; - - /* Find the position of the outside upper-left corner of - the window, in the root coordinate system. Don't - refer to the parent window here; we may be processing - this event after the window manager has changed our - parent, but before we have reached the ReparentNotify. */ - XTranslateCoordinates (FRAME_X_DISPLAY (f), - - /* From-window, to-window. */ - XtWindow (f->display.x->widget), - FRAME_X_DISPLAY_INFO (f)->root_window, - - /* From-position, to-position. */ - -event.xconfigure.border_width, - -event.xconfigure.border_width, - &win_x, &win_y, - - /* Child of win. */ - &child); - event.xconfigure.x = win_x; - event.xconfigure.y = win_y; - - f->display.x->pixel_width = event.xconfigure.width; - f->display.x->pixel_height = event.xconfigure.height; - f->display.x->left_pos = event.xconfigure.x; - f->display.x->top_pos = event.xconfigure.y; - - /* What we have now is the position of Emacs's own window. - Convert that to the position of the window manager window. */ - { - int x, y; - x_real_positions (f, &x, &y); - f->display.x->left_pos = x; - f->display.x->top_pos = y; - } - } - goto OTHER; -#else /* not USE_X_TOOLKIT */ - if (f) - { - int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height); - int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width); - - /* Even if the number of character rows and columns has - not changed, the font size may have changed, so we need - to check the pixel dimensions as well. */ - if (columns != f->width - || rows != f->height - || event.xconfigure.width != f->display.x->pixel_width - || event.xconfigure.height != f->display.x->pixel_height) - { - change_frame_size (f, rows, columns, 0, 1); - SET_FRAME_GARBAGED (f); - } - - if (! event.xconfigure.send_event) + && (event.xconfigure.window == XtWindow (f->display.x->widget))) { Window win, child; int win_x, win_y; @@ -3843,7 +3768,7 @@ XTranslateCoordinates (FRAME_X_DISPLAY (f), /* From-window, to-window. */ - f->display.x->window_desc, + XtWindow (f->display.x->widget), FRAME_X_DISPLAY_INFO (f)->root_window, /* From-position, to-position. */ @@ -3855,119 +3780,179 @@ &child); event.xconfigure.x = win_x; event.xconfigure.y = win_y; + + f->display.x->pixel_width = event.xconfigure.width; + f->display.x->pixel_height = event.xconfigure.height; + f->display.x->left_pos = event.xconfigure.x; + f->display.x->top_pos = event.xconfigure.y; + + /* What we have now is the position of Emacs's own window. + Convert that to the position of the window manager window. */ + { + int x, y; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + } } - - f->display.x->pixel_width = event.xconfigure.width; - f->display.x->pixel_height = event.xconfigure.height; - f->display.x->left_pos = event.xconfigure.x; - f->display.x->top_pos = event.xconfigure.y; - - /* What we have now is the position of Emacs's own window. - Convert that to the position of the window manager window. */ - { - int x, y; - x_real_positions (f, &x, &y); - f->display.x->left_pos = x; - f->display.x->top_pos = y; - if (y != event.xconfigure.y) + goto OTHER; +#else /* not USE_X_TOOLKIT */ + if (f) + { + int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height); + int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width); + + /* Even if the number of character rows and columns has + not changed, the font size may have changed, so we need + to check the pixel dimensions as well. */ + if (columns != f->width + || rows != f->height + || event.xconfigure.width != f->display.x->pixel_width + || event.xconfigure.height != f->display.x->pixel_height) + { + change_frame_size (f, rows, columns, 0, 1); + SET_FRAME_GARBAGED (f); + } + + if (! event.xconfigure.send_event) + { + Window win, child; + int win_x, win_y; + + /* Find the position of the outside upper-left corner of + the window, in the root coordinate system. Don't + refer to the parent window here; we may be processing + this event after the window manager has changed our + parent, but before we have reached the ReparentNotify. */ + XTranslateCoordinates (FRAME_X_DISPLAY (f), + + /* From-window, to-window. */ + f->display.x->window_desc, + FRAME_X_DISPLAY_INFO (f)->root_window, + + /* From-position, to-position. */ + -event.xconfigure.border_width, + -event.xconfigure.border_width, + &win_x, &win_y, + + /* Child of win. */ + &child); + event.xconfigure.x = win_x; + event.xconfigure.y = win_y; + } + + f->display.x->pixel_width = event.xconfigure.width; + f->display.x->pixel_height = event.xconfigure.height; + f->display.x->left_pos = event.xconfigure.x; + f->display.x->top_pos = event.xconfigure.y; + + /* What we have now is the position of Emacs's own window. + Convert that to the position of the window manager window. */ { - /* Since the WM decorations come below top_pos now, - we must put them below top_pos in the future. */ - f->display.x->win_gravity = NorthWestGravity; - x_wm_set_size_hint (f, 0, 0); + int x, y; + x_real_positions (f, &x, &y); + f->display.x->left_pos = x; + f->display.x->top_pos = y; + if (y != event.xconfigure.y) + { + /* Since the WM decorations come below top_pos now, + we must put them below top_pos in the future. */ + f->display.x->win_gravity = NorthWestGravity; + x_wm_set_size_hint (f, 0, 0); + } } - } - } + } #endif /* not USE_X_TOOLKIT */ - break; - - case ButtonPress: - case ButtonRelease: - { - /* If we decide we want to generate an event to be seen - by the rest of Emacs, we put it here. */ - struct input_event emacs_event; - emacs_event.kind = no_event; - - bzero (&compose_status, sizeof (compose_status)); - - f = x_window_to_frame (event.xbutton.window); - if (f) + break; + + case ButtonPress: + case ButtonRelease: { - if (!x_focus_frame || (f == x_focus_frame)) - construct_mouse_click (&emacs_event, &event, f); - } - else - { - struct scroll_bar *bar - = x_window_to_scroll_bar (event.xbutton.window); - - if (bar) - x_scroll_bar_handle_click (bar, &event, &emacs_event); -#ifdef USE_X_TOOLKIT + /* If we decide we want to generate an event to be seen + by the rest of Emacs, we put it here. */ + struct input_event emacs_event; + emacs_event.kind = no_event; + + bzero (&compose_status, sizeof (compose_status)); + + f = x_window_to_frame (event.xbutton.window); + if (f) + { + if (!x_focus_frame || (f == x_focus_frame)) + construct_mouse_click (&emacs_event, &event, f); + } else { - /* Assume we have a menubar button press. A bad - assumption should behave benignly. */ - popup_get_selection (&event); - break; - } + struct scroll_bar *bar + = x_window_to_scroll_bar (event.xbutton.window); + + if (bar) + x_scroll_bar_handle_click (bar, &event, &emacs_event); +#ifdef USE_X_TOOLKIT + else + { + /* Assume we have a menubar button press. A bad + assumption should behave benignly. */ + popup_get_selection (&event); + break; + } #endif /* USE_X_TOOLKIT */ - } - - if (event.type == ButtonPress) - { - dpyinfo->grabbed |= (1 << event.xbutton.button); - last_mouse_frame = f; - } - else - { - dpyinfo->grabbed &= ~(1 << event.xbutton.button); - } - - if (numchars >= 1 && emacs_event.kind != no_event) - { - bcopy (&emacs_event, bufp, sizeof (struct input_event)); - bufp++; - count++; - numchars--; - } + } + + if (event.type == ButtonPress) + { + dpyinfo->grabbed |= (1 << event.xbutton.button); + last_mouse_frame = f; + } + else + { + dpyinfo->grabbed &= ~(1 << event.xbutton.button); + } + + if (numchars >= 1 && emacs_event.kind != no_event) + { + bcopy (&emacs_event, bufp, sizeof (struct input_event)); + bufp++; + count++; + numchars--; + } #ifdef USE_X_TOOLKIT - goto OTHER; + goto OTHER; #endif /* USE_X_TOOLKIT */ - } - break; - - case CirculateNotify: - break; - case CirculateRequest: - break; - - case MappingNotify: - /* Someone has changed the keyboard mapping - update the - local cache. */ - switch (event.xmapping.request) - { - case MappingModifier: - x_find_modifier_meanings (dpyinfo); - /* This is meant to fall through. */ - case MappingKeyboard: - XRefreshKeyboardMapping (&event.xmapping); + } + break; + + case CirculateNotify: + break; + case CirculateRequest: + break; + + case MappingNotify: + /* Someone has changed the keyboard mapping - update the + local cache. */ + switch (event.xmapping.request) + { + case MappingModifier: + x_find_modifier_meanings (dpyinfo); + /* This is meant to fall through. */ + case MappingKeyboard: + XRefreshKeyboardMapping (&event.xmapping); + } +#ifdef USE_X_TOOLKIT + goto OTHER; +#endif /* USE_X_TOOLKIT */ + break; + + default: +#ifdef USE_X_TOOLKIT + OTHER: + BLOCK_INPUT; + XtDispatchEvent (&event); + UNBLOCK_INPUT; +#endif /* USE_X_TOOLKIT */ + break; } -#ifdef USE_X_TOOLKIT - goto OTHER; -#endif /* USE_X_TOOLKIT */ - break; - - default: -#ifdef USE_X_TOOLKIT - OTHER: - BLOCK_INPUT; - XtDispatchEvent (&event); - UNBLOCK_INPUT; -#endif /* USE_X_TOOLKIT */ - break; } } @@ -3982,7 +3967,8 @@ if (x_noop_count >= 100) { x_noop_count=0; - XNoOp (dpyinfo->display); + /* Use the first display in the list. Why not? */ + XNoOp (x_display_list->display); } } @@ -4015,6 +4001,7 @@ /* If the focus was just given to an autoraising frame, raise it now. */ + /* ??? This ought to be able to handle more than one such frame. */ if (pending_autoraise_frame) { x_raise_frame (pending_autoraise_frame); @@ -4189,15 +4176,15 @@ /* If the cursor is in the mouse face area, redisplay that when we clear the cursor. */ - if (f == mouse_face_mouse_frame + if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame && - (f->phys_cursor_y > mouse_face_beg_row - || (f->phys_cursor_y == mouse_face_beg_row - && f->phys_cursor_x >= mouse_face_beg_col)) + (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)) && - (f->phys_cursor_y < mouse_face_end_row - || (f->phys_cursor_y == mouse_face_end_row - && f->phys_cursor_x < mouse_face_end_col))) + (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))) mouse_face_here = 1; /* If the font is not as tall as a whole line, @@ -4353,65 +4340,91 @@ /* Handling X errors. */ -/* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the - X server's connection, or an error reported via the X protocol. */ +/* Handle the loss of connection to display DISPLAY. */ static SIGTYPE -x_connection_closed () +x_connection_closed (display, error_message) + Display *display; + char *error_message; { + struct x_display_info *dpyinfo = x_display_info_for_display (display); + Lisp_Object frame, tail; + if (_Xdebug) abort (); - shut_down_emacs (0, 1, Qnil); - - exit (70); + /* First delete frames whose minibuffers are on frames + that are on the dead display. */ + FOR_EACH_FRAME (tail, frame) + { + Lisp_Object minibuf_frame; + minibuf_frame + = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame)))); + if (! EQ (frame, minibuf_frame) + && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) + Fdelete_frame (frame, Qt); + } + + /* Now delete all remaining frames on the dead display. + We are now sure none of these is used as the minibuffer + for another frame that we need to delete. */ + FOR_EACH_FRAME (tail, frame) + if (FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo) + Fdelete_frame (frame, Qt); + + x_delete_display (dpyinfo); + + if (x_display_list == 0) + { + fprintf (stderr, "%s", error_message); + shut_down_emacs (0, 0, Qnil); + exit (70); + } + + /* Ordinary stack unwind doesn't deal with these. */ +#ifdef SIGIO + sigunblock (sigmask (SIGIO)); +#endif + sigunblock (sigmask (SIGALRM)); + TOTALLY_UNBLOCK_INPUT; + + error ("%s", error_message); } -/* An X error handler which prints an error message and then kills - Emacs. This is what's normally installed as Xlib's handler for - protocol errors. */ +/* This is the usual handler for X protocol errors. + It kills all frames on the display that we got the error for. + If that was the only one, it prints an error message and kills Emacs. */ + static int x_error_quitter (display, error) Display *display; XErrorEvent *error; { - char buf[256]; + char buf[256], buf1[356]; /* Note that there is no real way portable across R3/R4 to get the original error handler. */ XGetErrorText (display, error->error_code, buf, sizeof (buf)); - fprintf (stderr, "X protocol error: %s on protocol request %d\n", + sprintf (buf1, "X protocol error: %s on protocol request %d", buf, error->request_code); - -#if 0 - /* While we're testing Emacs 19, we'll just dump core whenever we - get an X error, so we can figure out why it happened. */ - abort (); -#endif - - x_connection_closed (); + x_connection_closed (display, buf1); } -/* A handler for X IO errors which prints an error message and then - kills Emacs. This is what is always installed as Xlib's handler - for I/O errors. */ +/* This is the handler for X IO errors, always. + It kills all frames on the display that we lost touch with. + If that was the only one, it prints an error message and kills Emacs. */ + static int x_io_error_quitter (display) Display *display; { - fprintf (stderr, "Connection to X server %s lost.\n", - XDisplayName (DisplayString (display))); - -#if 0 - /* While we're testing Emacs 19, we'll just dump core whenever we - get an X error, so we can figure out why it happened. */ - abort (); -#endif - - x_connection_closed (); + char buf[256]; + + sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); + x_connection_closed (display, buf); } - + /* A buffer for storing X error messages. */ static char *x_caught_error_message; #define X_CAUGHT_ERROR_MESSAGE_SIZE 200 @@ -4419,6 +4432,7 @@ /* An X error handler which stores the error message in x_caught_error_message. This is what's installed when x_catch_errors is in effect. */ + static int x_error_catcher (display, error) Display *display; @@ -4429,9 +4443,9 @@ } -/* Begin trapping X errors for frame F. - Actually we trap X errors for all frames, but F should be the frame - you are actually operating on. +/* Begin trapping X errors for display DPY. Actually we trap X errors + for all displays, but DPY should be the display you are actually + operating on. After calling this function, X protocol errors no longer cause Emacs to exit; instead, they are recorded in x_cfc_error_message. @@ -4444,11 +4458,11 @@ void x_catch_errors (), x_check_errors (), x_uncatch_errors (); void -x_catch_errors (f) - FRAME_PTR f; +x_catch_errors (dpy) + Display *dpy; { /* Make sure any errors from previous requests have been dealt with. */ - XSync (FRAME_X_DISPLAY (f), False); + XSync (dpy, False); /* Set up the error buffer. */ x_caught_error_message @@ -4464,19 +4478,19 @@ sprintf (a buffer, FORMAT, the x error message text) as the text. */ void -x_check_errors (f, format) - FRAME_PTR f; +x_check_errors (dpy, format) + Display *dpy; char *format; { /* Make sure to catch any errors incurred so far. */ - XSync (FRAME_X_DISPLAY (f), False); + XSync (dpy, False); if (x_caught_error_message[0]) { char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56]; sprintf (buf, format, x_caught_error_message); - x_uncatch_errors (f); + x_uncatch_errors (dpy); error (buf); } } @@ -4484,11 +4498,11 @@ /* Nonzero if we had any X protocol errors since we did x_catch_errors. */ int -x_had_errors_p (f) - FRAME_PTR f; +x_had_errors_p (dpy) + Display *dpy; { /* Make sure to catch any errors incurred so far. */ - XSync (FRAME_X_DISPLAY (f), False); + XSync (dpy, False); return x_caught_error_message[0] != 0; } @@ -4496,8 +4510,8 @@ /* Stop catching X protocol errors and let them make Emacs die. */ void -x_uncatch_errors (f) - FRAME_PTR f; +x_uncatch_errors (dpy) + Display *dpy; { xfree (x_caught_error_message); x_caught_error_message = 0; @@ -4515,28 +4529,6 @@ /* Changing the font of the frame. */ -/* Set the font of the x-window specified by frame F - to the font named NEWNAME. This is safe to use - even before F has an actual x-window. */ - -struct font_info -{ - XFontStruct *font; - char *name; - char *full_name; -}; - -/* A table of all the fonts we have already loaded. */ -static struct font_info *x_font_table; - -/* The current capacity of x_font_table. */ -static int x_font_table_size; - -/* The number of fonts actually stored in x_font_table. - x_font_table[n] is used and valid iff 0 <= n < n_fonts. - 0 <= n_fonts <= x_font_table_size. */ -static int n_fonts; - /* Give frame F the font named FONTNAME as its default font, and return the full name of that font. FONTNAME may be a wildcard pattern; in that case, we choose some font that fits the pattern. @@ -4572,13 +4564,13 @@ { int i, j; - for (i = 0; i < n_fonts; i++) + for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++) for (j = 0; j < n_matching_fonts; j++) - if (!strcmp (x_font_table[i].name, font_names[j]) - || !strcmp (x_font_table[i].full_name, font_names[j])) + if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j]) + || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j])) { already_loaded = i; - fontname = x_font_table[i].full_name; + fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name; goto found_font; } } @@ -4586,13 +4578,14 @@ /* If we have, just return it from the table. */ if (already_loaded >= 0) - f->display.x->font = x_font_table[already_loaded].font; + f->display.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font; /* Otherwise, load the font and add it to the table. */ else { int i; char *full_name; XFontStruct *font; + int n_fonts; /* Try to find a character-cell font in the list. */ #if 0 @@ -4618,21 +4611,22 @@ } /* Do we need to create the table? */ - if (x_font_table_size == 0) + if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0) { - x_font_table_size = 16; - x_font_table - = (struct font_info *) xmalloc (x_font_table_size - * sizeof (x_font_table[0])); + FRAME_X_DISPLAY_INFO (f)->font_table_size = 16; + FRAME_X_DISPLAY_INFO (f)->font_table + = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size + * sizeof (struct font_info)); } /* Do we need to grow the table? */ - else if (n_fonts >= x_font_table_size) + else if (FRAME_X_DISPLAY_INFO (f)->n_fonts + >= FRAME_X_DISPLAY_INFO (f)->font_table_size) { - x_font_table_size *= 2; - x_font_table - = (struct font_info *) xrealloc (x_font_table, - (x_font_table_size - * sizeof (x_font_table[0]))); + FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2; + FRAME_X_DISPLAY_INFO (f)->font_table + = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table, + (FRAME_X_DISPLAY_INFO (f)->font_table_size + * sizeof (struct font_info))); } /* Try to get the full name of FONT. Put it in full_name. */ @@ -4669,13 +4663,15 @@ XFree (atom); } - x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1); - bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1); + n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts; + FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1); + bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1); if (full_name != 0) - x_font_table[n_fonts].full_name = full_name; + FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name; else - x_font_table[n_fonts].full_name = x_font_table[n_fonts].name; - f->display.x->font = x_font_table[n_fonts++].font = font; + FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name; + f->display.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font; + FRAME_X_DISPLAY_INFO (f)->n_fonts++; if (full_name) fontname = full_name; @@ -5295,11 +5291,13 @@ if (f == x_highlight_frame) x_highlight_frame = 0; - if (f == mouse_face_mouse_frame) + if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame) { - mouse_face_beg_row = mouse_face_beg_col = -1; - mouse_face_end_row = mouse_face_end_col = -1; - mouse_face_window = Qnil; + FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row + = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col = -1; + FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row + = FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col = -1; + FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil; } UNBLOCK_INPUT; @@ -5463,7 +5461,7 @@ if (pixmap_id > 0) { - Pixmap icon_pixmap = x_lookup_pixmap (pixmap_id); + Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id); f->display.x->wm_hints.icon_pixmap = icon_pixmap; f->display.x->wm_hints.flags |= IconPixmapHint; } @@ -5515,6 +5513,8 @@ }; #endif /* USE_X_TOOLKIT */ +static int x_initialized; + struct x_display_info * x_term_init (display_name, xrm_option, resource_name) Lisp_Object display_name; @@ -5526,26 +5526,15 @@ int argc = 0; char** argv = 0; int connection; + Display *dpy; struct x_display_info *dpyinfo; XrmDatabase xrdb; -#ifndef F_SETOWN_BUG -#ifdef F_SETOWN - extern int old_fcntl_owner; -#endif /* ! defined (F_SETOWN) */ -#endif /* F_SETOWN_BUG */ - - dpyinfo = &the_x_screen; - - /* Put our one and only display on the chain. */ - x_display_list = dpyinfo; - dpyinfo->next = 0; - - dpyinfo->name = display_name; - - x_noop_count = 0; - - x_focus_frame = x_highlight_frame = 0; + if (!x_initialized) + { + x_initialize (); + x_initialized = 1; + } #ifdef USE_X_TOOLKIT #ifdef HAVE_X11R5 @@ -5570,44 +5559,52 @@ &argc, argv, NULL, NULL, 0); XtFree ((char *)argv); - dpyinfo->display = XtDisplay (Xt_app_shell); + dpy = XtDisplay (Xt_app_shell); #else /* not USE_X_TOOLKIT */ #ifdef HAVE_X11R5 XSetLocaleModifiers (""); #endif - dpyinfo->display = XOpenDisplay (XSTRING (display_name)->data); + dpy = XOpenDisplay (XSTRING (display_name)->data); #endif /* not USE_X_TOOLKIT */ - if (dpyinfo->display == 0) - fatal ("X server %s not responding.\n\ -Check the DISPLAY environment variable or use \"-d\"\n", - XSTRING (display_name)->data); - - { + /* Detect failure. */ + if (dpy == 0) + return 0; + + /* We have definitely succeeded. Record the new connection. */ + + dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info)); + + /* Put this display on the chain. */ + dpyinfo->next = x_display_list; + x_display_list = dpyinfo; + + /* Put it on x_display_name_list as well, to keep them parallel. */ + x_display_name_list = Fcons (Fcons (display_name, Qnil), + x_display_name_list); + dpyinfo->name_list_element = XCONS (x_display_name_list)->car; + + dpyinfo->display = dpy; + #if 0 - XSetAfterFunction (x_current_display, x_trace_wire); + XSetAfterFunction (x_current_display, x_trace_wire); #endif /* ! 0 */ - x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size - + XSTRING (Vsystem_name)->size - + 2); - sprintf (x_id_name, "%s@%s", - XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); - } + + dpyinfo->x_id_name + = (char *) xmalloc (XSTRING (Vinvocation_name)->size + + XSTRING (Vsystem_name)->size + + 2); + sprintf (dpyinfo->x_id_name, "%s@%s", + XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); /* Figure out which modifier bits mean what. */ x_find_modifier_meanings (dpyinfo); /* Get the scroll bar cursor. */ - x_vertical_scroll_bar_cursor + dpyinfo->vertical_scroll_bar_cursor = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow); -#if 0 - /* Watch for PropertyNotify events on the root window; we use them - to figure out when to invalidate our cache of the cut buffers. */ - x_watch_cut_buffer_cache (); -#endif - xrdb = x_load_resources (dpyinfo->display, xrm_option, resource_name, EMACS_CLASS); #ifdef HAVE_XRMSETDATABASE @@ -5615,6 +5612,9 @@ #else dpyinfo->display->db = xrdb; #endif + /* Put thr rdb where we can find it in a way that works on + all versions. */ + dpyinfo->xrdb = xrdb; dpyinfo->screen = ScreenOfDisplay (dpyinfo->display, DefaultScreen (dpyinfo->display)); @@ -5626,6 +5626,20 @@ dpyinfo->grabbed = 0; dpyinfo->reference_count = 0; dpyinfo->icon_bitmap_id = -1; + dpyinfo->n_fonts = 0; + dpyinfo->font_table_size = 0; + dpyinfo->bitmaps = 0; + dpyinfo->bitmaps_size = 0; + dpyinfo->bitmaps_last = 0; + dpyinfo->scratch_cursor_gc = 0; + dpyinfo->mouse_face_mouse_frame = 0; + dpyinfo->mouse_face_deferred_gc = 0; + dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; + dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; + dpyinfo->mouse_face_face_id = 0; + dpyinfo->mouse_face_window = Qnil; + dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0; + dpyinfo->mouse_face_defer = 0; dpyinfo->Xatom_wm_protocols = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False); @@ -5670,13 +5684,11 @@ #ifdef subprocesses /* This is only needed for distinguishing keyboard and process input. */ if (connection != 0) - change_keyboard_wait_descriptor (connection); + add_keyboard_wait_descriptor (connection); #endif - change_input_fd (connection); #ifndef F_SETOWN_BUG #ifdef F_SETOWN - old_fcntl_owner = fcntl (connection, F_GETOWN, 0); #ifdef F_SETOWN_SOCK_NEG /* stdin is a socket here */ fcntl (connection, F_SETOWN, -getpid ()); @@ -5687,11 +5699,63 @@ #endif /* F_SETOWN_BUG */ #ifdef SIGIO - init_sigio (); + init_sigio (connection); #endif /* ! defined (SIGIO) */ - expose_all_windows = 0; - + return dpyinfo; +} + +/* Get rid of display DPYINFO, assuming all frames are already gone, + and without sending any more commands to the X server. */ + +void +x_delete_display (dpyinfo) + struct x_display_info *dpyinfo; +{ + delete_keyboard_wait_descriptor (dpyinfo->connection); + + /* Discard this display from x_display_name_list and x_display_list. + We can't use Fdelq because that can quit. */ + if (! NILP (x_display_name_list) + && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element)) + x_display_name_list = XCONS (x_display_name_list)->cdr; + else + { + Lisp_Object tail; + + tail = x_display_name_list; + while (CONSP (tail) && CONSP (XCONS (tail)->cdr)) + { + if (EQ (XCONS (XCONS (tail)->cdr)->car, + dpyinfo->name_list_element)) + { + XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr; + break; + } + tail = XCONS (tail)->cdr; + } + } + + if (x_display_list == dpyinfo) + x_display_list = dpyinfo->next; + { + struct x_display_info *tail; + + for (tail = x_display_list; tail; tail = tail->next) + if (tail->next == dpyinfo) + tail->next = tail->next->next; + } + + /* ??? Should free the xrdb slot somehow? */ + free (dpyinfo->font_table); + free (dpyinfo->x_id_name); + free (dpyinfo); +} + +/* Set up use of X before we make the first connection. */ + +x_initialize () +{ clear_frame_hook = XTclear_frame; clear_end_of_line_hook = XTclear_end_of_line; ins_del_lines_hook = XTins_del_lines; @@ -5725,6 +5789,10 @@ off the bottom */ baud_rate = 19200; + x_noop_count = 0; + + x_focus_frame = x_highlight_frame = 0; + /* Try to use interrupt input; if we can't, then start polling. */ Fset_input_mode (Qt, Qnil, Qt, Qnil); @@ -5744,14 +5812,10 @@ void syms_of_xterm () { - the_x_screen.font_list_cache = Qnil; - the_x_screen.name = Qnil; - staticpro (&the_x_screen.font_list_cache); - staticpro (&the_x_screen.name); + staticpro (&x_display_name_list); + x_display_name_list = Qnil; staticpro (&last_mouse_scroll_bar); last_mouse_scroll_bar = Qnil; - staticpro (&mouse_face_window); - mouse_face_window = Qnil; } #endif /* ! defined (HAVE_X_WINDOWS) */