X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/41882805d6711e32ac0f066119226d84dbdedc13..e6335dc16c9c8fad7dc630e9a8261e4178d8e2fa:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index d34a25ab6f..b1f9e76080 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, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -323,11 +323,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 *)); @@ -1177,6 +1176,26 @@ x_set_glyph_string_clipping (s) } +/* Set SRC's clipping for output of glyph string DST. This is called + when we are drawing DST's left_overhang or right_overhang only in + the area of SRC. */ + +static void +x_set_glyph_string_clipping_exactly (src, dst) + struct glyph_string *src, *dst; +{ + XRectangle r; + struct glyph_string *clip_head = src->clip_head; + struct glyph_string *clip_tail = src->clip_tail; + + /* This foces clipping just this glyph string. */ + src->clip_head = src->clip_tail = src; + get_glyph_string_clip_rect (src, &r); + src->clip_head = clip_head, src->clip_tail = clip_tail; + XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted); +} + + /* RIF: Compute left and right overhang of glyph string S. */ @@ -1351,7 +1370,7 @@ x_draw_composite_glyph_string_foreground (s) /* If first glyph of S has a left box line, start drawing the text of S to the right of that box line. */ - if (s->face->box != FACE_NO_BOX + if (s->face && s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) x = s->x + abs (s->face->box_line_width); else @@ -1373,17 +1392,18 @@ x_draw_composite_glyph_string_foreground (s) else { for (i = 0; i < s->nchars; i++, ++s->gidx) - { - XDrawString16 (s->display, s->window, s->gc, - x + s->cmp->offsets[s->gidx * 2], - s->ybase - s->cmp->offsets[s->gidx * 2 + 1], - s->char2b + i, 1); - if (s->face->overstrike) + if (s->face) + { XDrawString16 (s->display, s->window, s->gc, - x + s->cmp->offsets[s->gidx * 2] + 1, + x + s->cmp->offsets[s->gidx * 2], s->ybase - s->cmp->offsets[s->gidx * 2 + 1], s->char2b + i, 1); - } + if (s->face->overstrike) + XDrawString16 (s->display, s->window, s->gc, + x + s->cmp->offsets[s->gidx * 2] + 1, + s->ybase - s->cmp->offsets[s->gidx * 2 + 1], + s->char2b + i, 1); + } } } @@ -2608,15 +2628,22 @@ x_draw_glyph_string (s) { int relief_drawn_p = 0; - /* If S draws into the background of its successor, draw the - background of the successor first so that S can draw into it. + /* If S draws into the background of its successors, draw the + background of the successors 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) { - xassert (s->next->img == NULL); - x_set_glyph_string_gc (s->next); - x_set_glyph_string_clipping (s->next); - x_draw_glyph_string_background (s->next, 1); + int width; + struct glyph_string *next; + + for (width = 0, next = s->next; next; + width += next->width, next = next->next) + if (next->first_glyph->type != IMAGE_GLYPH) + { + x_set_glyph_string_gc (next); + x_set_glyph_string_clipping (next); + x_draw_glyph_string_background (next, 1); + } } /* Set up S->gc, set clipping and draw S. */ @@ -2636,6 +2663,12 @@ x_draw_glyph_string (s) x_set_glyph_string_clipping (s); relief_drawn_p = 1; } + else if ((s->prev && s->prev->hl != s->hl && s->left_overhang) + || (s->next && s->next->hl != s->hl && s->right_overhang)) + /* We must clip just this glyph. left_overhang part has already + drawn when s->prev was drawn, and right_overhang part will be + drawn later when s->next is drawn. */ + x_set_glyph_string_clipping_exactly (s, s); else x_set_glyph_string_clipping (s); @@ -2753,6 +2786,48 @@ x_draw_glyph_string (s) /* Draw relief if not yet drawn. */ if (!relief_drawn_p && s->face->box != FACE_NO_BOX) x_draw_glyph_string_box (s); + + if (s->prev) + { + struct glyph_string *prev; + + for (prev = s->prev; prev; prev = prev->prev) + if (prev->hl != s->hl + && prev->x + prev->width + prev->right_overhang > s->x) + { + /* As prev was drawn while clipped to its own area, we + must draw the right_overhang part using s->hl now. */ + enum draw_glyphs_face save = prev->hl; + + prev->hl = s->hl; + x_set_glyph_string_gc (prev); + x_set_glyph_string_clipping_exactly (s, prev); + x_draw_glyph_string_foreground (prev); + XSetClipMask (prev->display, prev->gc, None); + prev->hl = save; + } + } + + if (s->next) + { + struct glyph_string *next; + + for (next = s->next; next; next = next->next) + if (next->hl != s->hl + && next->x - next->left_overhang && s->next->hl != s->hl) + { + /* As next will be drawn while clipped to its own area, + we must draw the left_overhang part using s->hl now. */ + enum draw_glyphs_face save = next->hl; + + next->hl = s->hl; + x_set_glyph_string_gc (next); + x_set_glyph_string_clipping_exactly (s, next); + x_draw_glyph_string_foreground (next); + XSetClipMask (next->display, next->gc, None); + next->hl = save; + } + } } /* Reset clipping. */ @@ -3470,7 +3545,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; @@ -3598,6 +3673,9 @@ 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; @@ -3723,7 +3801,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; @@ -3731,7 +3808,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)) @@ -3800,7 +3877,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) @@ -5717,7 +5794,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. */ @@ -5726,7 +5803,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 */ @@ -6088,7 +6165,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; @@ -6248,31 +6326,13 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) } /* Keysyms directly mapped to Unicode characters. */ - if (keysym >= 0x01000100 && keysym <= 0x0110FFFF) - { - inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; - inev.ie.code = keysym & 0xFFFFFF; - goto done_keysym; - } - - /* Keysyms directly mapped to supported Unicode characters. */ - if ((keysym >= 0x01000100 && keysym <= 0x010033ff) - || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + if (keysym >= 0x01000000 && keysym <= 0x0110FFFF) { - int code, charset_id, c1, c2; - - if (keysym < 0x01002500) - charset_id = charset_mule_unicode_0100_24ff, - code = (keysym & 0xFFFF) - 0x100; - else if (keysym < 0x0100e000) - charset_id = charset_mule_unicode_2500_33ff, - code = (keysym & 0xFFFF) - 0x2500; + if (keysym < 0x01000080) + inev.ie.kind = ASCII_KEYSTROKE_EVENT; else - charset_id = charset_mule_unicode_e000_ffff, - code = (keysym & 0xFFFF) - 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); + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = keysym & 0xFFFFFF; goto done_keysym; } @@ -6493,6 +6553,12 @@ 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: @@ -6520,6 +6586,11 @@ 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: @@ -7164,7 +7235,7 @@ x_draw_hollow_cursor (w, row) /* Set clipping, draw the rectangle, and reset clipping again. */ x_clip_to_row (w, row, TEXT_AREA, gc); - XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h); + XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1); XSetClipMask (dpy, gc, None); } @@ -7454,9 +7525,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 @@ -7468,7 +7548,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); } @@ -7486,47 +7566,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) - { - BLOCK_INPUT; - XSync (dpy, False); - UNBLOCK_INPUT; - } + 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 @@ -7541,8 +7615,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 @@ -7555,7 +7634,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. */ @@ -7564,20 +7643,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 @@ -7636,7 +7719,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); @@ -7646,7 +7728,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 @@ -7714,7 +7796,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) { @@ -7746,7 +7828,7 @@ x_error_handler (display, error) Display *display; XErrorEvent *error; { - if (! NILP (x_error_message_string)) + if (x_error_message) x_error_catcher (display, error); else x_error_quitter (display, error); @@ -9337,7 +9419,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) @@ -9377,7 +9458,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) { @@ -9458,7 +9539,7 @@ x_list_fonts (f, pattern, size, maxnames) } } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (names) @@ -9549,7 +9630,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)) @@ -9559,7 +9640,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) @@ -9715,7 +9796,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 @@ -9754,7 +9834,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))) { @@ -9763,7 +9843,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; @@ -10188,6 +10268,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. */ @@ -10265,6 +10349,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; @@ -10334,18 +10433,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); @@ -10691,7 +10786,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 *); @@ -10699,12 +10793,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 @@ -10744,7 +10838,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 @@ -10929,6 +11023,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; @@ -10988,8 +11085,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;