/* 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.
/* #include <sys/param.h> */
#include "charset.h"
+#include "character.h"
#include "coding.h"
#include "ccl.h"
#include "frame.h"
/* Where the mouse was last time we reported a mouse event. */
static XRectangle last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
static Lisp_Object last_mouse_press_frame;
/* The scroll bar in which the last X motion event occurred.
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 *));
/* 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
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.
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)
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);
}
+/* 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)
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;
+ }
}
/* 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
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);
+ }
}
}
{
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. */
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);
/* 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. */
/* 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;
last_mouse_motion_event = *event;
XSETFRAME (last_mouse_motion_frame, frame);
+ if (!FRAME_X_OUTPUT (frame))
+ return 0;
+
if (event->window != FRAME_X_WINDOW (frame))
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
+ last_mouse_glyph_frame = 0;
return 1;
}
+
/* Has the mouse moved off the glyph it was on at the last sighting? */
- if (event->x < last_mouse_glyph.x
- || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
- || event->y < last_mouse_glyph.y
- || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+ if (frame != last_mouse_glyph_frame
+ || event->x < last_mouse_glyph.x
+ || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+ || event->y < last_mouse_glyph.y
+ || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, event->x, event->y);
/* Remember which glyph we're now on. */
remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
+ last_mouse_glyph_frame = frame;
return 1;
}
Window win, child;
int win_x, win_y;
int parent_x = 0, parent_y = 0;
- int count;
win = root;
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))
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)
the frame are divided into. */
remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+ last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
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. */
/* 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 */
== dpyinfo->Xatom_editres)
{
f = x_any_window_to_frame (dpyinfo, event.xclient.window);
- _XEditResCheckMessages (f->output_data.x->widget, NULL,
- &event, NULL);
+ if (f)
+ _XEditResCheckMessages (f->output_data.x->widget, NULL,
+ &event, NULL);
goto done;
}
#endif /* HACK_EDITRES */
images, only, which should have 1 page. */
Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
f = x_window_to_frame (dpyinfo, event.xclient.window);
+ if (!f)
+ goto OTHER;
x_kill_gs_process (pixmap, f);
expose_frame (f, 0, 0, 0, 0);
goto done;
#endif /* USE_TOOLKIT_SCROLL_BARS */
f = x_any_window_to_frame (dpyinfo, event.xclient.window);
-
if (!f)
goto OTHER;
-
if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
*finish = X_EVENT_DROP;
}
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)
+ && (f == 0
+ || !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
goto done_keysym;
}
+ /* Keysyms directly mapped to Unicode characters. */
+ if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
+ {
+ if (keysym < 0x01000080)
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ else
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.code = keysym & 0xFFFFFF;
+ goto done_keysym;
+ }
+
/* Now non-ASCII. */
if (HASH_TABLE_P (Vx_keysym_table)
&& (NATNUMP (c = Fgethash (make_number (keysym),
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. */
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:
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:
int tool_bar_p = 0;
bzero (&compose_status, sizeof (compose_status));
- bzero (&last_mouse_glyph, sizeof (last_mouse_glyph));
+ last_mouse_glyph_frame = 0;
if (dpyinfo->grabbed
&& last_mouse_frame
/* 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);
}
/* Create the GNU bitmap and mask if necessary. */
if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
{
- FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
- = x_create_bitmap_from_data (f, gnu_bits,
- gnu_width, gnu_height);
- x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+ int rc = -1;
+
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#ifdef USE_GTK
+ if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+ return 0;
+#else
+ rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+ if (rc != -1)
+ FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+#endif /* USE_GTK */
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+ /* If all else fails, use the (black and white) xbm image. */
+ if (rc == -1)
+ {
+ rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
+ gnu_xbm_width, gnu_xbm_height);
+ if (rc == -1)
+ return 1;
+
+ FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+ x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+ }
}
/* The first time we create the GNU bitmap and mask,
#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
XErrorEvent *error;
{
XGetErrorText (display, error->error_code,
- SDATA (x_error_message_string),
+ x_error_message->string,
X_ERROR_MESSAGE_SIZE);
}
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
/* 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
/* 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. */
x_clear_errors (dpy)
Display *dpy;
{
- SSET (x_error_message_string, 0, 0);
+ x_error_message->string[0] = 0;
}
-/* Stop catching X protocol errors and let them make Emacs die.
- DPY should be the display that was passed to x_catch_errors.
- COUNT should be the value that was returned by
- the corresponding call to x_catch_errors. */
+/* Close off all unclosed x_catch_errors calls. */
void
-x_uncatch_errors (dpy, count)
- Display *dpy;
- int count;
+x_fully_uncatch_errors ()
+{
+ while (x_error_message)
+ x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled. */
+
+int
+x_catching_errors ()
{
- unbind_to (count, Qnil);
+ return x_error_message != 0;
}
#if 0
{
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);
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
if (dpyinfo)
x_delete_display (dpyinfo);
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
if (x_display_list == 0)
{
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);
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;
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;
xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
#endif
- return build_string (fontsetname);
+ return fontset_name (fontset);
}
\f
x_calc_absolute_position (f)
struct frame *f;
{
- int win_x = 0, win_y = 0;
int flags = f->size_hint_flags;
/* We have nothing to do if the current position
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
= 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)
/* At first, put PATTERN in the cache. */
BLOCK_INPUT;
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
if (try_XLoadQueryFont)
{
}
}
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (names)
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))
thisinfo = NULL;
x_clear_errors (dpy);
}
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (thisinfo)
{
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
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)))
{
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;
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);
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
}
+/* 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;
+}
\f
/***********************************************************************
Initialization
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. */
*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;
/* 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);
Display *dpy = dpyinfo->display;
XrmValue d, fr, to;
Font font;
- int count;
d.addr = (XPointer)&dpy;
d.size = sizeof (Display *);
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
#ifdef HAVE_X_SM
/* Only do this for the first display. */
- if (x_initialized == 1)
+ if (!x_session_initialized++)
x_session_initialize (dpyinfo);
#endif
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;
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;
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");