X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/94cc397c541f50af6b049af6c42806daa2be2709..85bdc6d29e19aa1b155de0361286ec7593b8693f:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 77a1b3745f..4d74910fec 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5,10 +5,10 @@ This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ /* New display code by Gerd Moellmann . */ /* Xt features made by Fred Pierresteguy. */ @@ -68,15 +66,15 @@ Boston, MA 02110-1301, USA. */ /* #include */ #include "charset.h" +#include "character.h" #include "coding.h" -#include "ccl.h" #include "frame.h" #include "dispextern.h" #include "fontset.h" #include "termhooks.h" #include "termopts.h" #include "termchar.h" -#include "gnu.h" +#include "emacs-icon.h" #include "disptab.h" #include "buffer.h" #include "window.h" @@ -85,6 +83,8 @@ Boston, MA 02110-1301, USA. */ #include "process.h" #include "atimer.h" #include "keymap.h" +#include "font.h" +#include "fontset.h" #ifdef USE_X_TOOLKIT #include @@ -335,8 +335,6 @@ static void x_update_window_end P_ ((struct window *, int, int)); static int x_io_error_quitter P_ ((Display *)); static struct terminal *x_create_terminal P_ ((struct x_display_info *)); void x_delete_terminal P_ ((struct terminal *)); -static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); -static int x_compute_min_glyph_bounds P_ ((struct frame *)); static void x_update_end P_ ((struct frame *)); static void XTframe_up_to_date P_ ((struct frame *)); static void XTset_terminal_modes P_ ((struct terminal *)); @@ -460,6 +458,89 @@ x_display_info_for_display (dpy) return 0; } +#define OPAQUE 0xffffffff +#define OPACITY "_NET_WM_WINDOW_OPACITY" + +void +x_set_frame_alpha (f) + struct frame *f; +{ + struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display *dpy = FRAME_X_DISPLAY (f); + Window win = FRAME_OUTER_WINDOW (f); + double alpha = 1.0; + double alpha_min = 1.0; + unsigned long opac; + + if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc) + /* Since the WM decoration lies under the FRAME_OUTER_WINDOW, + we must treat the former instead of the latter. */ + win = FRAME_X_OUTPUT(f)->parent_desc; + + if (dpyinfo->x_highlight_frame == f) + alpha = f->alpha[0]; + else + alpha = f->alpha[1]; + + if (FLOATP (Vframe_alpha_lower_limit)) + alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit); + else if (INTEGERP (Vframe_alpha_lower_limit)) + alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0; + + if (alpha < 0.0) + return; + else if (alpha > 1.0) + alpha = 1.0; + else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0) + alpha = alpha_min; + + opac = alpha * OPAQUE; + + /* return unless necessary */ + { + unsigned char *data; + Atom actual; + int rc, format; + unsigned long n, left; + + x_catch_errors (dpy); + rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False), + 0L, 1L, False, XA_CARDINAL, + &actual, &format, &n, &left, + &data); + + if (rc == Success && actual != None) + if (*(unsigned long *)data == opac) + { + XFree ((void *) data); + x_uncatch_errors (); + return; + } + else + XFree ((void *) data); + x_uncatch_errors (); + } + + x_catch_errors (dpy); + XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False), + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &opac, 1L); + x_uncatch_errors (); +} + +int +x_display_pixel_height (dpyinfo) + struct x_display_info *dpyinfo; +{ + return HeightOfScreen (dpyinfo->screen); +} + +int +x_display_pixel_width (dpyinfo) + struct x_display_info *dpyinfo; +{ + return WidthOfScreen (dpyinfo->screen); +} /*********************************************************************** @@ -865,154 +946,6 @@ XTreset_terminal_modes (struct terminal *terminal) { } - - -/*********************************************************************** - Display Iterator - ***********************************************************************/ - -/* Function prototypes of this page. */ - -static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *)); - - -/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B - is not contained in the font. */ - -static XCharStruct * -x_per_char_metric (font, char2b, font_type) - XFontStruct *font; - XChar2b *char2b; - int font_type; /* unused on X */ -{ - /* The result metric information. */ - XCharStruct *pcm = NULL; - - xassert (font && char2b); - - if (font->per_char != NULL) - { - if (font->min_byte1 == 0 && font->max_byte1 == 0) - { - /* min_char_or_byte2 specifies the linear character index - corresponding to the first element of the per_char array, - max_char_or_byte2 is the index of the last character. A - character with non-zero CHAR2B->byte1 is not in the font. - A character with byte2 less than min_char_or_byte2 or - greater max_char_or_byte2 is not in the font. */ - if (char2b->byte1 == 0 - && char2b->byte2 >= font->min_char_or_byte2 - && char2b->byte2 <= font->max_char_or_byte2) - pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2; - } - else - { - /* If either min_byte1 or max_byte1 are nonzero, both - min_char_or_byte2 and max_char_or_byte2 are less than - 256, and the 2-byte character index values corresponding - to the per_char array element N (counting from 0) are: - - byte1 = N/D + min_byte1 - byte2 = N\D + min_char_or_byte2 - - where: - - D = max_char_or_byte2 - min_char_or_byte2 + 1 - / = integer division - \ = integer modulus */ - if (char2b->byte1 >= font->min_byte1 - && char2b->byte1 <= font->max_byte1 - && char2b->byte2 >= font->min_char_or_byte2 - && char2b->byte2 <= font->max_char_or_byte2) - { - pcm = (font->per_char - + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) - * (char2b->byte1 - font->min_byte1)) - + (char2b->byte2 - font->min_char_or_byte2)); - } - } - } - else - { - /* If the per_char pointer is null, all glyphs between the first - and last character indexes inclusive have the same - information, as given by both min_bounds and max_bounds. */ - if (char2b->byte2 >= font->min_char_or_byte2 - && char2b->byte2 <= font->max_char_or_byte2) - pcm = &font->max_bounds; - } - - return ((pcm == NULL - || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) - ? NULL : pcm); -} - - -/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is - the two-byte form of C. Encoding is returned in *CHAR2B. */ - -static int -x_encode_char (c, char2b, font_info, two_byte_p) - int c; - XChar2b *char2b; - struct font_info *font_info; - 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. - This may be either a program in a special encoder language or a - fixed encoding. */ - if (font_info->font_encoder) - { - /* 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; - ccl->reg[1] = char2b->byte2; - ccl->reg[2] = -1; - } - else - { - ccl->reg[0] = charset; - ccl->reg[1] = char2b->byte1; - ccl->reg[2] = char2b->byte2; - } - - ccl_driver (ccl, NULL, NULL, 0, 0, NULL); - - /* 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]; - else - char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2]; - } - else if (font_info->encoding[charset]) - { - /* Fixed encoding scheme. See fontset.h for the meaning of the - encoding numbers. */ - int enc = font_info->encoding[charset]; - - if ((enc == 1 || enc == 2) - && CHARSET_DIMENSION (charset) == 2) - char2b->byte1 |= 0x80; - - if (enc == 1 || enc == 3) - char2b->byte2 |= 0x80; - } - - if (two_byte_p) - *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; - - return FONT_TYPE_UNKNOWN; -} - - /*********************************************************************** Glyph display @@ -1050,7 +983,7 @@ static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, int, int, int, XRectangle *)); #if GLYPH_DEBUG -static void x_check_font P_ ((struct frame *, XFontStruct *)); +static void x_check_font P_ ((struct frame *, struct font *)); #endif @@ -1092,9 +1025,8 @@ x_set_cursor_gc (s) } IF_DEBUG (x_check_font (s->f, s->font)); - xgcv.font = s->font->fid; xgcv.graphics_exposures = False; - mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; + mask = GCForeground | GCBackground | GCGraphicsExposures; if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, @@ -1124,28 +1056,25 @@ 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); - /* If font in this face is same as S->font, use it. */ if (s->font == s->face->font) s->gc = s->face->gc; else { /* Otherwise construct scratch_cursor_gc with values from FACE - but font FONT. */ + except for FONT. */ XGCValues xgcv; unsigned long mask; xgcv.background = s->face->background; xgcv.foreground = s->face->foreground; - IF_DEBUG (x_check_font (s->f, s->font)); - xgcv.font = s->font->fid; xgcv.graphics_exposures = False; - mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures; + mask = GCForeground | GCBackground | GCGraphicsExposures; if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc) XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc, @@ -1155,8 +1084,8 @@ x_set_mouse_face_gc (s) = XCreateGC (s->display, s->window, mask, &xgcv); s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc; - } + } xassert (s->gc != 0); } @@ -1226,16 +1155,38 @@ x_set_glyph_string_gc (s) static INLINE void x_set_glyph_string_clipping (s) struct glyph_string *s; +{ + XRectangle *r = s->clip; + int n = get_glyph_string_clip_rects (s, r, 2); + + if (n > 0) + XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted); + s->num_clips = n; +} + + +/* 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; - get_glyph_string_clip_rect (s, &r); - XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted); + + r.x = src->x; + r.width = src->width; + r.y = src->y; + r.height = src->height; + dst->clip[0] = r; + dst->num_clips = 1; + 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) @@ -1244,12 +1195,22 @@ x_compute_glyph_string_overhangs (s) if (s->cmp == NULL && s->first_glyph->type == CHAR_GLYPH) { - XCharStruct cs; - int direction, font_ascent, font_descent; - XTextExtents16 (s->font, s->char2b, s->nchars, &direction, - &font_ascent, &font_descent, &cs); - s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; - s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; + unsigned *code = alloca (sizeof (unsigned) * s->nchars); + struct font *font = s->font; + struct font_metrics metrics; + int i; + + for (i = 0; i < s->nchars; i++) + code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2; + font->driver->text_extents (font, code, s->nchars, &metrics); + s->right_overhang = (metrics.rbearing > metrics.width + ? metrics.rbearing - metrics.width : 0); + s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0; + } + else if (s->cmp) + { + s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; + s->left_overhang = - s->cmp->lbearing; } } @@ -1342,54 +1303,21 @@ x_draw_glyph_string_foreground (s) } else { - char *char1b = (char *) s->char2b; - int boff = s->font_info->baseline_offset; - - if (s->font_info->vertical_centering) - boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff; + struct font *font = s->font; + int boff = font->baseline_offset; + int y; - /* If we can use 8-bit functions, condense S->char2b. */ - if (!s->two_byte_p) - for (i = 0; i < s->nchars; ++i) - char1b[i] = s->char2b[i].byte2; + if (font->vertical_centering) + boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff; - /* Draw text with XDrawString if background has already been - filled. Otherwise, use XDrawImageString. (Note that - 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. */ + y = s->ybase - boff; if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR)) - { - /* Draw characters with 16-bit or 8-bit functions. */ - if (s->two_byte_p) - XDrawString16 (s->display, s->window, s->gc, x, - s->ybase - boff, s->char2b, s->nchars); - else - XDrawString (s->display, s->window, s->gc, x, - s->ybase - boff, char1b, s->nchars); - } + font->driver->draw (s, 0, s->nchars, x, y, 0); else - { - if (s->two_byte_p) - XDrawImageString16 (s->display, s->window, s->gc, x, - s->ybase - boff, s->char2b, s->nchars); - else - XDrawImageString (s->display, s->window, s->gc, x, - s->ybase - boff, char1b, s->nchars); - } - + font->driver->draw (s, 0, s->nchars, x, y, 1); if (s->face->overstrike) - { - /* For overstriking (to simulate bold-face), draw the - characters again shifted to the right by one pixel. */ - if (s->two_byte_p) - XDrawString16 (s->display, s->window, s->gc, x + 1, - s->ybase - boff, s->char2b, s->nchars); - else - XDrawString (s->display, s->window, s->gc, x + 1, - s->ybase - boff, char1b, s->nchars); - } + font->driver->draw (s, 0, s->nchars, x + 1, y, 0); } } @@ -1399,43 +1327,77 @@ static void x_draw_composite_glyph_string_foreground (s) struct glyph_string *s; { - int i, x; + int i, j, x; + struct font *font = s->font; /* 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 + eabs (s->face->box_line_width); else x = s->x; - /* S is a glyph string for a composition. S->gidx is the index of - the first character drawn for glyphs of this composition. - S->gidx == 0 means we are drawing the very first character of + /* S is a glyph string for a composition. S->cmp_from is the index + of the first character drawn for glyphs of this composition. + S->cmp_from == 0 means we are drawing the very first character of this composition. */ /* Draw a rectangle for the composition if the font for the very first character of the composition could not be loaded. */ if (s->font_not_found_p) { - if (s->gidx == 0) + if (s->cmp_from == 0) XDrawRectangle (s->display, s->window, s->gc, x, s->y, s->width - 1, s->height - 1); } + else if (! s->first_glyph->u.cmp.automatic) + { + int y = s->ybase; + + for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++) + if (COMPOSITION_GLYPH (s->cmp, j) != '\t') + { + int xx = x + s->cmp->offsets[j * 2]; + int yy = y - s->cmp->offsets[j * 2 + 1]; + + font->driver->draw (s, j, j + 1, xx, yy, 0); + if (s->face->overstrike) + font->driver->draw (s, j, j + 1, xx + 1, yy, 0); + } + } else { - for (i = 0; i < s->nchars; i++, ++s->gidx) + Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); + Lisp_Object glyph; + int y = s->ybase; + int width = 0; + + for (i = j = s->cmp_from; i < s->cmp_to; i++) { - 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) - 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); + glyph = LGSTRING_GLYPH (gstring, i); + if (NILP (LGLYPH_ADJUSTMENT (glyph))) + width += LGLYPH_WIDTH (glyph); + else + { + int xoff, yoff, wadjust; + + if (j < i) + { + font->driver->draw (s, j, i, x, y, 0); + x += width; + } + xoff = LGLYPH_XOFF (glyph); + yoff = LGLYPH_YOFF (glyph); + wadjust = LGLYPH_WADJUST (glyph); + font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0); + x += wadjust; + j = i + 1; + width = 0; + } } + if (j < i) + font->driver->draw (s, j, i, x, y, 0); } } @@ -1471,8 +1433,8 @@ x_frame_of_widget (widget) /* Look for a frame with that top-level widget. Allocate the color on that frame to get the right gamma correction value. */ - for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) - if (GC_FRAMEP (XCAR (tail)) + for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) + if (FRAMEP (XCAR (tail)) && (f = XFRAME (XCAR (tail)), (FRAME_X_P (f) && f->output_data.nothing != 1 @@ -2683,15 +2645,27 @@ 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 < s->right_overhang; + 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); + if (next->first_glyph->type == STRETCH_GLYPH) + x_draw_stretch_glyph_string (next); + else + x_draw_glyph_string_background (next, 1); + next->num_clips = 0; + } } /* Set up S->gc, set clipping and draw S. */ @@ -2711,6 +2685,14 @@ x_draw_glyph_string (s) x_set_glyph_string_clipping (s); relief_drawn_p = 1; } + else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ + && !s->clip_tail + && ((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); @@ -2733,7 +2715,8 @@ x_draw_glyph_string (s) break; case COMPOSITE_GLYPH: - if (s->for_overlaps || s->gidx > 0) + if (s->for_overlaps || (s->cmp_from > 0 + && ! s->first_glyph->u.cmp.automatic)) s->background_filled_p = 1; else x_draw_glyph_string_background (s, 1); @@ -2749,41 +2732,61 @@ x_draw_glyph_string (s) /* Draw underline. */ if (s->face->underline_p) { - unsigned long tem, h; + unsigned long thickness, position; int y; - /* Get the underline thickness. Default is 1 pixel. */ - if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h)) - h = 1; - - y = s->y + s->height - h; - if (!x_underline_at_descent_line) - { - /* Get the underline position. This is the recommended - vertical offset in pixels from the baseline to the top of - the underline. This is a signed value according to the - specs, and its default is - - ROUND ((maximum descent) / 2), with - ROUND(x) = floor (x + 0.5) */ - - if (x_use_underline_position_properties - && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem)) - y = s->ybase + (long) tem; - else if (s->face->font) - y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2; - } - + if (s->prev && s->prev->face->underline_p) + { + /* We use the same underline style as the previous one. */ + thickness = s->prev->underline_thickness; + position = s->prev->underline_position; + } + else + { + /* Get the underline thickness. Default is 1 pixel. */ + if (s->font && s->font->underline_thickness > 0) + thickness = s->font->underline_thickness; + else + thickness = 1; + if (x_underline_at_descent_line) + position = (s->height - thickness) - (s->ybase - s->y); + else + { + /* Get the underline position. This is the recommended + vertical offset in pixels from the baseline to the top of + the underline. This is a signed value according to the + specs, and its default is + + ROUND ((maximum descent) / 2), with + ROUND(x) = floor (x + 0.5) */ + + if (x_use_underline_position_properties + && s->font && s->font->underline_position >= 0) + position = s->font->underline_position; + else if (s->font) + position = (s->font->descent + 1) / 2; + } + position = max (position, underline_minimum_offset); + } + /* Check the sanity of thickness and position. We should + avoid drawing underline out of the current line area. */ + if (s->y + s->height <= s->ybase + position) + position = (s->height - 1) - (s->ybase - s->y); + if (s->y + s->height < s->ybase + position + thickness) + thickness = (s->y + s->height) - (s->ybase + position); + s->underline_thickness = thickness; + s->underline_position = position; + y = s->ybase + position; if (s->face->underline_defaulted_p) XFillRectangle (s->display, s->window, s->gc, - s->x, y, s->background_width, h); + s->x, y, s->background_width, thickness); else { XGCValues xgcv; XGetGCValues (s->display, s->gc, GCForeground, &xgcv); XSetForeground (s->display, s->gc, s->face->underline_color); XFillRectangle (s->display, s->window, s->gc, - s->x, y, s->background_width, h); + s->x, y, s->background_width, thickness); XSetForeground (s->display, s->gc, xgcv.foreground); } } @@ -2830,10 +2833,61 @@ 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); + if (prev->first_glyph->type == CHAR_GLYPH) + x_draw_glyph_string_foreground (prev); + else + x_draw_composite_glyph_string_foreground (prev); + XSetClipMask (prev->display, prev->gc, None); + prev->hl = save; + prev->num_clips = 0; + } + } + + 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->x + s->width) + { + /* 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); + if (next->first_glyph->type == CHAR_GLYPH) + x_draw_glyph_string_foreground (next); + else + x_draw_composite_glyph_string_foreground (next); + XSetClipMask (next->display, next->gc, None); + next->hl = save; + next->num_clips = 0; + } + } } /* Reset clipping. */ XSetClipMask (s->display, s->gc, None); + s->num_clips = 0; } /* Shift display to make room for inserted glyphs. */ @@ -3209,6 +3263,7 @@ frame_highlight (f) f->output_data.x->border_pixel); UNBLOCK_INPUT; x_update_cursor (f, 1); + x_set_frame_alpha (f); } static void @@ -3224,6 +3279,7 @@ frame_unhighlight (f) f->output_data.x->border_tile); UNBLOCK_INPUT; x_update_cursor (f, 1); + x_set_frame_alpha (f); } /* The focus has changed. Update the frames as necessary to reflect @@ -3286,9 +3342,9 @@ x_focus_changed (type, state, dpyinfo, frame, bufp) /* Don't stop displaying the initial startup message for a switch-frame event we don't need. */ - if (GC_NILP (Vterminal_frame) - && GC_CONSP (Vframe_list) - && !GC_NILP (XCDR (Vframe_list))) + if (NILP (Vterminal_frame) + && CONSP (Vframe_list) + && !NILP (XCDR (Vframe_list))) { bufp->kind = FOCUS_IN_EVENT; XSETFRAME (bufp->frame_or_window, frame); @@ -3361,6 +3417,15 @@ x_detect_focus_change (dpyinfo, event, bufp) FOCUS_IMPLICIT : FOCUS_EXPLICIT), dpyinfo, frame, bufp); break; + + case ClientMessage: + if (event->xclient.message_type == dpyinfo->Xatom_XEMBED) + { + enum xembed_message msg = event->xclient.data.l[1]; + x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut), + FOCUS_EXPLICIT, dpyinfo, frame, bufp); + } + break; } } @@ -3398,7 +3463,7 @@ x_frame_rehighlight (dpyinfo) if (dpyinfo->x_focus_frame) { dpyinfo->x_highlight_frame - = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) + = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) : dpyinfo->x_focus_frame); if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame)) @@ -3939,15 +4004,13 @@ x_window_to_scroll_bar (display, window_id) window_id = (Window) xg_get_scroll_id_for_window (display, window_id); #endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */ - for (tail = Vframe_list; - XGCTYPE (tail) == Lisp_Cons; - tail = XCDR (tail)) + for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) { Lisp_Object frame, bar, condemned; frame = XCAR (tail); /* All elements of Vframe_list should be frames. */ - if (! GC_FRAMEP (frame)) + if (! FRAMEP (frame)) abort (); if (! FRAME_X_P (XFRAME (frame))) @@ -3959,9 +4022,9 @@ x_window_to_scroll_bar (display, window_id) for (bar = FRAME_SCROLL_BARS (XFRAME (frame)); /* This trick allows us to search both the ordinary and condemned scroll bar lists with one loop. */ - ! GC_NILP (bar) || (bar = condemned, + ! NILP (bar) || (bar = condemned, condemned = Qnil, - ! GC_NILP (bar)); + ! NILP (bar)); bar = XSCROLL_BAR (bar)->next) if (XSCROLL_BAR (bar)->x_window == window_id && FRAME_X_DISPLAY (XFRAME (frame)) == display) @@ -3983,9 +4046,7 @@ x_window_to_menu_bar (window) { Lisp_Object tail; - for (tail = Vframe_list; - XGCTYPE (tail) == Lisp_Cons; - tail = XCDR (tail)) + for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) { if (FRAME_X_P (XFRAME (XCAR (tail)))) { @@ -5397,7 +5458,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event) XEvent *event; struct input_event *emacs_event; { - if (! GC_WINDOWP (bar->window)) + if (! WINDOWP (bar->window)) abort (); emacs_event->kind = SCROLL_BAR_CLICK_EVENT; @@ -5492,7 +5553,7 @@ x_scroll_bar_note_movement (bar, event) XSETVECTOR (last_mouse_scroll_bar, bar); /* If we're dragging the bar, display it. */ - if (! GC_NILP (bar->dragging)) + if (! NILP (bar->dragging)) { /* Where should the handle be now? */ int new_start = event->xmotion.y - XINT (bar->dragging); @@ -5956,6 +6017,18 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) } #endif /* USE_TOOLKIT_SCROLL_BARS */ + /* XEmbed messages from the embedder (if any). */ + if (event.xclient.message_type + == dpyinfo->Xatom_XEMBED) + { + enum xembed_message msg = event.xclient.data.l[1]; + if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT) + x_detect_focus_change (dpyinfo, &event, &inev.ie); + + *finish = X_EVENT_GOTO_OUT; + goto done; + } + f = x_any_window_to_frame (dpyinfo, event.xclient.window); if (!f) goto OTHER; @@ -6369,41 +6442,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) goto done_keysym; } - /* Keysyms directly mapped to supported Unicode characters. */ - if ((keysym >= 0x01000000 && keysym <= 0x010033ff) - || (keysym >= 0x0100e000 && keysym <= 0x0100ffff)) + /* Keysyms directly mapped to Unicode characters. */ + if (keysym >= 0x01000000 && keysym <= 0x0110FFFF) { - 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); - } + if (keysym < 0x01000080) + inev.ie.kind = ASCII_KEYSTROKE_EVENT; 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); - } + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = keysym & 0xFFFFFF; goto done_keysym; } @@ -6508,54 +6554,54 @@ 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; - - if (nbytes > 0) + for (i = 0, nchars = 0; i < nbytes; i++) + { + if (ASCII_BYTE_P (copy_bufptr[i])) + nchars++; + STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); + } + + if (nchars < nbytes) { /* Decode the input data. */ int require; unsigned char *p; - for (i = 0; i < nbytes; i++) - { - STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - } - - require = decoding_buffer_size (&coding, nbytes); - p = (unsigned char *) alloca (require); + /* 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; - /* 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); + decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); nbytes = coding.produced; nchars = coding.produced_char; - copy_bufptr = p; + copy_bufptr = coding.destination; + } - /* Convert the input data to a sequence of - character events. */ - for (i = 0; i < nbytes; i += len) - { - if (nchars == nbytes) - c = copy_bufptr[i], len = 1; - else - c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, - nbytes - i, len); - inev.ie.kind = (SINGLE_BYTE_CHAR_P (c) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.ie.code = c; - kbd_buffer_store_event_hold (&inev.ie, hold_quit); - } + /* Convert the input data to a sequence of + character events. */ + for (i = 0; i < nbytes; i += len) + { + if (nchars == nbytes) + c = copy_bufptr[i], len = 1; + else + c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, + nbytes - i, len); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (c) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = c; + kbd_buffer_store_event_hold (&inev.ie, hold_quit); } count += nchars; @@ -6682,8 +6728,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if (f) { - /* Generate SELECT_WINDOW_EVENTs when needed. */ - if (!NILP (Vmouse_autoselect_window)) + /* Generate SELECT_WINDOW_EVENTs when needed. + Don't let popup menus influence things (bug#1261). */ + if (!NILP (Vmouse_autoselect_window) && !popup_activated ()) { Lisp_Object window; @@ -6739,13 +6786,20 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) case ConfigureNotify: f = x_top_window_to_frame (dpyinfo, event.xconfigure.window); +#ifdef USE_GTK + if (!f + && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window)) + && event.xconfigure.window == FRAME_X_WINDOW (f)) + { + xg_frame_resized (f, event.xconfigure.width, + event.xconfigure.height); + f = 0; + } +#endif if (f) { #ifndef USE_X_TOOLKIT -#ifdef USE_GTK - xg_resize_widgets (f, event.xconfigure.width, - event.xconfigure.height); -#else /* not USE_GTK */ +#ifndef USE_GTK /* If there is a pending resize for fullscreen, don't do this one, the right one will come later. The toolkit version doesn't seem to need this, but we @@ -6775,11 +6829,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } -#endif /* not USE_GTK */ -#endif FRAME_PIXEL_WIDTH (f) = event.xconfigure.width; FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height; +#endif /* not USE_GTK */ +#endif #ifdef USE_GTK /* GTK creates windows but doesn't map them. @@ -6868,6 +6922,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) else construct_mouse_click (&inev.ie, &event.xbutton, f); } + if (FRAME_X_EMBEDDED_P (f)) + xembed_send_message (f, event.xbutton.time, + XEMBED_REQUEST_FOCUS, 0, 0, 0); } else { @@ -6916,6 +6973,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit) if ( #ifdef USE_GTK ! popup_activated () + /* Gtk+ menus only react to the first three buttons. */ + && event.xbutton.button < 3 && #endif f && event.type == ButtonPress @@ -7070,7 +7129,9 @@ XTread_socket (terminal, expected, hold_quit) int count = 0; XEvent event; int event_found = 0; +#if 0 struct x_display_info *dpyinfo; +#endif if (interrupt_input_blocked) { @@ -7107,7 +7168,7 @@ XTread_socket (terminal, expected, hold_quit) if (terminal->display_info.x == XTread_socket_fake_io_error) { XTread_socket_fake_io_error = 0; - x_io_error_quitter (dpyinfo->display); + x_io_error_quitter (terminal->display_info.x->display); } #if 0 /* This loop is a noop now. */ @@ -7387,7 +7448,7 @@ x_draw_bar_cursor (w, row, width, kind) WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x), WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + row->height - width), - cursor_glyph->pixel_width, + min (FRAME_COLUMN_WIDTH (f), cursor_glyph->pixel_width), width); XSetClipMask (dpy, gc, None); @@ -7820,7 +7881,7 @@ x_connection_closed (dpy, error_message) && FRAME_X_P (XFRAME (minibuf_frame)) && ! EQ (frame, minibuf_frame) && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo) - Fdelete_frame (frame, Qt); + Fdelete_frame (frame, Qnoelisp); } /* Now delete all remaining frames on the dead display. @@ -7833,7 +7894,7 @@ x_connection_closed (dpy, error_message) /* Set this to t so that Fdelete_frame won't get confused trying to find a replacement. */ FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt; - Fdelete_frame (frame, Qt); + Fdelete_frame (frame, Qnoelisp); } /* We have to close the display to inform Xt that it doesn't @@ -7845,31 +7906,37 @@ x_connection_closed (dpy, error_message) M-x make-frame-on-display RET :1 RET will indefinitely wait in Xt for events for display `:1', opened - in the first class to make-frame-on-display. + in the first call to make-frame-on-display. Closing the display is reported to lead to a bus error on OpenWindows in certain situations. I suspect that is a bug in OpenWindows. I don't know how to circumvent it here. */ -#ifdef USE_X_TOOLKIT - /* If DPYINFO is null, this means we didn't open the display - in the first place, so don't try to close it. */ if (dpyinfo) { - extern void (*fatal_error_signal_hook) P_ ((void)); - fatal_error_signal_hook = x_fatal_error_signal; - XtCloseDisplay (dpy); - fatal_error_signal_hook = NULL; - } +#ifdef USE_X_TOOLKIT + /* If DPYINFO is null, this means we didn't open the display + in the first place, so don't try to close it. */ + { + extern void (*fatal_error_signal_hook) P_ ((void)); + fatal_error_signal_hook = x_fatal_error_signal; + XtCloseDisplay (dpy); + fatal_error_signal_hook = NULL; + } #endif #ifdef USE_GTK - if (dpyinfo) - xg_display_close (dpyinfo->display); + /* Due to bugs in some Gtk+ versions, just exit here if this + is the last display/terminal. */ + if (terminal_list->next_terminal == NULL) + { + fprintf (stderr, "%s\n", error_msg); + shut_down_emacs (0, 0, Qnil); + exit (70); + } + xg_display_close (dpyinfo->display); #endif - if (dpyinfo) - { /* Indicate that this display is dead. */ dpyinfo->display = 0; @@ -7879,7 +7946,11 @@ x_connection_closed (dpy, error_message) /* We have just closed all frames on this display. */ abort (); - x_delete_display (dpyinfo); + { + Lisp_Object tmp; + XSETTERMINAL (tmp, dpyinfo->terminal); + Fdelete_terminal (tmp, Qnoelisp); + } } x_uncatch_errors (); @@ -7900,10 +7971,9 @@ x_connection_closed (dpy, error_message) unbind_to (index, Qnil); clear_waiting_for_input (); - /* FIXME: This is an asynchronous interrupt w.r.t elisp, so signalling an - error might not be the best thing to do. I'd vote for creating an - elisp event and stuffing it in the queue so people can bind to it via - the global map. --Stef */ + /* Here, we absolutely have to use a non-local exit (e.g. signal, throw, + longjmp), because returning from this function would get us back into + Xlib's code which will directly call `exit'. */ error ("%s", error_msg); } @@ -7987,29 +8057,32 @@ x_io_error_quitter (display) /* Changing the font of the frame. */ -/* Give frame F the font named FONTNAME as its default font, and - return the full name of that font. FONTNAME may be a wildcard - pattern; in that case, we choose some font that fits the pattern. - The return value shows which font we chose. */ +/* Give frame F the font FONT-OBJECT as its default font. The return + value is FONT-OBJECT. FONTSET is an ID of the fontset for the + frame. If it is negative, generate a new fontset from + FONT-OBJECT. */ Lisp_Object -x_new_font (f, fontname) +x_new_font (f, font_object, fontset) struct frame *f; - register char *fontname; + Lisp_Object font_object; + int fontset; { - struct font_info *fontp - = FS_LOAD_FONT (f, 0, fontname, -1); + struct font *font = XFONT_OBJECT (font_object); - if (!fontp) - return Qnil; - - FRAME_FONT (f) = (XFontStruct *) (fontp->font); - FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset; - FRAME_FONTSET (f) = -1; + if (fontset < 0) + fontset = fontset_from_font (font_object); + FRAME_FONTSET (f) = fontset; + if (FRAME_FONT (f) == font) + /* This font is already set in frame F. There's nothing more to + do. */ + return font_object; - FRAME_COLUMN_WIDTH (f) = fontp->average_width; - FRAME_SPACE_WIDTH (f) = fontp->space_width; - FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f)); + FRAME_FONT (f) = font; + FRAME_BASELINE_OFFSET (f) = font->baseline_offset; + FRAME_COLUMN_WIDTH (f) = font->average_width; + FRAME_SPACE_WIDTH (f) = font->space_width; + FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font); compute_fringe_widths (f, 1); @@ -8026,16 +8099,8 @@ x_new_font (f, fontname) FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; } - /* Now make the frame display the given font. */ if (FRAME_X_WINDOW (f) != 0) { - XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, - FRAME_FONT (f)->fid); - XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc, - FRAME_FONT (f)->fid); - XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, - FRAME_FONT (f)->fid); - /* Don't change the size of a tip frame; there's no point in doing it because it's done in Fx_show_tip, and it leads to problems because the tip frame has no widget. */ @@ -8043,46 +8108,17 @@ x_new_font (f, fontname) x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); } - 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. */ - -Lisp_Object -x_new_fontset (f, fontsetname) - struct frame *f; - char *fontsetname; -{ - int fontset = fs_query_fontset (build_string (fontsetname), 0); - Lisp_Object result; - - if (fontset < 0) - return Qnil; - - if (FRAME_FONTSET (f) == fontset) - /* This fontset is already set in frame F. There's nothing more - to do. */ - return fontset_name (fontset); - - result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); - - if (!STRINGP (result)) - /* Can't load ASCII font. */ - return Qnil; - - /* Since x_new_font doesn't update any fontset information, do it now. */ - FRAME_FONTSET (f) = fontset; - #ifdef HAVE_X_I18N if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea))) - xic_set_xfontset (f, SDATA (fontset_ascii (fontset))); + { + BLOCK_INPUT; + xic_set_xfontset (f, SDATA (fontset_ascii (fontset))); + UNBLOCK_INPUT; + } #endif - return build_string (fontsetname); + return font_object; } @@ -8290,9 +8326,11 @@ xim_close_dpy (dpyinfo) XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb, NULL, EMACS_CLASS, xim_instantiate_callback, NULL); -#endif /* not HAVE_X11R6_XIM */ +#else /* not HAVE_X11R6_XIM */ + /* If we have X11R6 xim, this causes a double-free. */ if (dpyinfo->display) XCloseIM (dpyinfo->xim); +#endif /* HAVE_X11R6_XIM */ dpyinfo->xim = NULL; XFree (dpyinfo->xim_styles); } @@ -8320,8 +8358,8 @@ x_calc_absolute_position (f) /* 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 - - FRAME_PIXEL_WIDTH (f) + f->left_pos); + f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)) + - FRAME_PIXEL_WIDTH (f) + f->left_pos; { int height = FRAME_PIXEL_HEIGHT (f); @@ -8342,8 +8380,9 @@ x_calc_absolute_position (f) XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL); #endif - if (flags & YNegative) - f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos); + if (flags & YNegative) + f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)) + - height + f->top_pos; } /* The left_pos and top_pos @@ -8366,7 +8405,7 @@ x_set_offset (f, xoff, yoff, change_gravity) { int modified_top, modified_left; - if (change_gravity != 0) + if (change_gravity > 0) { FRAME_X_OUTPUT (f)->left_before_move = f->left_pos; FRAME_X_OUTPUT (f)->top_before_move = f->top_pos; @@ -8988,6 +9027,51 @@ XTframe_raise_lower (f, raise_flag) x_lower_frame (f); } +/* XEmbed implementation. */ + +void +xembed_set_info (f, flags) + struct frame *f; + enum xembed_info flags; +{ + Atom atom; + unsigned long data[2]; + + atom = XInternAtom (FRAME_X_DISPLAY (f), "_XEMBED_INFO", False); + + data[0] = XEMBED_VERSION; + data[1] = flags; + + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), atom, atom, + 32, PropModeReplace, (unsigned char *) data, 2); +} + +void +xembed_send_message (f, time, message, detail, data1, data2) + struct frame *f; + Time time; + enum xembed_message message; + long detail; + long data1; + long data2; +{ + XEvent event; + + event.xclient.type = ClientMessage; + event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc; + event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED; + event.xclient.format = 32; + event.xclient.data.l[0] = time; + event.xclient.data.l[1] = message; + event.xclient.data.l[2] = detail; + event.xclient.data.l[3] = data1; + event.xclient.data.l[4] = data2; + + XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc, + False, NoEventMask, &event); + XSync (FRAME_X_DISPLAY (f), False); +} + /* Change of visibility. */ /* This tries to wait until the frame is really visible. @@ -9020,6 +9104,7 @@ x_make_frame_visible (f) if we get to x_make_frame_visible a second time before the window gets really visible. */ if (! FRAME_ICONIFIED_P (f) + && ! FRAME_X_EMBEDDED_P (f) && ! f->output_data.x->asked_for_visible) x_set_offset (f, f->left_pos, f->top_pos, 0); @@ -9028,14 +9113,22 @@ x_make_frame_visible (f) if (! EQ (Vx_no_window_manager, Qt)) x_wm_set_window_state (f, NormalState); #ifdef USE_X_TOOLKIT - /* This was XtPopup, but that did nothing for an iconified frame. */ - XtMapWidget (f->output_data.x->widget); + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, XEMBED_MAPPED); + else + { + /* This was XtPopup, but that did nothing for an iconified frame. */ + XtMapWidget (f->output_data.x->widget); + } #else /* not USE_X_TOOLKIT */ #ifdef USE_GTK gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); #else - XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, XEMBED_MAPPED); + else + XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); #endif /* not USE_GTK */ #endif /* not USE_X_TOOLKIT */ #if 0 /* This seems to bring back scroll bars in the wrong places @@ -9076,7 +9169,9 @@ x_make_frame_visible (f) because the window manager may choose the position and we don't want to override it. */ - if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f) + if (! FRAME_VISIBLE_P (f) + && ! FRAME_ICONIFIED_P (f) + && ! FRAME_X_EMBEDDED_P (f) && f->win_gravity == NorthWestGravity && previously_visible) { @@ -9187,6 +9282,10 @@ x_make_frame_invisible (f) if (FRAME_GTK_OUTER_WIDGET (f)) gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f)); else +#else + if (FRAME_X_EMBEDDED_P (f)) + xembed_set_info (f, 0); + else #endif { @@ -9291,7 +9390,9 @@ x_iconify_frame (f) /* Make sure the X server knows where the window should be positioned, in case the user deiconifies with the window manager. */ - if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f)) + if (! FRAME_VISIBLE_P (f) + && ! FRAME_ICONIFIED_P (f) + && ! FRAME_X_EMBEDDED_P (f)) x_set_offset (f, f->left_pos, f->top_pos, 0); /* Since we don't know which revision of X we're running, we'll use both @@ -9354,6 +9455,12 @@ x_free_frame_resources (f) commands to the X server. */ if (dpyinfo->display) { + /* We must free faces before destroying windows because some + font-driver (e.g. xft) access a window while finishing a + face. */ + if (FRAME_FACE_CACHE (f)) + free_frame_faces (f); + if (f->output_data.x->icon_desc) XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc); @@ -9433,9 +9540,7 @@ x_free_frame_resources (f) XFlush (FRAME_X_DISPLAY (f)); } - if (f->output_data.x->saved_menu_event) - xfree (f->output_data.x->saved_menu_event); - + xfree (f->output_data.x->saved_menu_event); xfree (f->output_data.x); f->output_data.x = NULL; @@ -9523,10 +9628,10 @@ x_wm_set_size_hint (f, flags, user_position) size_hints.width_inc = FRAME_COLUMN_WIDTH (f); size_hints.height_inc = FRAME_LINE_HEIGHT (f); - size_hints.max_width - = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); - size_hints.max_height - = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); + size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f)) + - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); + size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f)) + - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); /* Calculate the base and minimum sizes. @@ -9719,316 +9824,6 @@ x_wm_set_icon_position (f, icon_x, icon_y) Fonts ***********************************************************************/ -/* Return a pointer to struct font_info of font FONT_IDX of frame F. */ - -struct font_info * -x_get_font_info (f, font_idx) - FRAME_PTR f; - int font_idx; -{ - return (FRAME_X_FONT_TABLE (f) + font_idx); -} - - -/* Return a list of names of available fonts matching PATTERN on frame F. - - If SIZE is > 0, it is the size (maximum bounds width) of fonts - to be listed. - - SIZE < 0 means include scalable 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 - on how many fonts to match. */ - -Lisp_Object -x_list_fonts (f, pattern, size, maxnames) - struct frame *f; - Lisp_Object pattern; - int size; - int maxnames; -{ - Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil; - Lisp_Object tem, second_best; - struct x_display_info *dpyinfo - = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list; - Display *dpy = dpyinfo->display; - int try_XLoadQueryFont = 0; - int allow_auto_scaled_font = 0; - - if (size < 0) - { - allow_auto_scaled_font = 1; - size = 0; - } - - patterns = Fassoc (pattern, Valternate_fontname_alist); - if (NILP (patterns)) - patterns = Fcons (pattern, Qnil); - - if (maxnames == 1 && !size) - /* We can return any single font matching PATTERN. */ - try_XLoadQueryFont = 1; - - for (; CONSP (patterns); patterns = XCDR (patterns)) - { - int num_fonts; - char **names = NULL; - - pattern = XCAR (patterns); - /* See if we cached the result for this particular query. - The cache is an alist of the form: - ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */ - tem = XCDR (dpyinfo->name_list_element); - key = Fcons (Fcons (pattern, make_number (maxnames)), - allow_auto_scaled_font ? Qt : Qnil); - list = Fassoc (key, tem); - if (!NILP (list)) - { - list = Fcdr_safe (list); - /* We have a cashed list. Don't have to get the list again. */ - goto label_cached; - } - - /* At first, put PATTERN in the cache. */ - - BLOCK_INPUT; - x_catch_errors (dpy); - - if (try_XLoadQueryFont) - { - XFontStruct *font; - unsigned long value; - - font = XLoadQueryFont (dpy, SDATA (pattern)); - if (x_had_errors_p (dpy)) - { - /* This error is perhaps due to insufficient memory on X - server. Let's just ignore it. */ - font = NULL; - x_clear_errors (dpy); - } - - if (font - && XGetFontProperty (font, XA_FONT, &value)) - { - char *name = (char *) XGetAtomName (dpy, (Atom) value); - int len = strlen (name); - char *tmp; - - /* If DXPC (a Differential X Protocol Compressor) - Ver.3.7 is running, XGetAtomName will return null - string. We must avoid such a name. */ - if (len == 0) - try_XLoadQueryFont = 0; - else - { - num_fonts = 1; - names = (char **) alloca (sizeof (char *)); - /* Some systems only allow alloca assigned to a - simple var. */ - tmp = (char *) alloca (len + 1); names[0] = tmp; - bcopy (name, names[0], len + 1); - XFree (name); - } - } - else - try_XLoadQueryFont = 0; - - if (font) - XFreeFont (dpy, font); - } - - if (!try_XLoadQueryFont) - { - /* We try at least 10 fonts because XListFonts will return - auto-scaled fonts at the head. */ - if (maxnames < 0) - { - int limit; - - for (limit = 500;;) - { - names = XListFonts (dpy, SDATA (pattern), limit, &num_fonts); - if (num_fonts == limit) - { - BLOCK_INPUT; - XFreeFontNames (names); - UNBLOCK_INPUT; - limit *= 2; - } - else - break; - } - } - else - names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10), - &num_fonts); - - if (x_had_errors_p (dpy)) - { - /* This error is perhaps due to insufficient memory on X - server. Let's just ignore it. */ - names = NULL; - x_clear_errors (dpy); - } - } - - x_uncatch_errors (); - UNBLOCK_INPUT; - - if (names) - { - int i; - - /* Make a list of all the fonts we got back. - Store that in the font cache for the display. */ - for (i = 0; i < num_fonts; i++) - { - int width = 0; - char *p = names[i]; - int average_width = -1, resx = 0, dashes = 0; - - /* Count the number of dashes in NAMES[I]. If there are - 14 dashes, the field value following 9th dash - (RESOLUTION_X) is nonzero, and the field value - following 12th dash (AVERAGE_WIDTH) is 0, this is a - auto-scaled font which is usually too ugly to be used - for editing. Let's ignore it. */ - while (*p) - if (*p++ == '-') - { - dashes++; - if (dashes == 7) /* PIXEL_SIZE field */ - width = atoi (p); - else if (dashes == 9) - resx = atoi (p); - else if (dashes == 12) /* AVERAGE_WIDTH field */ - average_width = atoi (p); - } - - if (allow_auto_scaled_font - || dashes < 14 || average_width != 0 || resx == 0) - { - tem = build_string (names[i]); - if (NILP (Fassoc (tem, list))) - { - if (STRINGP (Vx_pixel_size_width_font_regexp) - && ((fast_c_string_match_ignore_case - (Vx_pixel_size_width_font_regexp, names[i])) - >= 0)) - /* We can set the value of PIXEL_SIZE to the - width of this font. */ - list = Fcons (Fcons (tem, make_number (width)), list); - else - /* For the moment, width is not known. */ - list = Fcons (Fcons (tem, Qnil), list); - } - } - } - - if (!try_XLoadQueryFont) - { - BLOCK_INPUT; - XFreeFontNames (names); - UNBLOCK_INPUT; - } - } - - /* Now store the result in the cache. */ - XSETCDR (dpyinfo->name_list_element, - Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element))); - - label_cached: - if (NILP (list)) continue; /* Try the remaining alternatives. */ - - newlist = second_best = Qnil; - /* Make a list of the fonts that have the right width. */ - for (; CONSP (list); list = XCDR (list)) - { - int found_size; - - tem = XCAR (list); - - if (!CONSP (tem) || NILP (XCAR (tem))) - continue; - if (!size) - { - newlist = Fcons (XCAR (tem), newlist); - continue; - } - - if (!INTEGERP (XCDR (tem))) - { - /* Since we have not yet known the size of this font, we - must try slow function call XLoadQueryFont. */ - XFontStruct *thisinfo; - - BLOCK_INPUT; - x_catch_errors (dpy); - thisinfo = XLoadQueryFont (dpy, - SDATA (XCAR (tem))); - if (x_had_errors_p (dpy)) - { - /* This error is perhaps due to insufficient memory on X - server. Let's just ignore it. */ - thisinfo = NULL; - x_clear_errors (dpy); - } - x_uncatch_errors (); - UNBLOCK_INPUT; - - if (thisinfo) - { - XSETCDR (tem, - (thisinfo->min_bounds.width == 0 - ? make_number (0) - : make_number (thisinfo->max_bounds.width))); - BLOCK_INPUT; - XFreeFont (dpy, thisinfo); - UNBLOCK_INPUT; - } - else - /* For unknown reason, the previous call of XListFont had - returned a font which can't be opened. Record the size - as 0 not to try to open it again. */ - XSETCDR (tem, make_number (0)); - } - - found_size = XINT (XCDR (tem)); - if (found_size == size) - newlist = Fcons (XCAR (tem), newlist); - else if (found_size > 0) - { - if (NILP (second_best)) - second_best = tem; - else if (found_size < size) - { - if (XINT (XCDR (second_best)) > size - || XINT (XCDR (second_best)) < found_size) - second_best = tem; - } - else - { - if (XINT (XCDR (second_best)) > size - && XINT (XCDR (second_best)) > found_size) - second_best = tem; - } - } - } - if (!NILP (newlist)) - break; - else if (!NILP (second_best)) - { - newlist = Fcons (XCAR (second_best), Qnil); - break; - } - } - - return newlist; -} - - #if GLYPH_DEBUG /* Check that FONT is valid on frame F. It is if it can be found in F's @@ -10037,391 +9832,17 @@ x_list_fonts (f, pattern, size, maxnames) static void x_check_font (f, font) struct frame *f; - XFontStruct *font; + struct font *font; { - int i; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - - xassert (font != NULL); - - for (i = 0; i < dpyinfo->n_fonts; i++) - if (dpyinfo->font_table[i].name - && font == dpyinfo->font_table[i].font) - break; + Lisp_Object frame; - xassert (i < dpyinfo->n_fonts); + xassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX])); + if (font->driver->check) + xassert (font->driver->check (f, font) == 0); } #endif /* GLYPH_DEBUG != 0 */ -/* Set *W to the minimum width, *H to the minimum font height of FONT. - Note: There are (broken) X fonts out there with invalid XFontStruct - min_bounds contents. For example, handa@etl.go.jp reports that - "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts - have font->min_bounds.width == 0. */ - -static INLINE void -x_font_min_bounds (font, w, h) - XFontStruct *font; - int *w, *h; -{ - *h = FONT_HEIGHT (font); - *w = font->min_bounds.width; - - /* Try to handle the case where FONT->min_bounds has invalid - contents. Since the only font known to have invalid min_bounds - is fixed-width, use max_bounds if min_bounds seems to be invalid. */ - if (*w <= 0) - *w = font->max_bounds.width; -} - - -/* Compute the smallest character width and smallest font height over - all fonts available on frame F. Set the members smallest_char_width - and smallest_font_height in F's x_display_info structure to - the values computed. Value is non-zero if smallest_font_height or - smallest_char_width become smaller than they were before. */ - -static int -x_compute_min_glyph_bounds (f) - struct frame *f; -{ - int i; - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - XFontStruct *font; - int old_width = dpyinfo->smallest_char_width; - int old_height = dpyinfo->smallest_font_height; - - dpyinfo->smallest_font_height = 100000; - dpyinfo->smallest_char_width = 100000; - - for (i = 0; i < dpyinfo->n_fonts; ++i) - if (dpyinfo->font_table[i].name) - { - struct font_info *fontp = dpyinfo->font_table + i; - int w, h; - - font = (XFontStruct *) fontp->font; - xassert (font != (XFontStruct *) ~0); - x_font_min_bounds (font, &w, &h); - - dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h); - dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w); - } - - xassert (dpyinfo->smallest_char_width > 0 - && dpyinfo->smallest_font_height > 0); - - return (dpyinfo->n_fonts == 1 - || dpyinfo->smallest_char_width < old_width - || dpyinfo->smallest_font_height < old_height); -} - - -/* Load font named FONTNAME of the size SIZE for frame F, and return a - pointer to the structure font_info while allocating it dynamically. - If SIZE is 0, load any size of font. - If loading is failed, return NULL. */ - -struct font_info * -x_load_font (f, fontname, size) - struct frame *f; - register char *fontname; - int size; -{ - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - Lisp_Object font_names; - - /* 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 - we already have by comparing names. */ - font_names = x_list_fonts (f, build_string (fontname), size, 1); - - if (!NILP (font_names)) - { - Lisp_Object tail; - int i; - - for (i = 0; i < dpyinfo->n_fonts; i++) - for (tail = font_names; CONSP (tail); tail = XCDR (tail)) - if (dpyinfo->font_table[i].name - && (!strcmp (dpyinfo->font_table[i].name, - SDATA (XCAR (tail))) - || !strcmp (dpyinfo->font_table[i].full_name, - SDATA (XCAR (tail))))) - return (dpyinfo->font_table + i); - } - - /* Load the font and add it to the table. */ - { - char *full_name; - XFontStruct *font; - struct font_info *fontp; - unsigned long value; - int i; - - /* If we have found fonts by x_list_font, load one of them. If - not, we still try to load a font by the name given as FONTNAME - because XListFonts (called in x_list_font) of some X server has - a bug of not finding a font even if the font surely exists and - is loadable by XLoadQueryFont. */ - if (size > 0 && !NILP (font_names)) - fontname = (char *) SDATA (XCAR (font_names)); - - BLOCK_INPUT; - x_catch_errors (FRAME_X_DISPLAY (f)); - font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname); - if (x_had_errors_p (FRAME_X_DISPLAY (f))) - { - /* This error is perhaps due to insufficient memory on X - server. Let's just ignore it. */ - font = NULL; - x_clear_errors (FRAME_X_DISPLAY (f)); - } - x_uncatch_errors (); - UNBLOCK_INPUT; - if (!font) - return NULL; - - /* Find a free slot in the font table. */ - for (i = 0; i < dpyinfo->n_fonts; ++i) - if (dpyinfo->font_table[i].name == NULL) - break; - - /* If no free slot found, maybe enlarge the font table. */ - if (i == dpyinfo->n_fonts - && dpyinfo->n_fonts == dpyinfo->font_table_size) - { - int sz; - dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size); - sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table; - dpyinfo->font_table - = (struct font_info *) xrealloc (dpyinfo->font_table, sz); - } - - fontp = dpyinfo->font_table + i; - if (i == dpyinfo->n_fonts) - ++dpyinfo->n_fonts; - - /* Now fill in the slots of *FONTP. */ - BLOCK_INPUT; - bzero (fontp, sizeof (*fontp)); - fontp->font = font; - fontp->font_idx = i; - 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)) - { - char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value); - char *p = name; - int dashes = 0; - - /* Count the number of dashes in the "full name". - If it is too few, this isn't really the font's full name, - so don't use it. - In X11R4, the fonts did not come with their canonical names - stored in them. */ - while (*p) - { - if (*p == '-') - dashes++; - p++; - } - - if (dashes >= 13) - { - full_name = (char *) xmalloc (p - name + 1); - bcopy (name, full_name, p - name + 1); - } - - XFree (name); - } - - if (full_name != 0) - fontp->full_name = full_name; - else - fontp->full_name = fontp->name; - - fontp->size = font->max_bounds.width; - fontp->height = FONT_HEIGHT (font); - - if (NILP (font_names)) - { - /* We come here because of a bug of XListFonts mentioned at - the head of this block. Let's store this information in - the cache for x_list_fonts. */ - Lisp_Object lispy_name = build_string (fontname); - Lisp_Object lispy_full_name = build_string (fontp->full_name); - Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)), - Qnil); - - XSETCDR (dpyinfo->name_list_element, - Fcons (Fcons (key, - Fcons (Fcons (lispy_full_name, - make_number (fontp->size)), - Qnil)), - XCDR (dpyinfo->name_list_element))); - if (full_name) - { - key = Fcons (Fcons (lispy_full_name, make_number (256)), - Qnil); - XSETCDR (dpyinfo->name_list_element, - Fcons (Fcons (key, - Fcons (Fcons (lispy_full_name, - make_number (fontp->size)), - Qnil)), - XCDR (dpyinfo->name_list_element))); - } - } - - /* The slot `encoding' specifies how to map a character - code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to - 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] - which is never used by any charset. If mapping can't be - decided, set FONT_ENCODING_NOT_DECIDED. */ - fontp->encoding[1] - = (font->max_byte1 == 0 - /* 1-byte font */ - ? (font->min_char_or_byte2 < 0x80 - ? (font->max_char_or_byte2 < 0x80 - ? 0 /* 0x20..0x7F */ - : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */ - : 1) /* 0xA0..0xFF */ - /* 2-byte font */ - : (font->min_byte1 < 0x80 - ? (font->max_byte1 < 0x80 - ? (font->min_char_or_byte2 < 0x80 - ? (font->max_char_or_byte2 < 0x80 - ? 0 /* 0x2020..0x7F7F */ - : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */ - : 3) /* 0x20A0..0x7FFF */ - : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */ - : (font->min_char_or_byte2 < 0x80 - ? (font->max_char_or_byte2 < 0x80 - ? 2 /* 0xA020..0xFF7F */ - : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */ - : 1))); /* 0xA0A0..0xFFFF */ - - fontp->baseline_offset - = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) - ? (long) value : 0); - fontp->relative_compose - = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) - ? (long) value : 0); - fontp->default_ascent - = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) - ? (long) value : 0); - - /* Set global flag fonts_changed_p to non-zero if the font loaded - has a character with a smaller width than any other character - before, or if the font loaded has a smaller height than any - other font loaded before. If this happens, it will make a - glyph matrix reallocation necessary. */ - fonts_changed_p |= x_compute_min_glyph_bounds (f); - UNBLOCK_INPUT; - return fontp; - } -} - - -/* Return a pointer to struct font_info of a font named FONTNAME for - frame F. If no such font is loaded, return NULL. */ - -struct font_info * -x_query_font (f, fontname) - struct frame *f; - register char *fontname; -{ - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - int i; - - for (i = 0; i < dpyinfo->n_fonts; i++) - if (dpyinfo->font_table[i].name - && (!xstricmp (dpyinfo->font_table[i].name, fontname) - || !xstricmp (dpyinfo->font_table[i].full_name, fontname))) - return (dpyinfo->font_table + i); - return NULL; -} - - -/* Find a CCL program for a font specified by FONTP, and set the member - `encoder' of the structure. */ - -void -x_find_ccl_program (fontp) - struct font_info *fontp; -{ - Lisp_Object list, elt; - - elt = Qnil; - for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list)) - { - elt = XCAR (list); - if (CONSP (elt) - && STRINGP (XCAR (elt)) - && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name) - >= 0) - || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name) - >= 0))) - break; - } - - if (! NILP (list)) - { - struct ccl_program *ccl - = (struct ccl_program *) xmalloc (sizeof (struct ccl_program)); - - if (setup_ccl_program (ccl, XCDR (elt)) < 0) - xfree (ccl); - else - fontp->font_encoder = ccl; - } -} - - /*********************************************************************** Initialization @@ -10457,7 +9878,6 @@ static int x_initialized; 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. */ static int @@ -10504,7 +9924,6 @@ same_x_server (name1, name2) && (*name1 == '.' || *name1 == '\0') && (*name2 == '.' || *name2 == '\0')); } -#endif /* Count number of set bits in mask and number of bits to shift to get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET @@ -10703,7 +10122,6 @@ x_term_init (display_name, xrm_option, resource_name) terminal = x_create_terminal (dpyinfo); -#ifdef MULTI_KBOARD { struct x_display_info *share; Lisp_Object tail; @@ -10723,11 +10141,15 @@ x_term_init (display_name, xrm_option, resource_name) if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound)) { char *vendor = ServerVendor (dpy); + /* Temporarily hide the partially initialized terminal */ + terminal_list = terminal->next_terminal; UNBLOCK_INPUT; terminal->kboard->Vsystem_key_alist = call1 (Qvendor_specific_keysyms, vendor ? build_string (vendor) : empty_unibyte_string); BLOCK_INPUT; + terminal->next_terminal = terminal_list; + terminal_list = terminal; } terminal->kboard->next_kboard = all_kboards; @@ -10740,7 +10162,6 @@ x_term_init (display_name, xrm_option, resource_name) } terminal->kboard->reference_count++; } -#endif /* Put this display on the chain. */ dpyinfo->next = x_display_list; @@ -10796,16 +10217,12 @@ x_term_init (display_name, xrm_option, resource_name) DefaultScreen (dpyinfo->display)); select_visual (dpyinfo); dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen); - dpyinfo->height = HeightOfScreen (dpyinfo->screen); - dpyinfo->width = WidthOfScreen (dpyinfo->screen); dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen); dpyinfo->client_leader_window = 0; dpyinfo->grabbed = 0; dpyinfo->reference_count = 0; dpyinfo->icon_bitmap_id = -1; - dpyinfo->font_table = NULL; dpyinfo->n_fonts = 0; - dpyinfo->font_table_size = 0; dpyinfo->bitmaps = 0; dpyinfo->bitmaps_size = 0; dpyinfo->bitmaps_last = 0; @@ -10823,7 +10240,7 @@ x_term_init (display_name, xrm_option, resource_name) dpyinfo->x_focus_frame = 0; dpyinfo->x_focus_event_frame = 0; dpyinfo->x_highlight_frame = 0; - dpyinfo->image_cache = make_image_cache (); + dpyinfo->terminal->image_cache = make_image_cache (); dpyinfo->wm_type = X_WMTYPE_UNKNOWN; /* See if we can construct pixel values from RGB values. */ @@ -10933,6 +10350,9 @@ x_term_init (display_name, xrm_option, resource_name) dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR", False); + dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED", + False); + dpyinfo->cut_buffers_initialized = 0; dpyinfo->x_dnd_atoms_size = 8; @@ -10978,16 +10398,9 @@ x_term_init (display_name, xrm_option, resource_name) add_keyboard_wait_descriptor (connection); #endif -#ifndef F_SETOWN_BUG #ifdef F_SETOWN -#ifdef F_SETOWN_SOCK_NEG - /* stdin is a socket here */ - fcntl (connection, F_SETOWN, -getpid ()); -#else /* ! defined (F_SETOWN_SOCK_NEG) */ fcntl (connection, F_SETOWN, getpid ()); -#endif /* ! defined (F_SETOWN_SOCK_NEG) */ #endif /* ! defined (F_SETOWN) */ -#endif /* F_SETOWN_BUG */ #ifdef SIGIO if (interrupt_input) @@ -11122,7 +10535,8 @@ x_delete_display (dpyinfo) tail->next = tail->next->next; } -#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */ + /* Xt and GTK do this themselves. */ +#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) #ifndef AIX /* On AIX, XCloseDisplay calls this. */ XrmDestroyDatabase (dpyinfo->xrdb); #endif @@ -11132,25 +10546,8 @@ x_delete_display (dpyinfo) xim_close_dpy (dpyinfo); #endif - /* Free the font names in the font table. */ - for (i = 0; i < dpyinfo->n_fonts; i++) - if (dpyinfo->font_table[i].name) - { - if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name) - xfree (dpyinfo->font_table[i].full_name); - xfree (dpyinfo->font_table[i].name); - } - - if (dpyinfo->font_table) - { - if (dpyinfo->font_table->font_encoder) - xfree (dpyinfo->font_table->font_encoder); - xfree (dpyinfo->font_table); - } - if (dpyinfo->x_id_name) - xfree (dpyinfo->x_id_name); - if (dpyinfo->color_cells) - xfree (dpyinfo->color_cells); + xfree (dpyinfo->x_id_name); + xfree (dpyinfo->color_cells); xfree (dpyinfo); } @@ -11231,8 +10628,6 @@ static struct redisplay_interface x_redisplay_interface = x_draw_fringe_bitmap, 0, /* define_fringe_bitmap */ 0, /* destroy_fringe_bitmap */ - x_per_char_metric, - x_encode_char, x_compute_glyph_string_overhangs, x_draw_glyph_string, x_define_frame_cursor, @@ -11256,25 +10651,23 @@ x_delete_terminal (struct terminal *terminal) return; BLOCK_INPUT; - /* Free the fonts in the font table. */ - for (i = 0; i < dpyinfo->n_fonts; i++) - if (dpyinfo->font_table[i].name) - { - XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font); - } - - x_destroy_all_bitmaps (dpyinfo); - XSetCloseDownMode (dpyinfo->display, DestroyAll); + /* If called from x_connection_closed, the display may already be closed + and dpyinfo->display was set to 0 to indicate that. */ + if (dpyinfo->display) + { + x_destroy_all_bitmaps (dpyinfo); + XSetCloseDownMode (dpyinfo->display, DestroyAll); #ifdef USE_GTK - xg_display_close (dpyinfo->display); + xg_display_close (dpyinfo->display); #else #ifdef USE_X_TOOLKIT - XtCloseDisplay (dpyinfo->display); + XtCloseDisplay (dpyinfo->display); #else - XCloseDisplay (dpyinfo->display); + XCloseDisplay (dpyinfo->display); #endif #endif /* ! USE_GTK */ + } x_delete_display (dpyinfo); UNBLOCK_INPUT; @@ -11403,8 +10796,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"); @@ -11416,7 +10807,9 @@ syms_of_xterm () doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. A value of nil means ignore them. If you encounter fonts with bogus UNDERLINE_POSITION font properties, for example 7x13 on XFree prior -to 4.1, set this to nil. */); +to 4.1, set this to nil. You can also use `underline-minimum-offset' +to override the font's UNDERLINE_POSITION for small font display +sizes. */); x_use_underline_position_properties = 1; DEFVAR_BOOL ("x-underline-at-descent-line",