X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/61087d3fd64d11574f98e94c9413ef56b69c9919..c3e9438b5fde71d0464c1bd55919468880256651:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 8aa52b658c..ba51dbb8f5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1,6 +1,6 @@ /* X Communication module for terminals which understand the X protocol. - Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04 - Free Software Foundation, Inc. + Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -16,8 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ /* New display code by Gerd Moellmann . */ /* Xt features made by Fred Pierresteguy. */ @@ -130,9 +130,7 @@ extern void _XEditResCheckMessages (); #ifdef HAVE_XAW3D #include #include -#define ARROW_SCROLLBAR -#define XAW_ARROW_SCROLLBARS -#include +#include #else /* !HAVE_XAW3D */ #include #include @@ -251,6 +249,7 @@ static unsigned long ignore_next_mouse_click_timeout; /* Where the mouse was last time we reported a mouse event. */ static XRectangle last_mouse_glyph; +static FRAME_PTR last_mouse_glyph_frame; static Lisp_Object last_mouse_press_frame; /* The scroll bar in which the last X motion event occurred. @@ -323,11 +322,10 @@ static void x_set_window_size_1 P_ ((struct frame *, int, int, int)); static const XColor *x_color_cells P_ ((Display *, int *)); static void x_update_window_end P_ ((struct window *, int, int)); void x_delete_display P_ ((struct x_display_info *)); -static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, - unsigned)); + static int x_io_error_quitter P_ ((Display *)); -int x_catch_errors P_ ((Display *)); -void x_uncatch_errors P_ ((Display *, int)); +void x_catch_errors P_ ((Display *)); +void x_uncatch_errors P_ ((void)); void x_lower_frame P_ ((struct frame *)); void x_scroll_bar_clear P_ ((struct frame *)); int x_had_errors_p P_ ((Display *)); @@ -357,7 +355,7 @@ static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, enum text_cursor_kinds)); -static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC)); +static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC)); static void x_flush P_ ((struct frame *f)); static void x_update_begin P_ ((struct frame *)); static void x_update_window_begin P_ ((struct window *)); @@ -537,6 +535,12 @@ x_draw_vertical_window_border (w, x, y0, y1) int x, y0, y1; { struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face; + + face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID); + if (face) + XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, + face->foreground); XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), f->output_data.x->normal_gc, x, y0, x, y1); @@ -709,12 +713,12 @@ x_draw_fringe_bitmap (w, row, p) int oldVH = row->visible_height; row->visible_height = p->h; row->y -= rowY - p->y; - x_clip_to_row (w, row, gc); + x_clip_to_row (w, row, -1, gc); row->y = oldY; row->visible_height = oldVH; } else - x_clip_to_row (w, row, gc); + x_clip_to_row (w, row, -1, gc); if (p->bx >= 0 && !p->overlay_p) { @@ -906,6 +910,7 @@ x_encode_char (c, char2b, font_info, two_byte_p) /* It's a program. */ struct ccl_program *ccl = font_info->font_encoder; + check_ccl_update (ccl); if (CHARSET_DIMENSION (charset) == 1) { ccl->reg[0] = charset; @@ -1294,7 +1299,7 @@ x_draw_glyph_string_foreground (s) XDrawImageString is usually faster than XDrawString.) Always use XDrawImageString when drawing the cursor so that there is no chance that characters under a box cursor are invisible. */ - if (s->for_overlaps_p + if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR)) { /* Draw characters with 16-bit or 8-bit functions. */ @@ -2127,15 +2132,9 @@ x_draw_glyph_string_box (s) struct glyph *last_glyph; XRectangle clip_rect; - last_x = window_box_right (s->w, s->area); - if (s->row->full_width_p - && !s->w->pseudo_window_p) - { - last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w); - if (s->area != RIGHT_MARGIN_AREA - || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w)) - last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w); - } + last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area)); /* The glyph that may have a right box line. */ last_glyph = (s->cmp || s->img @@ -2605,7 +2604,7 @@ x_draw_glyph_string (s) /* If S draws into the background of its successor, draw the background of the successor first so that S can draw into it. This makes S->next use XDrawString instead of XDrawImageString. */ - if (s->next && s->right_overhang && !s->for_overlaps_p) + if (s->next && s->right_overhang && !s->for_overlaps) { xassert (s->next->img == NULL); x_set_glyph_string_gc (s->next); @@ -2618,7 +2617,7 @@ x_draw_glyph_string (s) /* Draw relief (if any) in advance for char/composition so that the glyph string can be drawn over it. */ - if (!s->for_overlaps_p + if (!s->for_overlaps && s->face->box != FACE_NO_BOX && (s->first_glyph->type == CHAR_GLYPH || s->first_glyph->type == COMPOSITE_GLYPH)) @@ -2644,7 +2643,7 @@ x_draw_glyph_string (s) break; case CHAR_GLYPH: - if (s->for_overlaps_p) + if (s->for_overlaps) s->background_filled_p = 1; else x_draw_glyph_string_background (s, 0); @@ -2652,7 +2651,7 @@ x_draw_glyph_string (s) break; case COMPOSITE_GLYPH: - if (s->for_overlaps_p || s->gidx > 0) + if (s->for_overlaps || s->gidx > 0) s->background_filled_p = 1; else x_draw_glyph_string_background (s, 1); @@ -2663,7 +2662,7 @@ x_draw_glyph_string (s) abort (); } - if (!s->for_overlaps_p) + if (!s->for_overlaps) { /* Draw underline. */ if (s->face->underline_p) @@ -2823,10 +2822,6 @@ x_clear_frame () XFlush (FRAME_X_DISPLAY (f)); -#ifdef USE_GTK - xg_frame_cleared (f); -#endif - UNBLOCK_INPUT; } @@ -3468,7 +3463,7 @@ x_find_modifier_meanings (dpyinfo) /* Convert between the modifier bits X uses and the modifier bits Emacs uses. */ -static unsigned int +unsigned int x_x_to_emacs_modifiers (dpyinfo, state) struct x_display_info *dpyinfo; unsigned int state; @@ -3587,7 +3582,7 @@ construct_mouse_click (result, event, f) static XMotionEvent last_mouse_motion_event; static Lisp_Object last_mouse_motion_frame; -static void +static int note_mouse_movement (frame, event) FRAME_PTR frame; XMotionEvent *event; @@ -3596,23 +3591,36 @@ note_mouse_movement (frame, event) last_mouse_motion_event = *event; XSETFRAME (last_mouse_motion_frame, frame); + if (!FRAME_X_OUTPUT (frame)) + return 0; + if (event->window != FRAME_X_WINDOW (frame)) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, -1, -1); + last_mouse_glyph_frame = 0; + return 1; } + /* Has the mouse moved off the glyph it was on at the last sighting? */ - else if (event->x < last_mouse_glyph.x - || event->x >= last_mouse_glyph.x + last_mouse_glyph.width - || event->y < last_mouse_glyph.y - || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) + if (frame != last_mouse_glyph_frame + || event->x < last_mouse_glyph.x + || event->x >= last_mouse_glyph.x + last_mouse_glyph.width + || event->y < last_mouse_glyph.y + || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) { frame->mouse_moved = 1; last_mouse_scroll_bar = Qnil; note_mouse_highlight (frame, event->x, event->y); + /* Remember which glyph we're now on. */ + remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph); + last_mouse_glyph_frame = frame; + return 1; } + + return 0; } @@ -3631,56 +3639,6 @@ redo_mouse_highlight () } -static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *)); - - -/* Try to determine frame pixel position and size of the glyph under - frame pixel coordinates X/Y on frame F . Return the position and - size in *RECT. Value is non-zero if we could compute these - values. */ - -static int -glyph_rect (f, x, y, rect) - struct frame *f; - int x, y; - XRectangle *rect; -{ - Lisp_Object window; - struct window *w; - struct glyph_row *r, *end_row; - - window = window_from_coordinates (f, x, y, 0, &x, &y, 0); - if (NILP (window)) - return 0; - - w = XWINDOW (window); - r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - end_row = r + w->current_matrix->nrows - 1; - - for (; r < end_row && r->enabled_p; ++r) - { - if (r->y >= y) - { - struct glyph *g = r->glyphs[TEXT_AREA]; - struct glyph *end = g + r->used[TEXT_AREA]; - int gx = r->x; - while (g < end && gx < x) - gx += g->pixel_width, ++g; - if (g < end) - { - rect->width = g->pixel_width; - rect->height = r->height; - rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx); - rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); - return 1; - } - break; - } - } - - return 0; -} - /* Return the current position of the mouse. *FP should be a frame which indicates which display to ask about. @@ -3761,7 +3719,6 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) Window win, child; int win_x, win_y; int parent_x = 0, parent_y = 0; - int count; win = root; @@ -3769,7 +3726,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) structure is changing at the same time this function is running. So at least we must not crash from them. */ - count = x_catch_errors (FRAME_X_DISPLAY (*fp)); + x_catch_errors (FRAME_X_DISPLAY (*fp)); if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -3838,7 +3795,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) if (x_had_errors_p (FRAME_X_DISPLAY (*fp))) f1 = 0; - x_uncatch_errors (FRAME_X_DISPLAY (*fp), count); + x_uncatch_errors (); /* If not, is it one of our scroll bars? */ if (! f1) @@ -3868,32 +3825,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) on it, i.e. into the same rectangles that matrices on the frame are divided into. */ - int width, height, gx, gy; - XRectangle rect; - - if (glyph_rect (f1, win_x, win_y, &rect)) - last_mouse_glyph = rect; - else - { - width = FRAME_SMALLEST_CHAR_WIDTH (f1); - height = FRAME_SMALLEST_FONT_HEIGHT (f1); - gx = win_x; - gy = win_y; - - /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to - round down even for negative values. */ - if (gx < 0) - gx -= width - 1; - if (gy < 0) - gy -= height - 1; - gx = (gx + width - 1) / width * width; - gy = (gy + height - 1) / height * height; - - last_mouse_glyph.width = width; - last_mouse_glyph.height = height; - last_mouse_glyph.x = gx; - last_mouse_glyph.y = gy; - } + remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph); + last_mouse_glyph_frame = f1; *bar_window = Qnil; *part = 0; @@ -3928,9 +3861,9 @@ x_window_to_scroll_bar (display, window_id) { Lisp_Object tail; -#ifdef USE_GTK +#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS) window_id = (Window) xg_get_scroll_id_for_window (display, window_id); -#endif /* USE_GTK */ +#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */ for (tail = Vframe_list; XGCTYPE (tail) == Lisp_Cons; @@ -4029,8 +3962,6 @@ static Boolean xaw3d_arrow_scroll; static Boolean xaw3d_pick_top; -extern void set_vertical_scroll_bar P_ ((struct window *)); - /* Action hook installed via XtAppAddActionHook when toolkit scroll bars are used.. The hook is responsible for detecting when the user ends an interaction with the scroll bar, and generates @@ -4287,8 +4218,6 @@ xg_scroll_callback (widget, data) int part = -1, whole = 0, portion = 0; GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget)); - if (xg_ignore_gtk_scrollbar) return; - position = gtk_adjustment_get_value (adj); p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA); @@ -4302,6 +4231,8 @@ xg_scroll_callback (widget, data) previous = *p; *p = position; + if (xg_ignore_gtk_scrollbar) return; + diff = (int) (position - previous); if (diff == (int) adj->step_increment) @@ -4557,6 +4488,7 @@ x_create_toolkit_scroll_bar (f, bar) f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel; } +#ifdef XtNbeNiceToColormap /* Tell the toolkit about them. */ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1) @@ -4580,16 +4512,17 @@ x_create_toolkit_scroll_bar (f, bar) pixel = f->output_data.x->scroll_bar_top_shadow_pixel; if (pixel != -1) { - XtSetArg (av[ac], "topShadowPixel", pixel); + XtSetArg (av[ac], XtNtopShadowPixel, pixel); ++ac; } pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel; if (pixel != -1) { - XtSetArg (av[ac], "bottomShadowPixel", pixel); + XtSetArg (av[ac], XtNbottomShadowPixel, pixel); ++ac; } } +#endif widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass, f->output_data.x->edit_widget, av, ac); @@ -4598,11 +4531,14 @@ x_create_toolkit_scroll_bar (f, bar) char *initial = ""; char *val = initial; XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val, +#ifdef XtNarrowScrollbars + XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll, +#endif XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL); - if (val == initial) + if (xaw3d_arrow_scroll || val == initial) { /* ARROW_SCROLL */ xaw3d_arrow_scroll = True; - /* Isn't that just a personal preference ? -sm */ + /* Isn't that just a personal preference ? --Stef */ XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL); } } @@ -4735,30 +4671,11 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) XawScrollbarSetThumb (widget, top, shown); else { -#ifdef HAVE_XAW3D - ScrollbarWidget sb = (ScrollbarWidget) widget; - int scroll_mode = 0; - - /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */ - if (xaw3d_arrow_scroll) - { - /* Xaw3d stupidly ignores resize requests while dragging - so we have to make it believe it's not in dragging mode. */ - scroll_mode = sb->scrollbar.scroll_mode; - if (scroll_mode == 2) - sb->scrollbar.scroll_mode = 0; - } -#endif /* Try to make the scrolling a tad smoother. */ if (!xaw3d_pick_top) shown = min (shown, old_shown); XawScrollbarSetThumb (widget, top, shown); - -#ifdef HAVE_XAW3D - if (xaw3d_arrow_scroll && scroll_mode == 2) - sb->scrollbar.scroll_mode = scroll_mode; -#endif } } } @@ -4861,9 +4778,7 @@ x_scroll_bar_create (w, top, left, width, height) top, left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1), - left, - width); + max (height, 1)); xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar)); #else /* not USE_GTK */ Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); @@ -5107,18 +5022,6 @@ XTset_vertical_scroll_bar (w, portion, whole, position) #ifdef USE_TOOLKIT_SCROLL_BARS -#ifdef USE_GTK - if (mask) - xg_update_scrollbar_pos (f, - SCROLL_BAR_X_WINDOW (bar), - top, - sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, - sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, - max (height, 1), - left, - width); -#else /* not USE_GTK */ - /* Move/size the scroll bar widget. */ if (mask) { @@ -5127,13 +5030,21 @@ XTset_vertical_scroll_bar (w, portion, whole, position) if (width > 0 && height > 0) x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), left, top, width, height, False); +#ifdef USE_GTK + xg_update_scrollbar_pos (f, + SCROLL_BAR_X_WINDOW (bar), + top, + sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2, + max (height, 1)); +#else /* not USE_GTK */ XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar), sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, max (height, 1), 0); - } #endif /* not USE_GTK */ + } #else /* not USE_TOOLKIT_SCROLL_BARS */ /* Clear areas not covered by the scroll bar because of @@ -5584,73 +5495,6 @@ x_scroll_bar_clear (f) #endif /* not USE_TOOLKIT_SCROLL_BARS */ } - -/* Define a queue to save up SelectionRequest events for later handling. */ - -struct selection_event_queue - { - XEvent event; - struct selection_event_queue *next; - }; - -static struct selection_event_queue *queue; - -/* Nonzero means queue up certain events--don't process them yet. */ - -static int x_queue_selection_requests; - -/* Queue up an X event *EVENT, to be processed later. */ - -static void -x_queue_event (f, event) - FRAME_PTR f; - XEvent *event; -{ - struct selection_event_queue *queue_tmp - = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue)); - - if (queue_tmp != NULL) - { - queue_tmp->event = *event; - queue_tmp->next = queue; - queue = queue_tmp; - } -} - -/* Take all the queued events and put them back - so that they get processed afresh. */ - -static void -x_unqueue_events (display) - Display *display; -{ - while (queue != NULL) - { - struct selection_event_queue *queue_tmp = queue; - XPutBackEvent (display, &queue_tmp->event); - queue = queue_tmp->next; - xfree ((char *)queue_tmp); - } -} - -/* Start queuing SelectionRequest events. */ - -void -x_start_queuing_selection_requests (display) - Display *display; -{ - x_queue_selection_requests++; -} - -/* Stop queuing SelectionRequest events. */ - -void -x_stop_queuing_selection_requests (display) - Display *display; -{ - x_queue_selection_requests--; - x_unqueue_events (display); -} /* The main X event-reading loop - XTread_socket. */ @@ -5702,8 +5546,8 @@ static struct x_display_info *next_noop_dpyinfo; f->output_data.x->saved_menu_event \ = (XEvent *) xmalloc (sizeof (XEvent)); \ bcopy (&event, f->output_data.x->saved_menu_event, size); \ - inev.kind = MENU_BAR_ACTIVATE_EVENT; \ - XSETFRAME (inev.frame_or_window, f); \ + inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \ + XSETFRAME (inev.ie.frame_or_window, f); \ } \ while (0) @@ -5810,7 +5654,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) int *finish; struct input_event *hold_quit; { - struct input_event inev; + union { + struct input_event ie; + struct selection_input_event sie; + } inev; int count = 0; int do_help = 0; int nbytes = 0; @@ -5820,9 +5667,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) *finish = X_EVENT_NORMAL; - EVENT_INIT (inev); - inev.kind = NO_EVENT; - inev.arg = Qnil; + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; switch (event.type) { @@ -5865,7 +5712,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) Display *d = event.xclient.display; /* Catch and ignore errors, in case window has been iconified by a window manager such as GWM. */ - int count = x_catch_errors (d); + x_catch_errors (d); XSetInputFocus (d, event.xclient.window, /* The ICCCM says this is the only valid choice. */ @@ -5874,7 +5721,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) /* This is needed to detect the error if there is an error. */ XSync (d, False); - x_uncatch_errors (d, count); + x_uncatch_errors (); } /* Not certain about handling scroll bars here */ #endif /* 0 */ @@ -5920,8 +5767,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (!f) goto OTHER; /* May be a dialog that is to be removed */ - inev.kind = DELETE_WINDOW_EVENT; - XSETFRAME (inev.frame_or_window, f); + inev.ie.kind = DELETE_WINDOW_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); goto done; } @@ -5984,7 +5831,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (event.xclient.message_type == dpyinfo->Xatom_Scrollbar) { - x_scroll_bar_to_input_event (&event, &inev); + x_scroll_bar_to_input_event (&event, &inev.ie); *finish = X_EVENT_GOTO_OUT; goto done; } @@ -5995,7 +5842,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (!f) goto OTHER; - if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev)) + if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie)) *finish = X_EVENT_DROP; } break; @@ -6016,11 +5863,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) { XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; - inev.kind = SELECTION_CLEAR_EVENT; - SELECTION_EVENT_DISPLAY (&inev) = eventp->display; - SELECTION_EVENT_SELECTION (&inev) = eventp->selection; - SELECTION_EVENT_TIME (&inev) = eventp->time; - inev.frame_or_window = Qnil; + inev.ie.kind = SELECTION_CLEAR_EVENT; + SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; + SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; + SELECTION_EVENT_TIME (&inev.sie) = eventp->time; + inev.ie.frame_or_window = Qnil; } break; @@ -6029,23 +5876,19 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner)) goto OTHER; #endif /* USE_X_TOOLKIT */ - if (x_queue_selection_requests) - x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner), - &event); - else - { + { XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event; - inev.kind = SELECTION_REQUEST_EVENT; - SELECTION_EVENT_DISPLAY (&inev) = eventp->display; - SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor; - SELECTION_EVENT_SELECTION (&inev) = eventp->selection; - SELECTION_EVENT_TARGET (&inev) = eventp->target; - SELECTION_EVENT_PROPERTY (&inev) = eventp->property; - SELECTION_EVENT_TIME (&inev) = eventp->time; - inev.frame_or_window = Qnil; - } + inev.ie.kind = SELECTION_REQUEST_EVENT; + SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display; + SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor; + SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; + SELECTION_EVENT_TARGET (&inev.sie) = eventp->target; + SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property; + SELECTION_EVENT_TIME (&inev.sie) = eventp->time; + inev.ie.frame_or_window = Qnil; + } break; case PropertyNotify: @@ -6081,6 +5924,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) { x_check_fullscreen (f); +#ifdef USE_GTK + /* This seems to be needed for GTK 2.6. */ + x_clear_area (event.xexpose.display, + event.xexpose.window, + event.xexpose.x, event.xexpose.y, + event.xexpose.width, event.xexpose.height, + FALSE); +#endif if (f->async_visible == 0) { f->async_visible = 1; @@ -6175,8 +6026,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) { f->async_iconified = 1; - inev.kind = ICONIFY_EVENT; - XSETFRAME (inev.frame_or_window, f); + inev.ie.kind = ICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); } } goto OTHER; @@ -6208,8 +6059,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (f->iconified) { - inev.kind = DEICONIFY_EVENT; - XSETFRAME (inev.frame_or_window, f); + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -6232,7 +6083,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) f = x_any_window_to_frame (dpyinfo, event.xkey.window); - if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) + && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)) { clear_mouse_face (dpyinfo); dpyinfo->mouse_face_hidden = 1; @@ -6318,7 +6170,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (status_return == XBufferOverflow) { copy_bufsiz = nbytes + 1; - copy_bufptr = (char *) alloca (copy_bufsiz); + copy_bufptr = (unsigned char *) alloca (copy_bufsiz); nbytes = XmbLookupString (FRAME_XIC (f), &event.xkey, copy_bufptr, copy_bufsiz, &keysym, @@ -6336,7 +6188,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (status_return == XBufferOverflow) { copy_bufsiz = nbytes + 1; - copy_bufptr = (char *) alloca (copy_bufsiz); + copy_bufptr = (unsigned char *) alloca (copy_bufsiz); nbytes = Xutf8LookupString (FRAME_XIC (f), &event.xkey, copy_bufptr, @@ -6372,21 +6224,60 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (compose_status.chars_matched > 0 && nbytes == 0) break; + bzero (&compose_status, sizeof (compose_status)); orig_keysym = keysym; /* Common for all keysym input events. */ - XSETFRAME (inev.frame_or_window, f); - inev.modifiers + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers); - inev.timestamp = event.xkey.time; + inev.ie.timestamp = event.xkey.time; /* First deal with keysyms which have defined translations to characters. */ if (keysym >= 32 && keysym < 128) /* Avoid explicitly decoding each ASCII character. */ { - inev.kind = ASCII_KEYSTROKE_EVENT; - inev.code = keysym; + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; + goto done_keysym; + } + + /* Keysyms directly mapped to supported Unicode characters. */ + if ((keysym >= 0x01000000 && keysym <= 0x010033ff) + || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + { + int code = keysym & 0xFFFF, charset_id, c1, c2; + + if (code < 0x80) + { + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + inev.ie.code = code; + } + else if (code < 0x100) + { + if (code < 0xA0) + charset_id = CHARSET_8_BIT_CONTROL; + else + charset_id = charset_latin_iso8859_1; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = MAKE_CHAR (charset_id, code, 0); + } + else + { + if (code < 0x2500) + charset_id = charset_mule_unicode_0100_24ff, + code -= 0x100; + else if (code < 0xE000) + charset_id = charset_mule_unicode_2500_33ff, + code -= 0x2500; + else + charset_id = charset_mule_unicode_e000_ffff, + code -= 0xE000; + c1 = (code / 96) + 32, c2 = (code % 96) + 32; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = MAKE_CHAR (charset_id, c1, c2); + } goto done_keysym; } @@ -6396,10 +6287,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) Vx_keysym_table, Qnil)))) { - inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.code = XFASTINT (c); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = XFASTINT (c); goto done_keysym; } @@ -6489,8 +6380,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) STORE_KEYSYM_FOR_DEBUG (keysym); /* make_lispy_event will convert this to a symbolic key. */ - inev.kind = NON_ASCII_KEYSTROKE_EVENT; - inev.code = keysym; + inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; goto done_keysym; } @@ -6541,18 +6432,18 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) else c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, nbytes - i, len); - inev.kind = (SINGLE_BYTE_CHAR_P (c) + inev.ie.kind = (SINGLE_BYTE_CHAR_P (c) ? ASCII_KEYSTROKE_EVENT : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.code = c; - kbd_buffer_store_event_hold (&inev, hold_quit); + inev.ie.code = c; + kbd_buffer_store_event_hold (&inev.ie, hold_quit); } /* Previous code updated count by nchars rather than nbytes, but that seems bogus to me. ++kfs */ count += nbytes; - inev.kind = NO_EVENT; /* Already stored above. */ + inev.ie.kind = NO_EVENT; /* Already stored above. */ if (keysym == NoSymbol) break; @@ -6579,7 +6470,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) #endif case EnterNotify: - x_detect_focus_change (dpyinfo, &event, &inev); + x_detect_focus_change (dpyinfo, &event, &inev.ie); f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); @@ -6606,14 +6497,20 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) so update things that depend on mouse position. */ if (f && !f->output_data.x->hourglass_p) note_mouse_movement (f, &event.xmotion); +#ifdef USE_GTK + /* We may get an EnterNotify on the buttons in the toolbar. In that + case we moved out of any highlighted area and need to note this. */ + if (!f && last_mouse_glyph_frame) + note_mouse_movement (last_mouse_glyph_frame, &event); +#endif goto OTHER; case FocusIn: - x_detect_focus_change (dpyinfo, &event, &inev); + x_detect_focus_change (dpyinfo, &event, &inev.ie); goto OTHER; case LeaveNotify: - x_detect_focus_change (dpyinfo, &event, &inev); + x_detect_focus_change (dpyinfo, &event, &inev.ie); f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); if (f) @@ -6633,17 +6530,21 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (any_help_event_p) do_help = -1; } +#ifdef USE_GTK + /* See comment in EnterNotify above */ + else if (last_mouse_glyph_frame) + note_mouse_movement (last_mouse_glyph_frame, &event); +#endif goto OTHER; case FocusOut: - x_detect_focus_change (dpyinfo, &event, &inev); + x_detect_focus_change (dpyinfo, &event, &inev.ie); goto OTHER; case MotionNotify: { previous_help_echo_string = help_echo_string; - help_echo_string = help_echo_object = help_echo_window = Qnil; - help_echo_pos = -1; + help_echo_string = Qnil; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -6676,13 +6577,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) && !EQ (window, last_window) && !EQ (window, selected_window)) { - inev.kind = SELECT_WINDOW_EVENT; - inev.frame_or_window = window; + inev.ie.kind = SELECT_WINDOW_EVENT; + inev.ie.frame_or_window = window; } last_window=window; } - note_mouse_movement (f, &event.xmotion); + if (!note_mouse_movement (f, &event.xmotion)) + help_echo_string = previous_help_echo_string; } else { @@ -6791,6 +6693,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) int tool_bar_p = 0; bzero (&compose_status, sizeof (compose_status)); + last_mouse_glyph_frame = 0; if (dpyinfo->grabbed && last_mouse_frame @@ -6836,13 +6739,13 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0) { ignore_next_mouse_click_timeout = 0; - construct_mouse_click (&inev, &event, f); + construct_mouse_click (&inev.ie, &event.xbutton, f); } if (event.type == ButtonRelease) ignore_next_mouse_click_timeout = 0; } else - construct_mouse_click (&inev, &event, f); + construct_mouse_click (&inev.ie, &event.xbutton, f); } } } @@ -6857,12 +6760,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) scroll bars. */ if (bar && event.xbutton.state & ControlMask) { - x_scroll_bar_handle_click (bar, &event, &inev); + x_scroll_bar_handle_click (bar, &event, &inev.ie); *finish = X_EVENT_DROP; } #else /* not USE_TOOLKIT_SCROLL_BARS */ if (bar) - x_scroll_bar_handle_click (bar, &event, &inev); + x_scroll_bar_handle_click (bar, &event, &inev.ie); #endif /* not USE_TOOLKIT_SCROLL_BARS */ } @@ -6870,12 +6773,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) { dpyinfo->grabbed |= (1 << event.xbutton.button); last_mouse_frame = f; - /* Ignore any mouse motion that happened - before this event; any subsequent mouse-movement - Emacs events should reflect only motion after - the ButtonPress. */ - if (f != 0) - f->mouse_moved = 0; if (!tool_bar_p) last_tool_bar_item = -1; @@ -6883,6 +6780,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) else dpyinfo->grabbed &= ~(1 << event.xbutton.button); + /* Ignore any mouse motion that happened before this event; + any subsequent mouse-movement Emacs events should reflect + only motion after the ButtonPress/Release. */ + if (f != 0) + f->mouse_moved = 0; + #if defined (USE_X_TOOLKIT) || defined (USE_GTK) f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window); /* For a down-event in the menu bar, @@ -6970,9 +6873,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) } done: - if (inev.kind != NO_EVENT) + if (inev.ie.kind != NO_EVENT) { - kbd_buffer_store_event_hold (&inev, hold_quit); + kbd_buffer_store_event_hold (&inev.ie, hold_quit); count++; } @@ -7216,19 +7119,20 @@ XTread_socket (sd, expected, hold_quit) mode lines must be clipped to the whole window. */ static void -x_clip_to_row (w, row, gc) +x_clip_to_row (w, row, area, gc) struct window *w; struct glyph_row *row; + int area; GC gc; { struct frame *f = XFRAME (WINDOW_FRAME (w)); XRectangle clip_rect; - int window_y, window_width; + int window_x, window_y, window_width; - window_box (w, -1, 0, &window_y, &window_width, 0); + window_box (w, area, &window_x, &window_y, &window_width, 0); - clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0); - clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + clip_rect.x = window_x; + clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); clip_rect.y = max (clip_rect.y, window_y); clip_rect.width = window_width; clip_rect.height = row->visible_height; @@ -7258,29 +7162,10 @@ x_draw_hollow_cursor (w, row) if (cursor_glyph == NULL) return; - /* Compute the width of the rectangle to draw. If on a stretch - glyph, and `x-stretch-block-cursor' is nil, don't draw a - rectangle as wide as the glyph, but use a canonical character - width instead. */ - wd = cursor_glyph->pixel_width - 1; - if (cursor_glyph->type == STRETCH_GLYPH - && !x_stretch_cursor_p) - wd = min (FRAME_COLUMN_WIDTH (f), wd); - w->phys_cursor_width = wd; - - /* Compute frame-relative coordinates from window-relative - coordinates. */ + /* Compute frame-relative coordinates for phys cursor. */ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); - - /* Compute the proper height and ascent of the rectangle, based - on the actual glyph. Using the full height of the row looks - bad when there are tall images on that row. */ - h = max (min (FRAME_LINE_HEIGHT (f), row->height), - cursor_glyph->ascent + cursor_glyph->descent); - if (h < row->height) - y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h; - h--; + y = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + wd = w->phys_cursor_width; /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ @@ -7293,8 +7178,8 @@ x_draw_hollow_cursor (w, row) gc = dpyinfo->scratch_cursor_gc; /* Set clipping, draw the rectangle, and reset clipping again. */ - x_clip_to_row (w, row, gc); - XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h); + x_clip_to_row (w, row, TEXT_AREA, gc); + XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1); XSetClipMask (dpy, gc, None); } @@ -7365,7 +7250,7 @@ x_draw_bar_cursor (w, row, width, kind) width = min (cursor_glyph->pixel_width, width); w->phys_cursor_width = width; - x_clip_to_row (w, row, gc); + x_clip_to_row (w, row, TEXT_AREA, gc); if (kind == BAR_CURSOR) XFillRectangle (dpy, window, gc, @@ -7507,10 +7392,30 @@ x_bitmap_icon (f, file) /* Create the GNU bitmap and mask if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) { - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id - = x_create_bitmap_from_data (f, gnu_bits, - gnu_width, gnu_height); - x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + int rc = -1; + +#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) +#ifdef USE_GTK + if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + return 0; +#else + rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits); + if (rc != -1) + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; +#endif /* USE_GTK */ +#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ + + /* If all else fails, use the (black and white) xbm image. */ + if (rc == -1) + { + rc = x_create_bitmap_from_data (f, gnu_xbm_bits, + gnu_xbm_width, gnu_xbm_height); + if (rc == -1) + return 1; + + FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc; + x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + } } /* The first time we create the GNU bitmap and mask, @@ -7564,9 +7469,18 @@ x_text_icon (f, icon_name) #define X_ERROR_MESSAGE_SIZE 200 /* If non-nil, this should be a string. - It means catch X errors and store the error message in this string. */ + It means catch X errors and store the error message in this string. -static Lisp_Object x_error_message_string; + The reason we use a stack is that x_catch_error/x_uncatch_error can + be called from a signal handler. +*/ + +struct x_error_message_stack { + char string[X_ERROR_MESSAGE_SIZE]; + Display *dpy; + struct x_error_message_stack *prev; +}; +static struct x_error_message_stack *x_error_message; /* An X error handler which stores the error message in x_error_message_string. This is called from x_error_handler if @@ -7578,7 +7492,7 @@ x_error_catcher (display, error) XErrorEvent *error; { XGetErrorText (display, error->error_code, - SDATA (x_error_message_string), + x_error_message->string, X_ERROR_MESSAGE_SIZE); } @@ -7596,43 +7510,41 @@ x_error_catcher (display, error) Calling x_uncatch_errors resumes the normal error handling. */ void x_check_errors (); -static Lisp_Object x_catch_errors_unwind (); -int +void x_catch_errors (dpy) Display *dpy; { - int count = SPECPDL_INDEX (); + struct x_error_message_stack *data = xmalloc (sizeof (*data)); /* Make sure any errors from previous requests have been dealt with. */ XSync (dpy, False); - record_unwind_protect (x_catch_errors_unwind, - Fcons (make_save_value (dpy, 0), - x_error_message_string)); - - x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE); - SSET (x_error_message_string, 0, 0); - - return count; + data->dpy = dpy; + data->string[0] = 0; + data->prev = x_error_message; + x_error_message = data; } -/* Unbind the binding that we made to check for X errors. */ +/* Undo the last x_catch_errors call. + DPY should be the display that was passed to x_catch_errors. */ -static Lisp_Object -x_catch_errors_unwind (old_val) - Lisp_Object old_val; +void +x_uncatch_errors () { - Lisp_Object first = XCAR (old_val); - Display *dpy = XSAVE_VALUE (first)->pointer; + struct x_error_message_stack *tmp; + + BLOCK_INPUT; /* The display may have been closed before this function is called. Check if it is still open before calling XSync. */ - if (x_display_info_for_display (dpy) != 0) - XSync (dpy, False); + if (x_display_info_for_display (x_error_message->dpy) != 0) + XSync (x_error_message->dpy, False); - x_error_message_string = XCDR (old_val); - return Qnil; + tmp = x_error_message; + x_error_message = x_error_message->prev; + xfree (tmp); + UNBLOCK_INPUT; } /* If any X protocol errors have arrived since the last call to @@ -7647,8 +7559,13 @@ x_check_errors (dpy, format) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - if (SREF (x_error_message_string, 0)) - error (format, SDATA (x_error_message_string)); + if (x_error_message->string[0]) + { + char string[X_ERROR_MESSAGE_SIZE]; + bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE); + x_uncatch_errors (); + error (format, string); + } } /* Nonzero if we had any X protocol errors @@ -7661,7 +7578,7 @@ x_had_errors_p (dpy) /* Make sure to catch any errors incurred so far. */ XSync (dpy, False); - return SREF (x_error_message_string, 0) != 0; + return x_error_message->string[0] != 0; } /* Forget about any errors we have had, since we did x_catch_errors on DPY. */ @@ -7670,20 +7587,24 @@ void x_clear_errors (dpy) Display *dpy; { - SSET (x_error_message_string, 0, 0); + x_error_message->string[0] = 0; } -/* Stop catching X protocol errors and let them make Emacs die. - DPY should be the display that was passed to x_catch_errors. - COUNT should be the value that was returned by - the corresponding call to x_catch_errors. */ +/* Close off all unclosed x_catch_errors calls. */ void -x_uncatch_errors (dpy, count) - Display *dpy; - int count; +x_fully_uncatch_errors () +{ + while (x_error_message) + x_uncatch_errors (); +} + +/* Nonzero if x_catch_errors has been done and not yet canceled. */ + +int +x_catching_errors () { - unbind_to (count, Qnil); + return x_error_message != 0; } #if 0 @@ -7742,7 +7663,6 @@ x_connection_closed (dpy, error_message) { struct x_display_info *dpyinfo = x_display_info_for_display (dpy); Lisp_Object frame, tail; - int count; error_msg = (char *) alloca (strlen (error_message) + 1); strcpy (error_msg, error_message); @@ -7752,7 +7672,7 @@ x_connection_closed (dpy, error_message) below. Otherwise, we might end up with printing ``can't find per display information'' in the recursive call instead of printing the original message here. */ - count = x_catch_errors (dpy); + x_catch_errors (dpy); /* We have to close the display to inform Xt that it doesn't exist anymore. If we don't, Xt will continue to wait for @@ -7820,7 +7740,7 @@ x_connection_closed (dpy, error_message) if (dpyinfo) x_delete_display (dpyinfo); - x_uncatch_errors (dpy, count); + x_uncatch_errors (); if (x_display_list == 0) { @@ -7840,12 +7760,47 @@ x_connection_closed (dpy, error_message) error ("%s", error_msg); } +/* We specifically use it before defining it, so that gcc doesn't inline it, + otherwise gdb doesn't know how to properly put a breakpoint on it. */ +static void x_error_quitter (Display *display, XErrorEvent *error); + +/* This is the first-level handler for X protocol errors. + It calls x_error_quitter or x_error_catcher. */ + +static int +x_error_handler (display, error) + Display *display; + XErrorEvent *error; +{ + if (x_error_message) + x_error_catcher (display, error); + else + x_error_quitter (display, error); + return 0; +} /* 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 void +/* .gdbinit puts a breakpoint here, so make sure it is not inlined. */ + +#if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */ +#define NO_INLINE __attribute__((noinline)) +#else +#define NO_INLINE +#endif + +/* Some versions of GNU/Linux define noinline in their headers. */ + +#ifdef noinline +#undef noinline +#endif + +/* On older GCC versions, just putting x_error_quitter + after x_error_handler prevents inlining into the former. */ + +static void NO_INLINE x_error_quitter (display, error) Display *display; XErrorEvent *error; @@ -7862,21 +7817,6 @@ x_error_quitter (display, error) } -/* This is the first-level handler for X protocol errors. - It calls x_error_quitter or x_error_catcher. */ - -static int -x_error_handler (display, error) - Display *display; - XErrorEvent *error; -{ - if (! NILP (x_error_message_string)) - x_error_catcher (display, error); - else - x_error_quitter (display, error); - return 0; -} - /* 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. */ @@ -7914,7 +7854,8 @@ x_new_font (f, fontname) FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset; FRAME_FONTSET (f) = -1; - FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f)); + FRAME_COLUMN_WIDTH (f) = fontp->average_width; + FRAME_SPACE_WIDTH (f) = fontp->space_width; FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f)); compute_fringe_widths (f, 1); @@ -8022,11 +7963,7 @@ xim_destroy_callback (xim, client_data, call_data) if (FRAME_X_DISPLAY_INFO (f) == dpyinfo) { FRAME_XIC (f) = NULL; - if (FRAME_XIC_FONTSET (f)) - { - XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f)); - FRAME_XIC_FONTSET (f) = NULL; - } + xic_free_xfontset (f); } } @@ -8219,7 +8156,6 @@ void x_calc_absolute_position (f) struct frame *f; { - int win_x = 0, win_y = 0; int flags = f->size_hint_flags; /* We have nothing to do if the current position @@ -8227,20 +8163,11 @@ x_calc_absolute_position (f) if (! ((flags & XNegative) || (flags & YNegative))) return; - /* Find the offsets of the outside upper-left corner of - the inner window, with respect to the outer window. - But do this only if we will need the results. */ - if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window) - /* This is to get *_pixels_outer_diff. */ - x_real_positions (f, &win_x, &win_y); - /* Treat negative positions as relative to the leftmost bottommost position that fits on the screen. */ if (flags & XNegative) f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width - - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff - - FRAME_PIXEL_WIDTH (f) - + f->left_pos); + - FRAME_PIXEL_WIDTH (f) + f->left_pos); { int height = FRAME_PIXEL_HEIGHT (f); @@ -8262,15 +8189,7 @@ x_calc_absolute_position (f) #endif if (flags & YNegative) - f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - - FRAME_X_OUTPUT (f)->y_pixels_outer_diff - - /* Assume the window manager decorations are the same size on - three sides, i.e. left, right and bottom. This is to - compensate for the bottom part. */ - - FRAME_X_OUTPUT (f)->x_pixels_outer_diff - - height - + f->top_pos); + f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos); } /* The left_pos and top_pos @@ -8386,7 +8305,9 @@ x_check_expected_move (f) FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos; FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos; - x_set_offset (f, expect_left, expect_top, 1); + f->left_pos = expect_left; + f->top_pos = expect_top; + x_set_offset (f, expect_left, expect_top, 0); } else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN) FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; @@ -9346,7 +9267,14 @@ x_wm_set_icon_pixmap (f, pixmap_id) #endif } -#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */ + +#ifdef USE_GTK + { + xg_set_frame_icon (f, icon_pixmap, icon_mask); + return; + } + +#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */ { Arg al[1]; @@ -9356,12 +9284,12 @@ x_wm_set_icon_pixmap (f, pixmap_id) XtSetValues (f->output_data.x->widget, al, 1); } -#else /* not USE_X_TOOLKIT */ +#else /* not USE_X_TOOLKIT && not USE_GTK */ f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint); XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); -#endif /* not USE_X_TOOLKIT */ +#endif /* not USE_X_TOOLKIT && not USE_GTK */ } void @@ -9418,7 +9346,6 @@ x_list_fonts (f, pattern, size, maxnames) = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list; Display *dpy = dpyinfo->display; int try_XLoadQueryFont = 0; - int count; int allow_auto_scaled_font = 0; if (size < 0) @@ -9458,7 +9385,7 @@ x_list_fonts (f, pattern, size, maxnames) /* At first, put PATTERN in the cache. */ BLOCK_INPUT; - count = x_catch_errors (dpy); + x_catch_errors (dpy); if (try_XLoadQueryFont) { @@ -9539,7 +9466,7 @@ x_list_fonts (f, pattern, size, maxnames) } } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (names) @@ -9630,7 +9557,7 @@ x_list_fonts (f, pattern, size, maxnames) XFontStruct *thisinfo; BLOCK_INPUT; - count = x_catch_errors (dpy); + x_catch_errors (dpy); thisinfo = XLoadQueryFont (dpy, SDATA (XCAR (tem))); if (x_had_errors_p (dpy)) @@ -9640,7 +9567,7 @@ x_list_fonts (f, pattern, size, maxnames) thisinfo = NULL; x_clear_errors (dpy); } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (thisinfo) @@ -9796,7 +9723,6 @@ x_load_font (f, fontname, size) { struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); Lisp_Object font_names; - int count; /* Get a list of all the fonts that match this name. Once we have a list of matching fonts, we compare them against the fonts @@ -9835,7 +9761,7 @@ x_load_font (f, fontname, size) fontname = (char *) SDATA (XCAR (font_names)); BLOCK_INPUT; - count = x_catch_errors (FRAME_X_DISPLAY (f)); + x_catch_errors (FRAME_X_DISPLAY (f)); font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); if (x_had_errors_p (FRAME_X_DISPLAY (f))) { @@ -9844,7 +9770,7 @@ x_load_font (f, fontname, size) font = NULL; x_clear_errors (FRAME_X_DISPLAY (f)); } - x_uncatch_errors (FRAME_X_DISPLAY (f), count); + x_uncatch_errors (); UNBLOCK_INPUT; if (!font) return NULL; @@ -9877,6 +9803,43 @@ x_load_font (f, fontname, size) fontp->name = (char *) xmalloc (strlen (fontname) + 1); bcopy (fontname, fontp->name, strlen (fontname) + 1); + if (font->min_bounds.width == font->max_bounds.width) + { + /* Fixed width font. */ + fontp->average_width = fontp->space_width = font->min_bounds.width; + } + else + { + XChar2b char2b; + XCharStruct *pcm; + + char2b.byte1 = 0x00, char2b.byte2 = 0x20; + pcm = x_per_char_metric (font, &char2b, 0); + if (pcm) + fontp->space_width = pcm->width; + else + fontp->space_width = FONT_WIDTH (font); + + fontp->average_width + = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value) + ? (long) value / 10 : 0); + if (fontp->average_width < 0) + fontp->average_width = - fontp->average_width; + if (fontp->average_width == 0) + { + if (pcm) + { + int width = pcm->width; + for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) + if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL) + width += pcm->width; + fontp->average_width = width / 95; + } + else + fontp->average_width = FONT_WIDTH (font); + } + } + /* Try to get the full name of FONT. Put it in FULL_NAME. */ full_name = 0; if (XGetFontProperty (font, XA_FONT, &value)) @@ -10077,6 +10040,10 @@ static XrmOptionDescRec emacs_options[] = { static int x_initialized; +#ifdef HAVE_X_SM +static int x_session_initialized; +#endif + #ifdef MULTI_KBOARD /* Test whether two display-name strings agree up to the dot that separates the screen number from the server number. */ @@ -10154,6 +10121,21 @@ get_bits_and_offset (mask, bits, offset) *bits = nr; } +int +x_display_ok (display) + const char * display; +{ + int dpy_ok = 1; + Display *dpy; + + dpy = XOpenDisplay (display); + if (dpy) + XCloseDisplay (dpy); + else + dpy_ok = 0; + return dpy_ok; +} + struct x_display_info * x_term_init (display_name, xrm_option, resource_name) Lisp_Object display_name; @@ -10223,18 +10205,14 @@ x_term_init (display_name, xrm_option, resource_name) /* Load our own gtkrc if it exists. */ { - struct gcpro gcpro1, gcpro2; char *file = "~/.emacs.d/gtkrc"; Lisp_Object s, abs_file; - GCPRO2 (s, abs_file); s = make_string (file, strlen (file)); abs_file = Fexpand_file_name (s, Qnil); if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file))) gtk_rc_parse (SDATA (abs_file)); - - UNGCPRO; } XSetErrorHandler (x_error_handler); @@ -10504,6 +10482,8 @@ x_term_init (display_name, xrm_option, resource_name) /* For properties of font. */ dpyinfo->Xatom_PIXEL_SIZE = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False); + dpyinfo->Xatom_AVERAGE_WIDTH + = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False); dpyinfo->Xatom_MULE_BASELINE_OFFSET = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False); dpyinfo->Xatom_MULE_RELATIVE_COMPOSE @@ -10578,7 +10558,6 @@ x_term_init (display_name, xrm_option, resource_name) Display *dpy = dpyinfo->display; XrmValue d, fr, to; Font font; - int count; d.addr = (XPointer)&dpy; d.size = sizeof (Display *); @@ -10586,12 +10565,12 @@ x_term_init (display_name, xrm_option, resource_name) fr.size = sizeof (XtDefaultFont); to.size = sizeof (Font *); to.addr = (XPointer)&font; - count = x_catch_errors (dpy); + x_catch_errors (dpy); if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) abort (); if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); - x_uncatch_errors (dpy, count); + x_uncatch_errors (); } #endif #endif @@ -10631,7 +10610,7 @@ x_term_init (display_name, xrm_option, resource_name) #ifdef HAVE_X_SM /* Only do this for the first display. */ - if (x_initialized == 1) + if (!x_session_initialized++) x_session_initialize (dpyinfo); #endif @@ -10816,6 +10795,9 @@ x_initialize () last_tool_bar_item = -1; any_help_event_p = 0; ignore_next_mouse_click_timeout = 0; +#ifdef HAVE_X_SM + x_session_initialized = 0; +#endif #ifdef USE_GTK current_count = -1; @@ -10875,8 +10857,7 @@ x_initialize () void syms_of_xterm () { - staticpro (&x_error_message_string); - x_error_message_string = Qnil; + x_error_message = NULL; staticpro (&x_display_name_list); x_display_name_list = Qnil;