X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/786a43d6cf102c185b05a31c10fba6b62b21511a..e6335dc16c9c8fad7dc630e9a8261e4178d8e2fa:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 8359cec011..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. @@ -68,6 +68,7 @@ Boston, MA 02110-1301, USA. */ /* #include */ #include "charset.h" +#include "character.h" #include "coding.h" #include "ccl.h" #include "frame.h" @@ -322,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 *)); @@ -815,7 +815,8 @@ XTreset_terminal_modes () /* Function prototypes of this page. */ -static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *)); +static int x_encode_char P_ ((int, XChar2b *, struct font_info *, + struct charset *, int *)); /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B @@ -894,13 +895,13 @@ x_per_char_metric (font, char2b, font_type) the two-byte form of C. Encoding is returned in *CHAR2B. */ static int -x_encode_char (c, char2b, font_info, two_byte_p) +x_encode_char (c, char2b, font_info, charset, two_byte_p) int c; XChar2b *char2b; struct font_info *font_info; + struct charset *charset; int *two_byte_p; { - int charset = CHAR_CHARSET (c); XFontStruct *font = font_info->font; /* FONT_INFO may define a scheme by which to encode byte1 and byte2. @@ -914,31 +915,31 @@ x_encode_char (c, char2b, font_info, two_byte_p) check_ccl_update (ccl); if (CHARSET_DIMENSION (charset) == 1) { - ccl->reg[0] = charset; + ccl->reg[0] = CHARSET_ID (charset); ccl->reg[1] = char2b->byte2; ccl->reg[2] = -1; } else { - ccl->reg[0] = charset; + ccl->reg[0] = CHARSET_ID (charset); ccl->reg[1] = char2b->byte1; ccl->reg[2] = char2b->byte2; } - ccl_driver (ccl, NULL, NULL, 0, 0, NULL); + ccl_driver (ccl, NULL, NULL, 0, 0, Qnil); /* We assume that MSBs are appropriately set/reset by CCL program. */ if (font->max_byte1 == 0) /* 1-byte font */ - char2b->byte1 = 0, char2b->byte2 = ccl->reg[1]; + STORE_XCHAR2B (char2b, 0, ccl->reg[1]); else - char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2]; + STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]); } - else if (font_info->encoding[charset]) + else if (font_info->encoding_type) { /* Fixed encoding scheme. See fontset.h for the meaning of the encoding numbers. */ - int enc = font_info->encoding[charset]; + unsigned char enc = font_info->encoding_type; if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2) @@ -1066,9 +1067,9 @@ x_set_mouse_face_gc (s) face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); if (s->first_glyph->type == CHAR_GLYPH) - face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch); + face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil); else - face_id = FACE_FOR_CHAR (s->f, face, 0); + face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); s->face = FACE_FROM_ID (s->f, face_id); PREPARE_FACE_FOR_DISPLAY (s->f, s->face); @@ -1175,9 +1176,28 @@ 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. If S is a glyph - string for a composition, assume overhangs don't exist. */ + Compute left and right overhang of glyph string S. */ static void x_compute_glyph_string_overhangs (s) @@ -1193,6 +1213,11 @@ x_compute_glyph_string_overhangs (s) s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; } + else if (s->cmp) + { + s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; + s->left_overhang = - s->cmp->lbearing; + } } @@ -1345,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 @@ -1367,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); + } } } @@ -2602,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. */ @@ -2630,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); @@ -2747,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. */ @@ -3464,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; @@ -3592,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; @@ -3717,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; @@ -3725,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)) @@ -3794,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) @@ -5711,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. */ @@ -5720,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 */ @@ -6082,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; @@ -6241,24 +6325,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) goto done_keysym; } - /* Keysyms directly mapped to supported Unicode characters. */ - if ((keysym >= 0x01000100 && keysym <= 0x010033ff) - || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + /* Keysyms directly mapped to Unicode characters. */ + 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; } @@ -6371,38 +6445,39 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) register int c; int nchars, len; - /* The input should be decoded with `coding_system' - which depends on which X*LookupString function - we used just above and the locale. */ - setup_coding_system (coding_system, &coding); - coding.src_multibyte = 0; - coding.dst_multibyte = 1; - /* The input is converted to events, thus we can't - handle composition. Anyway, there's no XIM that - gives us composition information. */ - coding.composing = COMPOSITION_DISABLED; - - for (i = 0; i < nbytes; i++) + for (i = 0, nchars = 0; i < nbytes; i++) { + if (ASCII_BYTE_P (copy_bufptr[i])) + nchars++; STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); } - { - /* Decode the input data. */ - int require; - unsigned char *p; - - require = decoding_buffer_size (&coding, nbytes); - p = (unsigned char *) alloca (require); - coding.mode |= CODING_MODE_LAST_BLOCK; - /* We explicitly disable composition handling because - key data should not contain any composition sequence. */ - coding.composing = COMPOSITION_DISABLED; - decode_coding (&coding, copy_bufptr, p, nbytes, require); - nbytes = coding.produced; - nchars = coding.produced_char; - copy_bufptr = p; - } + if (nchars < nbytes) + { + /* Decode the input data. */ + int require; + unsigned char *p; + + /* The input should be decoded with `coding_system' + which depends on which X*LookupString function + we used just above and the locale. */ + setup_coding_system (coding_system, &coding); + coding.src_multibyte = 0; + coding.dst_multibyte = 1; + /* The input is converted to events, thus we can't + handle composition. Anyway, there's no XIM that + gives us composition information. */ + coding.common_flags &= ~CODING_ANNOTATION_MASK; + + require = MAX_MULTIBYTE_LENGTH * nbytes; + coding.destination = alloca (require); + coding.dst_bytes = require; + coding.mode |= CODING_MODE_LAST_BLOCK; + decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); + nbytes = coding.produced; + nchars = coding.produced_char; + copy_bufptr = coding.destination; + } /* Convert the input data to a sequence of character events. */ @@ -6478,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: @@ -6505,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: @@ -7149,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); } @@ -7362,15 +7448,30 @@ x_bitmap_icon (f, file) /* Create the GNU bitmap and mask if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) { + int rc = -1; + #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id - = x_create_bitmap_from_xpm_data (f, gnu_bits); +#ifdef USE_GTK + if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + return 0; #else - FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id - = x_create_bitmap_from_data (f, gnu_bits, - gnu_width, gnu_height); -#endif /* (HAVE_XPM) && defined (HAVE_X_WINDOWS) */ - x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); + 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, @@ -7424,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. + + The reason we use a stack is that x_catch_error/x_uncatch_error can + be called from a signal handler. +*/ -static Lisp_Object x_error_message_string; +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 @@ -7438,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); } @@ -7456,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 @@ -7511,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 @@ -7525,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. */ @@ -7534,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 () { - unbind_to (count, Qnil); + while (x_error_message) + x_uncatch_errors (); +} + +/* Nonzero if x_catch_errors has been done and not yet canceled. */ + +int +x_catching_errors () +{ + return x_error_message != 0; } #if 0 @@ -7606,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); @@ -7616,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 @@ -7684,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) { @@ -7716,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); @@ -7789,11 +7901,16 @@ x_new_font (f, fontname) register char *fontname; { struct font_info *fontp - = FS_LOAD_FONT (f, 0, fontname, -1); + = FS_LOAD_FONT (f, fontname); if (!fontp) return Qnil; + if (FRAME_FONT (f) == (XFontStruct *) (fontp->font)) + /* This font is already set in frame F. There's nothing more to + do. */ + return build_string (fontp->full_name); + FRAME_FONT (f) = (XFontStruct *) (fontp->font); FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset; FRAME_FONTSET (f) = -1; @@ -7837,33 +7954,45 @@ x_new_font (f, fontname) return build_string (fontp->full_name); } -/* Give frame F the fontset named FONTSETNAME as its default font, and - return the full name of that fontset. FONTSETNAME may be a wildcard - pattern; in that case, we choose some fontset that fits the pattern. - The return value shows which fontset we chose. */ +/* Give frame F the fontset named FONTSETNAME as its default fontset, + and return the full name of that fontset. FONTSETNAME may be a + wildcard pattern; in that case, we choose some fontset that fits + the pattern. FONTSETNAME may be a font name for ASCII characters; + in that case, we create a fontset from that font name. + + The return value shows which fontset we chose. + If FONTSETNAME specifies the default fontset, return Qt. + If an ASCII font in the specified fontset can't be loaded, return + Qnil. */ Lisp_Object x_new_fontset (f, fontsetname) struct frame *f; - char *fontsetname; + Lisp_Object fontsetname; { - int fontset = fs_query_fontset (build_string (fontsetname), 0); + int fontset = fs_query_fontset (fontsetname, 0); Lisp_Object result; - if (fontset < 0) - return Qnil; - - if (FRAME_FONTSET (f) == fontset) + if (fontset > 0 && f->output_data.x->fontset == fontset) /* This fontset is already set in frame F. There's nothing more to do. */ return fontset_name (fontset); + else if (fontset == 0) + /* The default fontset can't be the default font. */ + return Qt; - result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); + if (fontset > 0) + result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); + else + result = x_new_font (f, SDATA (fontsetname)); if (!STRINGP (result)) /* Can't load ASCII font. */ return Qnil; + if (fontset < 0) + fontset = new_fontset_from_font_name (result); + /* Since x_new_font doesn't update any fontset information, do it now. */ FRAME_FONTSET (f) = fontset; @@ -7873,7 +8002,7 @@ x_new_fontset (f, fontsetname) xic_set_xfontset (f, SDATA (fontset_ascii (fontset))); #endif - return build_string (fontsetname); + return fontset_name (fontset); } @@ -9271,7 +9400,7 @@ x_get_font_info (f, font_idx) If SIZE is > 0, it is the size (maximum bounds width) of fonts to be listed. - SIZE < 0 means include scalable fonts. + SIZE < 0 means include auto scaled fonts. Frame F null means we have not yet created any frame on X, and consult the first display in x_display_list. MAXNAMES sets a limit @@ -9290,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) @@ -9330,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) { @@ -9411,7 +9539,7 @@ x_list_fonts (f, pattern, size, maxnames) } } - x_uncatch_errors (dpy, count); + x_uncatch_errors (); UNBLOCK_INPUT; if (names) @@ -9502,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)) @@ -9512,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) @@ -9668,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 @@ -9707,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))) { @@ -9716,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; @@ -9746,6 +9873,7 @@ x_load_font (f, fontname, size) bzero (fontp, sizeof (*fontp)); fontp->font = font; fontp->font_idx = i; + fontp->charset = -1; /* fs_load_font sets it. */ fontp->name = (char *) xmalloc (strlen (fontname) + 1); bcopy (fontname, fontp->name, strlen (fontname) + 1); @@ -9857,10 +9985,10 @@ x_load_font (f, fontname, size) the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, 2:0xA020..0xFF7F). For the moment, we don't know which charset - uses this font. So, we set information in fontp->encoding[1] + uses this font. So, we set information in fontp->encoding_type which is never used by any charset. If mapping can't be decided, set FONT_ENCODING_NOT_DECIDED. */ - fontp->encoding[1] + fontp->encoding_type = (font->max_byte1 == 0 /* 1-byte font */ ? (font->min_char_or_byte2 < 0x80 @@ -9960,6 +10088,160 @@ x_find_ccl_program (fontp) } +/* Return a char-table whose elements are t if the font FONT_INFO + contains a glyph for the corresponding character, and nil if + not. */ + +Lisp_Object +x_get_font_repertory (f, font_info) + FRAME_PTR f; + struct font_info *font_info; +{ + XFontStruct *font = (XFontStruct *) font_info->font; + Lisp_Object table; + int min_byte1, max_byte1, min_byte2, max_byte2; + int c; + struct charset *charset = CHARSET_FROM_ID (font_info->charset); + int offset = CHARSET_OFFSET (charset); + + table = Fmake_char_table (Qnil, Qnil); + + min_byte1 = font->min_byte1; + max_byte1 = font->max_byte1; + min_byte2 = font->min_char_or_byte2; + max_byte2 = font->max_char_or_byte2; + if (min_byte1 == 0 && max_byte1 == 0) + { + if (! font->per_char || font->all_chars_exist == True) + { + if (offset >= 0) + char_table_set_range (table, offset + min_byte2, + offset + max_byte2, Qt); + else + for (; min_byte2 <= max_byte2; min_byte2++) + { + c = DECODE_CHAR (charset, min_byte2); + CHAR_TABLE_SET (table, c, Qt); + } + } + else + { + XCharStruct *pcm = font->per_char; + int from = -1; + int i; + + for (i = min_byte2; i <= max_byte2; i++, pcm++) + { + if (pcm->width == 0 && pcm->rbearing == pcm->lbearing) + { + if (from >= 0) + { + if (offset >= 0) + char_table_set_range (table, offset + from, + offset + i - 1, Qt); + else + for (; from < i; from++) + { + c = DECODE_CHAR (charset, from); + CHAR_TABLE_SET (table, c, Qt); + } + from = -1; + } + } + else if (from < 0) + from = i; + } + if (from >= 0) + { + if (offset >= 0) + char_table_set_range (table, offset + from, offset + i - 1, + Qt); + else + for (; from < i; from++) + { + c = DECODE_CHAR (charset, from); + CHAR_TABLE_SET (table, c, Qt); + } + } + } + } + else + { + if (! font->per_char || font->all_chars_exist == True) + { + int i, j; + + if (offset >= 0) + for (i = min_byte1; i <= max_byte1; i++) + char_table_set_range + (table, offset + ((i << 8) | min_byte2), + offset + ((i << 8) | max_byte2), Qt); + else + for (i = min_byte1; i <= max_byte1; i++) + for (j = min_byte2; j <= max_byte2; j++) + { + unsigned code = (i << 8) | j; + c = DECODE_CHAR (charset, code); + CHAR_TABLE_SET (table, c, Qt); + } + } + else + { + XCharStruct *pcm = font->per_char; + int i; + + for (i = min_byte1; i <= max_byte1; i++) + { + int from = -1; + int j; + + for (j = min_byte2; j <= max_byte2; j++, pcm++) + { + if (pcm->width == 0 && pcm->rbearing == pcm->lbearing) + { + if (from >= 0) + { + if (offset >= 0) + char_table_set_range + (table, offset + ((i << 8) | from), + offset + ((i << 8) | (j - 1)), Qt); + else + { + for (; from < j; from++) + { + unsigned code = (i << 8) | from; + c = ENCODE_CHAR (charset, code); + CHAR_TABLE_SET (table, c, Qt); + } + } + from = -1; + } + } + else if (from < 0) + from = j; + } + if (from >= 0) + { + if (offset >= 0) + char_table_set_range + (table, offset + ((i << 8) | from), + offset + ((i << 8) | (j - 1)), Qt); + else + { + for (; from < j; from++) + { + unsigned code = (i << 8) | from; + c = DECODE_CHAR (charset, code); + CHAR_TABLE_SET (table, c, Qt); + } + } + } + } + } + } + + return table; +} /*********************************************************************** Initialization @@ -9986,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. */ @@ -10063,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; @@ -10132,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); @@ -10489,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 *); @@ -10497,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 @@ -10542,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 @@ -10727,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; @@ -10786,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; @@ -10798,8 +11096,6 @@ syms_of_xterm () staticpro (&Qvendor_specific_keysyms); Qvendor_specific_keysyms = intern ("vendor-specific-keysyms"); - staticpro (&Qutf_8); - Qutf_8 = intern ("utf-8"); staticpro (&Qlatin_1); Qlatin_1 = intern ("latin-1");