/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+ Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GNU Emacs.
extern Lisp_Object Qhelp_echo;
\f
-/* Non-zero means Emacs uses toolkit scroll bars. */
+/* Non-nil means Emacs uses toolkit scroll bars. */
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
DRAW_IMAGE_SUNKEN
};
+static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
static const XColor *x_color_cells P_ ((struct frame *, int *));
static void x_update_window_end P_ ((struct window *, int, int));
static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
prepare_image_for_display (it->f, img);
it->ascent = it->phys_ascent = image_ascent (img, face);
- it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
- it->pixel_width = img->width + 2 * img->margin;
+ it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+ it->pixel_width = img->width + 2 * img->hmargin;
it->nglyphs = 1;
int face_id;
struct face *face;
- /* What face has to be used for the mouse face? */
+ /* What face has to be used last for the mouse face? */
face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
face = FACE_FROM_ID (s->f, face_id);
+ if (face == NULL)
+ 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);
else
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->img->pixmap)
{
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->img->pixmap)
{
{
int x, y;
int box_line_width = s->face->box_line_width;
- int margin = s->img->margin;
int height;
Pixmap pixmap = None;
flickering. */
s->stippled_p = s->face->stipple != 0;
if (height > s->img->height
- || margin
+ || s->img->hmargin
+ || s->img->vmargin
|| s->img->mask
|| s->img->pixmap == 0
|| s->width != s->background_width)
happen when toolkit scroll bars are used and a window is split.
Reconfiguring the scroll bar will generate an expose for a newly
created window. */
- if (w->current_matrix == NULL)
+ if (w->current_matrix == NULL || w == updated_window)
return;
TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
clear_mouse_face (dpyinfo)
struct x_display_info *dpyinfo;
{
- if (tip_frame)
+#if 0 /* This prevents redrawing tool bar items when changing from one
+ to another while a tooltip is open, so don't do it. */
+ if (!NILP (tip_frame))
return;
+#endif
if (! NILP (dpyinfo->mouse_face_window))
show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
{
register int i;
register int c;
- unsigned char *p, *pend;
int nchars, len;
for (i = 0; i < nbytes; i++)
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
{
- Lisp_Object frame;
int from_menu_bar_p = 0;
if (f == dpyinfo->mouse_face_mouse_frame)
int n;
XSETFRAME (frame, f);
+ help_echo = Qnil;
n = gen_help_event (bufp, numchars,
Qnil, frame, Qnil, Qnil, 0);
bufp += n, count += n, numchars -= n;
signal (signalnum, x_connection_signal);
#endif /* USG */
}
+
\f
-/* Handling X errors. */
+/************************************************************************
+ Handling X errors
+ ************************************************************************/
-/* Handle the loss of connection to display DISPLAY. */
+/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
+ the text of an error message that lead to the connection loss. */
static SIGTYPE
-x_connection_closed (display, error_message)
- Display *display;
+x_connection_closed (dpy, error_message)
+ Display *dpy;
char *error_message;
{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
-
+ int count;
+ char *msg;
+
+ msg = (char *) alloca (strlen (error_message) + 1);
+ strcpy (msg, error_message);
+ handling_signal = 0;
+
+ /* Prevent being called recursively because of an error condition
+ 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);
+
/* 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
events from the display. As a consequence, a sequence of
in OpenWindows. I don't know how to cicumvent it here. */
#ifdef USE_X_TOOLKIT
- XtCloseDisplay (display);
+ /* 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)
+ XtCloseDisplay (dpy);
#endif
/* Indicate that this display is dead. */
if (dpyinfo)
x_delete_display (dpyinfo);
+ x_uncatch_errors (dpy, count);
+
if (x_display_list == 0)
{
- fprintf (stderr, "%s\n", error_message);
+ fprintf (stderr, "%s\n", msg);
shut_down_emacs (0, 0, Qnil);
exit (70);
}
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
- handling_signal = 0;
- error ("%s", error_message);
+ error ("%s", msg);
}
+
/* This is the usual handler for X protocol errors.
It kills all frames on the display that we got the error for.
If that was the only one, it prints an error message and kills Emacs. */
x_connection_closed (display, buf1);
}
+
/* This is the first-level handler for X protocol errors.
It calls x_error_quitter or x_error_catcher. */
f->output_data.x->font->fid);
frame_update_line_height (f);
- x_set_window_size (f, 0, f->width, f->height);
+
+ /* 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. */
+ if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+ x_set_window_size (f, 0, f->width, f->height);
}
else
/* If we are setting a new frame's font for the first time,
UNBLOCK_INPUT;
}
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-void
-x_set_window_size (f, change_gravity, cols, rows)
+/* Change the size of frame F's X window to COLS/ROWS in the case F
+ doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
+ top-left-corner window gravity for this size change and subsequent
+ size changes. Otherwise we leave the window gravity unchanged. */
+
+static void
+x_set_window_size_1 (f, change_gravity, cols, rows)
struct frame *f;
int change_gravity;
int cols, rows;
{
-#ifndef USE_X_TOOLKIT
int pixelwidth, pixelheight;
-#endif
-
- BLOCK_INPUT;
-
-#ifdef USE_X_TOOLKIT
- {
- /* The x and y position of the widget is clobbered by the
- call to XtSetValues within EmacsFrameSetCharSize.
- This is a real kludge, but I don't understand Xt so I can't
- figure out a correct fix. Can anyone else tell me? -- rms. */
- int xpos = f->output_data.x->widget->core.x;
- int ypos = f->output_data.x->widget->core.y;
- EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
- f->output_data.x->widget->core.x = xpos;
- f->output_data.x->widget->core.y = ypos;
- }
-
-#else /* not USE_X_TOOLKIT */
check_frame_size (f, &rows, &cols);
f->output_data.x->vertical_scroll_bar_extra
SET_FRAME_GARBAGED (f);
XFlush (FRAME_X_DISPLAY (f));
+}
+
+
+/* Call this to change the size of frame F's x-window.
+ If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ for this size change and subsequent size changes.
+ Otherwise we leave the window gravity unchanged. */
+
+void
+x_set_window_size (f, change_gravity, cols, rows)
+ struct frame *f;
+ int change_gravity;
+ int cols, rows;
+{
+ BLOCK_INPUT;
+#ifdef USE_X_TOOLKIT
+
+ if (f->output_data.x->widget != None)
+ {
+ /* The x and y position of the widget is clobbered by the
+ call to XtSetValues within EmacsFrameSetCharSize.
+ This is a real kludge, but I don't understand Xt so I can't
+ figure out a correct fix. Can anyone else tell me? -- rms. */
+ int xpos = f->output_data.x->widget->core.x;
+ int ypos = f->output_data.x->widget->core.y;
+ EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
+ f->output_data.x->widget->core.x = xpos;
+ f->output_data.x->widget->core.y = ypos;
+ }
+ else
+ x_set_window_size_1 (f, change_gravity, cols, rows);
+
+#else /* not USE_X_TOOLKIT */
+
+ x_set_window_size_1 (f, change_gravity, cols, rows);
+
#endif /* not USE_X_TOOLKIT */
/* If cursor was outside the new size, mark it as off. */
UNBLOCK_INPUT;
#endif /* not USE_X_TOOLKIT */
}
+
\f
-/* Destroy the X window of frame F. */
+/* Free X resources of frame F. */
void
-x_destroy_window (f)
+x_free_frame_resources (f)
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
/* If a display connection is dead, don't try sending more
commands to the X server. */
- if (dpyinfo->display != 0)
+ if (dpyinfo->display)
{
- if (f->output_data.x->icon_desc != 0)
+ if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
#endif
+
if (FRAME_X_WINDOW (f))
- {
- XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- FRAME_X_WINDOW (f) = 0;
- }
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
XtDestroyWidget (f->output_data.x->widget);
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
unload_color (f, f->output_data.x->mouse_pixel);
+
if (f->output_data.x->scroll_bar_background_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_background_pixel);
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
unload_color (f, f->output_data.x->white_relief.pixel);
if (f->output_data.x->black_relief.allocated_p)
unload_color (f, f->output_data.x->black_relief.pixel);
+
+ if (FRAME_FACE_CACHE (f))
+ free_frame_faces (f);
- free_frame_faces (f);
+ x_free_gcs (f);
XFlush (FRAME_X_DISPLAY (f));
}
xfree (f->output_data.x->saved_menu_event);
xfree (f->output_data.x);
- f->output_data.x = 0;
+ f->output_data.x = NULL;
+
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
if (f == dpyinfo->x_focus_event_frame)
if (f == dpyinfo->x_highlight_frame)
dpyinfo->x_highlight_frame = 0;
- dpyinfo->reference_count--;
-
if (f == dpyinfo->mouse_face_mouse_frame)
{
dpyinfo->mouse_face_beg_row
UNBLOCK_INPUT;
}
+
+
+/* Destroy the X window of frame F. */
+
+void
+x_destroy_window (f)
+ struct frame *f;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ /* If a display connection is dead, don't try sending more
+ commands to the X server. */
+ if (dpyinfo->display != 0)
+ x_free_frame_resources (f);
+
+ dpyinfo->reference_count--;
+}
+
\f
/* Setting window manager hints. */
}
-/* Return a list of names of available fonts matching PATTERN on frame
- F. If SIZE is not 0, it is the size (maximum bound width) of fonts
- to be listed. 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. */
+/* 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)
- FRAME_PTR f;
+ struct frame *f;
Lisp_Object pattern;
int size;
int maxnames;
{
Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
Lisp_Object tem, second_best;
- Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
+ struct x_display_info *dpyinfo
+ = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
+ Display *dpy = dpyinfo->display;
int try_XLoadQueryFont = 0;
int count;
+ int allow_scalable_fonts_p = 0;
+
+ if (size < 0)
+ {
+ allow_scalable_fonts_p = 1;
+ size = 0;
+ }
patterns = Fassoc (pattern, Valternate_fontname_alist);
if (NILP (patterns))
pattern = XCAR (patterns);
/* See if we cached the result for this particular query.
The cache is an alist of the form:
- (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
- */
- if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
- key = Fcons (pattern, make_number (maxnames)),
- !NILP (list = Fassoc (key, tem))))
+ ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
+ tem = XCDR (dpyinfo->name_list_element);
+ key = Fcons (Fcons (pattern, make_number (maxnames)),
+ allow_scalable_fonts_p ? 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. */
int average_width = -1, dashes = 0;
/* Count the number of dashes in NAMES[I]. If there are
- 14 dashes, 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. */
+ 14 dashes, 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++ == '-')
{
else if (dashes == 12) /* AVERAGE_WIDTH field */
average_width = atoi (p);
}
- if (dashes < 14 || average_width != 0)
+
+ if (allow_scalable_fonts_p
+ || dashes < 14 || average_width != 0)
{
tem = build_string (names[i]);
if (NILP (Fassoc (tem, list)))
}
/* Now store the result in the cache. */
- if (f != NULL)
- XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
- = Fcons (Fcons (key, list),
- XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
+ XCDR (dpyinfo->name_list_element)
+ = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
label_cached:
if (NILP (list)) continue; /* Try the remaining alternatives. */
if (!INTEGERP (XCDR (tem)))
{
/* Since we have not yet known the size of this font, we
- must try slow function call XLoadQueryFont. */
+ must try slow function call XLoadQueryFont. */
XFontStruct *thisinfo;
BLOCK_INPUT;
fontp->size = font->max_bounds.width;
fontp->height = FONT_HEIGHT (font);
- {
- /* For some font, ascent and descent in max_bounds field is
- larger than the above value. */
- int max_height = font->max_bounds.ascent + font->max_bounds.descent;
- if (max_height > fontp->height)
- fontp->height = max_height;
- }
if (NILP (font_names))
{
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);
XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
+ = Fcons (Fcons (key,
Fcons (Fcons (lispy_full_name,
make_number (fontp->size)),
Qnil)),
XCDR (dpyinfo->name_list_element));
if (full_name)
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ {
+ key = Fcons (Fcons (lispy_full_name, make_number (256)),
+ Qnil);
+ XCDR (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
{
extern int gray_bitmap_width, gray_bitmap_height;
- extern unsigned char *gray_bitmap_bits;
+ extern char *gray_bitmap_bits;
dpyinfo->gray
= XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
gray_bitmap_bits,
estimate_mode_line_height_hook = x_estimate_mode_line_height;
scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 0; /* just as fast to write the line */
+ char_ins_del_ok = 1;
line_ins_del_ok = 1; /* we'll just blt 'em */
fast_clear_end_of_line = 1; /* X does this well */
memory_below_frame = 0; /* we don't remember what scrolls
wide as that tab on the display.");
x_stretch_cursor_p = 0;
- DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
- "If not nil, Emacs uses toolkit scroll bars.");
+ DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+ "What X toolkit scroll bars Emacs uses.\n\
+A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
+Otherwise, value is a symbol describing the X toolkit.");
#ifdef USE_TOOLKIT_SCROLL_BARS
- x_toolkit_scroll_bars_p = 1;
+#ifdef USE_MOTIF
+ Vx_toolkit_scroll_bars = intern ("motif");
+#elif defined HAVE_XAW3D
+ Vx_toolkit_scroll_bars = intern ("xaw3d");
+#else
+ Vx_toolkit_scroll_bars = intern ("xaw");
+#endif
#else
- x_toolkit_scroll_bars_p = 0;
+ Vx_toolkit_scroll_bars = Qnil;
#endif
staticpro (&last_mouse_motion_frame);