X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/42d02da077d0678e85e9391905e4ce3986c014d8..e2b64074e76730218f85de1d63ceb6832e579d01:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 0dafcfb010..ab46a7700e 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 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 @@ -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); @@ -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; @@ -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 @@ -4329,7 +4328,7 @@ xg_scroll_callback (widget, data) } if (part >= 0) - { + { window_being_scrolled = bar->window; last_scroll_bar_part = part; x_send_scroll_bar_event (bar->window, part, portion, whole); @@ -4553,6 +4552,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) @@ -4576,16 +4576,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); @@ -4594,11 +4595,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); } } @@ -4731,30 +4735,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 } } } @@ -5625,8 +5610,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) @@ -5733,7 +5718,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; @@ -5743,9 +5731,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) { @@ -5843,8 +5831,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; } @@ -5907,7 +5895,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; } @@ -5918,7 +5906,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; @@ -5939,11 +5927,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; @@ -5956,14 +5944,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) 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; @@ -6102,8 +6090,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; @@ -6135,8 +6123,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))) @@ -6299,21 +6287,22 @@ 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; } @@ -6323,10 +6312,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; } @@ -6416,8 +6405,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; } @@ -6468,18 +6457,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; @@ -6506,7 +6495,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); @@ -6536,11 +6525,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) 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) @@ -6563,7 +6552,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) goto OTHER; case FocusOut: - x_detect_focus_change (dpyinfo, &event, &inev); + x_detect_focus_change (dpyinfo, &event, &inev.ie); goto OTHER; case MotionNotify: @@ -6603,8 +6592,8 @@ 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; @@ -6763,13 +6752,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, f); } if (event.type == ButtonRelease) ignore_next_mouse_click_timeout = 0; } else - construct_mouse_click (&inev, &event, f); + construct_mouse_click (&inev.ie, &event, f); } } } @@ -6784,12 +6773,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 */ } @@ -6797,12 +6786,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; @@ -6810,6 +6793,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, @@ -6897,9 +6886,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++; } @@ -7156,7 +7145,7 @@ x_clip_to_row (w, row, area, gc) window_box (w, area, &window_x, &window_y, &window_width, 0); clip_rect.x = window_x; - clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + 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; @@ -7186,29 +7175,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. */ @@ -7772,12 +7742,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 (! NILP (x_error_message_string)) + 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; @@ -7794,21 +7799,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. */