/* Functions for the X window system.
- Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+ Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
Free Software Foundation.
This file is part of GNU Emacs.
int gray_bitmap_width = gray_width;
int gray_bitmap_height = gray_height;
-unsigned char *gray_bitmap_bits = gray_bits;
+char *gray_bitmap_bits = gray_bits;
/* The name we're using in resource queries. Most often "emacs". */
Lisp_Object Vx_resource_class;
-/* Non-zero means we're allowed to display a busy cursor. */
+/* Non-zero means we're allowed to display an hourglass cursor. */
-int display_busy_cursor_p;
+int display_hourglass_p;
/* The background and shape of the mouse pointer, and shape when not
over text or in the modeline. */
Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-Lisp_Object Vx_busy_pointer_shape;
+Lisp_Object Vx_hourglass_pointer_shape;
/* The shape when over mouse-sensitive text. */
Lisp_Object Vx_sensitive_text_pointer_shape;
+/* If non-nil, the pointer shape to indicate that windows can be
+ dragged horizontally. */
+
+Lisp_Object Vx_window_horizontal_drag_shape;
+
/* Color of chars displayed in cursor box. */
Lisp_Object Vx_cursor_fore_pixel;
Lisp_Object Vx_pixel_size_width_font_regexp;
-/* Evaluate this expression to rebuild the section of syms_of_xfns
- that initializes and staticpros the symbols declared below. Note
- that Emacs 18 has a bug that keeps C-x C-e from being able to
- evaluate this expression.
-
-(progn
- ;; Accumulate a list of the symbols we want to initialize from the
- ;; declarations at the top of the file.
- (goto-char (point-min))
- (search-forward "/\*&&& symbols declared here &&&*\/\n")
- (let (symbol-list)
- (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
- (setq symbol-list
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- symbol-list))
- (forward-line 1))
- (setq symbol-list (nreverse symbol-list))
- ;; Delete the section of syms_of_... where we initialize the symbols.
- (search-forward "\n /\*&&& init symbols here &&&*\/\n")
- (let ((start (point)))
- (while (looking-at "^ Q")
- (forward-line 2))
- (kill-region start (point)))
- ;; Write a new symbol initialization section.
- (while symbol-list
- (insert (format " %s = intern (\"" (car symbol-list)))
- (let ((start (point)))
- (insert (substring (car symbol-list) 1))
- (subst-char-in-region start (point) ?_ ?-))
- (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
- (setq symbol-list (cdr symbol-list)))))
-
- */
-
-/*&&& symbols declared here &&&*/
Lisp_Object Qauto_raise;
Lisp_Object Qauto_lower;
Lisp_Object Qbar;
extern Lisp_Object Qdisplay;
Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
-Lisp_Object Qcompound_text;
+Lisp_Object Qcompound_text, Qcancel_timer;
/* The below are defined in frame.c. */
Lisp_Object Qface_set_after_frame_default;
+#if GLYPH_DEBUG
+int image_cache_refcount, dpyinfo_refcount;
+#endif
+
+
\f
/* Error if we are not connected to X. */
f = XFRAME (frame);
if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
- if (f->output_data.x->busy_window == wdesc)
+ if (f->output_data.x->hourglass_window == wdesc)
return f;
#ifdef USE_X_TOOLKIT
if ((f->output_data.x->edit_widget
{
/* This frame matches if the window is any of its widgets. */
x = f->output_data.x;
- if (x->busy_window == wdesc)
+ if (x->hourglass_window == wdesc)
found = f;
else if (x->widget)
{
continue;
x = f->output_data.x;
/* This frame matches if the window is any of its widgets. */
- if (x->busy_window == wdesc)
+ if (x->hourglass_window == wdesc)
return f;
else if (x->widget)
{
fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
if (fd < 0)
return -1;
- /* XReadBitmapFile won't handle magic file names. */
- if (fd == 0)
- return -1;
emacs_close (fd);
filename = (char *) XSTRING (found)->data;
void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
};
+static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
+static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
+static void x_change_window_heights P_ ((Lisp_Object, int));
static void x_disable_image P_ ((struct frame *, struct image *));
static void x_create_im P_ ((struct frame *));
void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
return cdef.pixel;
- return Fsignal (Qerror, Fcons (build_string ("Undefined color"),
- Fcons (color_name, Qnil)));
+ Fsignal (Qerror, Fcons (build_string ("Undefined color"),
+ Fcons (color_name, Qnil)));
+ return 0;
}
struct frame *f;
Lisp_Object arg, oldval;
{
- unsigned long pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
unload_color (f, f->output_data.x->foreground_pixel);
f->output_data.x->foreground_pixel = pixel;
struct frame *f;
Lisp_Object arg, oldval;
{
- unsigned long pixel
- = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
+ unsigned long pixel = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
unload_color (f, f->output_data.x->background_pixel);
f->output_data.x->background_pixel = pixel;
Lisp_Object arg, oldval;
{
Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
- Cursor busy_cursor;
+ Cursor hourglass_cursor, horizontal_drag_cursor;
int count;
unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
unsigned long mask_color = f->output_data.x->background_pixel;
/* Don't let pointers be invisible. */
if (mask_color == pixel
&& mask_color == f->output_data.x->background_pixel)
- pixel = f->output_data.x->foreground_pixel;
+ {
+ x_free_colors (f, &pixel, 1);
+ pixel = x_copy_color (f, f->output_data.x->foreground_pixel);
+ }
unload_color (f, f->output_data.x->mouse_pixel);
f->output_data.x->mouse_pixel = pixel;
nontext_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_left_ptr);
x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
- if (!EQ (Qnil, Vx_busy_pointer_shape))
+ if (!EQ (Qnil, Vx_hourglass_pointer_shape))
{
- CHECK_NUMBER (Vx_busy_pointer_shape, 0);
- busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
- XINT (Vx_busy_pointer_shape));
+ CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
+ hourglass_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f),
+ XINT (Vx_hourglass_pointer_shape));
}
else
- busy_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
- x_check_errors (FRAME_X_DISPLAY (f), "bad busy pointer cursor: %s");
+ hourglass_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_watch);
+ x_check_errors (FRAME_X_DISPLAY (f), "bad hourglass pointer cursor: %s");
x_check_errors (FRAME_X_DISPLAY (f), "bad nontext pointer cursor: %s");
if (!EQ (Qnil, Vx_mode_pointer_shape))
else
cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
+ if (!NILP (Vx_window_horizontal_drag_shape))
+ {
+ CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_X_DISPLAY (f),
+ XINT (Vx_window_horizontal_drag_shape));
+ }
+ else
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+
/* Check and report errors with the above calls. */
x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
x_uncatch_errors (FRAME_X_DISPLAY (f), count);
XColor fore_color, back_color;
fore_color.pixel = f->output_data.x->mouse_pixel;
+ x_query_color (f, &fore_color);
back_color.pixel = mask_color;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &fore_color);
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &back_color);
+ x_query_color (f, &back_color);
+
XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
+ &fore_color, &back_color);
+ XRecolorCursor (FRAME_X_DISPLAY (f), hourglass_cursor,
&fore_color, &back_color);
- XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
+ XRecolorCursor (FRAME_X_DISPLAY (f), horizontal_drag_cursor,
&fore_color, &back_color);
}
if (FRAME_X_WINDOW (f) != 0)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
- if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
+ if (cursor != f->output_data.x->text_cursor
+ && f->output_data.x->text_cursor != 0)
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
f->output_data.x->text_cursor = cursor;
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->nontext_cursor);
f->output_data.x->nontext_cursor = nontext_cursor;
- if (busy_cursor != f->output_data.x->busy_cursor
- && f->output_data.x->busy_cursor != 0)
- XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->busy_cursor);
- f->output_data.x->busy_cursor = busy_cursor;
+ if (hourglass_cursor != f->output_data.x->hourglass_cursor
+ && f->output_data.x->hourglass_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->hourglass_cursor);
+ f->output_data.x->hourglass_cursor = hourglass_cursor;
if (mode_cursor != f->output_data.x->modeline_cursor
&& f->output_data.x->modeline_cursor != 0)
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
f->output_data.x->cross_cursor = cross_cursor;
+ if (horizontal_drag_cursor != f->output_data.x->horizontal_drag_cursor
+ && f->output_data.x->horizontal_drag_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
+ f->output_data.x->horizontal_drag_cursor = horizontal_drag_cursor;
+
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
Lisp_Object result;
Lisp_Object fontset_name;
Lisp_Object frame;
+ int old_fontset = f->output_data.x->fontset;
CHECK_STRING (arg, 1);
error ("The characters of the given font have varying widths");
else if (STRINGP (result))
{
+ if (STRINGP (fontset_name))
+ {
+ /* Fontset names are built from ASCII font names, so the
+ names may be equal despite there was a change. */
+ if (old_fontset == f->output_data.x->fontset)
+ return;
+ }
+ else if (!NILP (Fequal (result, oldval)))
+ return;
+
store_frame_param (f, Qfont, result);
recompute_basic_faces (f);
}
else
Fmake_frame_visible (frame);
}
+
\f
+/* Change window heights in windows rooted in WINDOW by N lines. */
+
static void
-x_set_menu_bar_lines_1 (window, n)
+x_change_window_heights (window, n)
Lisp_Object window;
int n;
{
/* Handle just the top child in a vertical split. */
if (!NILP (w->vchild))
- x_set_menu_bar_lines_1 (w->vchild, n);
+ x_change_window_heights (w->vchild, n);
/* Adjust all children in a horizontal split. */
for (window = w->hchild; !NILP (window); window = w->next)
{
w = XWINDOW (window);
- x_set_menu_bar_lines_1 (window, n);
+ x_change_window_heights (window, n);
}
}
}
#else /* not USE_X_TOOLKIT */
FRAME_MENU_BAR_LINES (f) = nlines;
- x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
+ x_change_window_heights (f->root_window, nlines - olines);
#endif /* not USE_X_TOOLKIT */
adjust_glyphs (f);
}
struct frame *f;
Lisp_Object value, oldval;
{
- int delta, nlines;
+ int delta, nlines, root_height;
+ Lisp_Object root_window;
+
+ /* Treat tool bars like menu bars. */
+ if (FRAME_MINIBUF_ONLY_P (f))
+ return;
/* Use VALUE only if an integer >= 0. */
if (INTEGERP (value) && XINT (value) >= 0)
++windows_or_buffers_changed;
delta = nlines - FRAME_TOOL_BAR_LINES (f);
+
+ /* Don't resize the tool-bar to more than we have room for. */
+ root_window = FRAME_ROOT_WINDOW (f);
+ root_height = XINT (XWINDOW (root_window)->height);
+ if (root_height - delta < 1)
+ {
+ delta = root_height - 1;
+ nlines = FRAME_TOOL_BAR_LINES (f) + delta;
+ }
+
FRAME_TOOL_BAR_LINES (f) = nlines;
- x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
+ x_change_window_heights (root_window, delta);
adjust_glyphs (f);
+
+ /* We also have to make sure that the internal border at the top of
+ the frame, below the menu bar or tool bar, is redrawn when the
+ tool bar disappears. This is so because the internal border is
+ below the tool bar if one is displayed, but is below the menu bar
+ if there isn't a tool bar. The tool bar draws into the area
+ below the menu bar. */
+ if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
+ {
+ updating_frame = f;
+ clear_frame ();
+ clear_current_matrices (f);
+ updating_frame = NULL;
+ }
+
+ /* If the tool bar gets smaller, the internal border below it
+ has to be cleared. It was formerly part of the display
+ of the larger tool bar, and updating windows won't clear it. */
+ if (delta < 0)
+ {
+ int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = PIXEL_WIDTH (f);
+ int y = nlines * CANON_Y_UNIT (f);
+
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ UNBLOCK_INPUT;
+ }
}
coding.mode |= CODING_MODE_LAST_BLOCK;
if (coding.type == coding_type_iso2022)
coding.flags |= CODING_FLAG_ISO_SAFE;
+ /* We suppress producing escape sequences for composition. */
+ coding.composing = COMPOSITION_DISABLED;
bufsize = encoding_buffer_size (&coding, bytes);
buf = (unsigned char *) xmalloc (bufsize);
encode_coding (&coding, str, buf, bytes, bufsize);
/* Create XIC for frame F. */
+static XIMStyle xic_style;
+
void
create_frame_xic (f)
struct frame *f;
XIM xim;
XIC xic = NULL;
XFontSet xfs = NULL;
- static XIMStyle xic_style;
if (FRAME_XIC (f))
return;
gc_values.foreground = f->output_data.x->foreground_pixel;
gc_values.background = f->output_data.x->background_pixel;
gc_values.line_width = 0; /* Means 1 using fast algorithm. */
- f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCLineWidth | GCFont
- | GCForeground | GCBackground,
- &gc_values);
+ f->output_data.x->normal_gc
+ = XCreateGC (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ GCLineWidth | GCFont | GCForeground | GCBackground,
+ &gc_values);
/* Reverse video style. */
gc_values.foreground = f->output_data.x->background_pixel;
gc_values.background = f->output_data.x->foreground_pixel;
- f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCFont | GCForeground | GCBackground
- | GCLineWidth,
- &gc_values);
+ f->output_data.x->reverse_gc
+ = XCreateGC (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ GCFont | GCForeground | GCBackground | GCLineWidth,
+ &gc_values);
/* Cursor has cursor-color background, background-color foreground. */
gc_values.foreground = f->output_data.x->background_pixel;
UNBLOCK_INPUT;
}
+
+/* Free what was was allocated in x_make_gc. */
+
+void
+x_free_gcs (f)
+ struct frame *f;
+{
+ Display *dpy = FRAME_X_DISPLAY (f);
+
+ BLOCK_INPUT;
+
+ if (f->output_data.x->normal_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->normal_gc);
+ f->output_data.x->normal_gc = 0;
+ }
+
+ if (f->output_data.x->reverse_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->reverse_gc);
+ f->output_data.x->reverse_gc = 0;
+ }
+
+ if (f->output_data.x->cursor_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->cursor_gc);
+ f->output_data.x->cursor_gc = 0;
+ }
+
+ if (f->output_data.x->border_tile)
+ {
+ XFreePixmap (dpy, f->output_data.x->border_tile);
+ f->output_data.x->border_tile = 0;
+ }
+
+ UNBLOCK_INPUT;
+}
+
+
+/* Handler for signals raised during x_create_frame and
+ x_create_top_frame. FRAME is the frame which is partially
+ constructed. */
+
+static Lisp_Object
+unwind_create_frame (frame)
+ Lisp_Object frame;
+{
+ struct frame *f = XFRAME (frame);
+
+ /* If frame is ``official'', nothing to do. */
+ if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+ {
+#if GLYPH_DEBUG
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+
+ x_free_frame_resources (f);
+
+ /* Check that reference counts are indeed correct. */
+ xassert (dpyinfo->reference_count == dpyinfo_refcount);
+ xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+ return Qt;
+ }
+
+ return Qnil;
+}
+
+
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1, 1, 0,
"Make a new X window, which is called a \"frame\" in Emacs terms.\n\
int minibuffer_only = 0;
long window_prompting = 0;
int width, height;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
struct x_display_info *dpyinfo = NULL;
f->output_data.x->fontset = -1;
f->output_data.x->scroll_bar_foreground_pixel = -1;
f->output_data.x->scroll_bar_background_pixel = -1;
+ record_unwind_protect (unwind_create_frame, frame);
f->icon_name
= x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
f->icon_name = Qnil;
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+ image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
#ifdef MULTI_KBOARD
FRAME_KBOARD (f) = kb;
#endif
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
"menuBar", "MenuBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
+ x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
"toolBar", "ToolBar", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate",
tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
- /* Create the X widget or window. Add the tool-bar height to the
- initial frame height so that the user gets a text display area of
- the size he specified with -g or via .Xdefaults. Later changes
- of the tool-bar height don't change the frame size. This is done
- so that users can create tall Emacs frames without having to
- guess how tall the tool-bar will get. */
- f->height += FRAME_TOOL_BAR_LINES (f);
-
+ /* Create the X widget or window. */
#ifdef USE_X_TOOLKIT
x_window (f, window_prompting, minibuffer_only);
#else
f->height. */
width = f->width;
height = f->height;
+
+ /* Add the tool-bar height to the initial frame height so that the
+ user gets a text display area of the size he specified with -g or
+ via .Xdefaults. Later changes of the tool-bar height don't
+ change the frame size. This is done so that users can create
+ tall Emacs frames without having to guess how tall the tool-bar
+ will get. */
+ if (FRAME_TOOL_BAR_LINES (f))
+ {
+ int margin, relief, bar_height;
+
+ relief = (tool_bar_button_relief > 0
+ ? tool_bar_button_relief
+ : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+
+ if (INTEGERP (Vtool_bar_button_margin)
+ && XINT (Vtool_bar_button_margin) > 0)
+ margin = XFASTINT (Vtool_bar_button_margin);
+ else if (CONSP (Vtool_bar_button_margin)
+ && INTEGERP (XCDR (Vtool_bar_button_margin))
+ && XINT (XCDR (Vtool_bar_button_margin)) > 0)
+ margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+ else
+ margin = 0;
+
+ bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+ height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+ }
+
f->height = 0;
SET_FRAME_WIDTH (f, 0);
change_frame_size (f, height, width, 1, 0, 0);
- /* Set up faces after all frame parameters are known. */
+ /* Set up faces after all frame parameters are known. This call
+ also merges in face attributes specified for new frames. If we
+ don't do this, the `menu' face for instance won't have the right
+ colors, and the menu bar won't appear in the specified colors for
+ new frames. */
call1 (Qface_set_after_frame_default, frame);
#ifdef USE_X_TOOLKIT
return unbind_to (count, frame);
}
+
/* FRAME is used only to get a handle on the X display. We don't pass the
display info directly because we're called from frame.c, which doesn't
know about that structure. */
validate_x_resource_name ();
- dpyinfo = x_term_init (name, (unsigned char *)0,
+ dpyinfo = x_term_init (name, (char *)0,
(char *) XSTRING (Vx_resource_name)->data);
if (dpyinfo == 0)
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
extern Lisp_Object QCdata;
Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
-Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
+Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
/* Other symbols. */
IMAGE_STRING_VALUE,
IMAGE_SYMBOL_VALUE,
IMAGE_POSITIVE_INTEGER_VALUE,
+ IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
IMAGE_NON_NEGATIVE_INTEGER_VALUE,
IMAGE_ASCENT_VALUE,
IMAGE_INTEGER_VALUE,
return 0;
break;
+ case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
+ if (INTEGERP (value) && XINT (value) >= 0)
+ break;
+ if (CONSP (value)
+ && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
+ && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+ break;
+ return 0;
+
case IMAGE_ASCENT_VALUE:
if (SYMBOLP (value) && EQ (value, Qcenter))
break;
struct frame *f = check_x_frame (frame);
int id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
- int width = img->width + 2 * img->margin;
- int height = img->height + 2 * img->margin;
+ int width = img->width + 2 * img->hmargin;
+ int height = img->height + 2 * img->vmargin;
if (NILP (pixels))
size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
- if (img->pixmap == 0 && !img->load_failed_p)
+ if (img->pixmap == None && !img->load_failed_p)
img->load_failed_p = img->type->load (f, img) == 0;
}
struct image *img;
struct face *face;
{
- int height = img->height + img->margin;
+ int height = img->height + img->vmargin;
int ascent;
if (img->ascent == CENTERED_IMAGE_ASCENT)
{
if (face->font)
- ascent = height / 2 - (face->font->descent - face->font->ascent) / 2;
+ /* This expression is arranged so that if the image can't be
+ exactly centered, it will be moved slightly up. This is
+ because a typical font is `top-heavy' (due to the presence
+ uppercase letters), so the image placement should err towards
+ being top-heavy too. It also just generally looks better. */
+ ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
else
ascent = height / 2;
}
Helper functions for X image types
***********************************************************************/
+static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
+ int, int));
static void x_clear_image P_ ((struct frame *f, struct image *img));
static unsigned long x_alloc_image_color P_ ((struct frame *f,
struct image *img,
Lisp_Object color_name,
unsigned long dflt));
-/* Free X resources of image IMG which is used on frame F. */
+
+/* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
+ free the pixmap if any. MASK_P non-zero means clear the mask
+ pixmap if any. COLORS_P non-zero means free colors allocated for
+ the image, if any. */
static void
-x_clear_image (f, img)
+x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
struct frame *f;
struct image *img;
+ int pixmap_p, mask_p, colors_p;
{
- BLOCK_INPUT;
-
- if (img->pixmap)
+ if (pixmap_p && img->pixmap)
{
XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
- img->pixmap = 0;
+ img->pixmap = None;
}
- if (img->mask)
+ if (mask_p && img->mask)
{
XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
- img->mask = 0;
+ img->mask = None;
}
- if (img->ncolors)
+ if (colors_p && img->ncolors)
{
x_free_colors (f, img->colors, img->ncolors);
xfree (img->colors);
img->colors = NULL;
img->ncolors = 0;
}
-
+}
+
+/* Free X resources of image IMG which is used on frame F. */
+
+static void
+x_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ BLOCK_INPUT;
+ x_clear_image_1 (f, img, 1, 1, 1);
UNBLOCK_INPUT;
}
/* Handle image type independent image attributes
`:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
Lisp_Object ascent, margin, relief;
- Lisp_Object file;
ascent = image_spec_value (spec, QCascent, NULL);
if (INTEGERP (ascent))
margin = image_spec_value (spec, QCmargin, NULL);
if (INTEGERP (margin) && XINT (margin) >= 0)
- img->margin = XFASTINT (margin);
+ img->vmargin = img->hmargin = XFASTINT (margin);
+ else if (CONSP (margin) && INTEGERP (XCAR (margin))
+ && INTEGERP (XCDR (margin)))
+ {
+ if (XINT (XCAR (margin)) > 0)
+ img->hmargin = XFASTINT (XCAR (margin));
+ if (XINT (XCDR (margin)) > 0)
+ img->vmargin = XFASTINT (XCDR (margin));
+ }
relief = image_spec_value (spec, QCrelief, NULL);
if (INTEGERP (relief))
{
img->relief = XINT (relief);
- img->margin += abs (img->relief);
+ img->hmargin += abs (img->relief);
+ img->vmargin += abs (img->relief);
}
/* Manipulation of the image's mask. */
else if (NILP (mask) && found_p && img->mask)
{
XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
- img->mask = 0;
+ img->mask = None;
}
}
}
/* Should we apply an image transformation algorithm? */
if (img->pixmap)
{
- Lisp_Object algorithm;
+ Lisp_Object conversion;
- algorithm = image_spec_value (spec, QCalgorithm, NULL);
- if (EQ (algorithm, Qdisabled))
+ conversion = image_spec_value (spec, QCconversion, NULL);
+ if (EQ (conversion, Qdisabled))
x_disable_image (f, img);
- else if (EQ (algorithm, Qlaplace))
+ else if (EQ (conversion, Qlaplace))
x_laplace (f, img);
- else if (EQ (algorithm, Qemboss))
+ else if (EQ (conversion, Qemboss))
x_emboss (f, img);
- else if (CONSP (algorithm)
- && EQ (XCAR (algorithm), Qedge_detection))
+ else if (CONSP (conversion)
+ && EQ (XCAR (conversion), Qedge_detection))
{
Lisp_Object tem;
- tem = XCDR (algorithm);
+ tem = XCDR (conversion);
if (CONSP (tem))
x_edge_detection (f, img,
Fplist_get (tem, QCmatrix),
Fplist_get (tem, QCcolor_adjustment));
}
}
-
}
-
+
UNBLOCK_INPUT;
xassert (!interrupt_input_blocked);
}
/* Allocate a pixmap of the same size. */
*pixmap = XCreatePixmap (display, window, width, height, depth);
- if (*pixmap == 0)
+ if (*pixmap == None)
{
x_destroy_x_image (*ximg);
*ximg = NULL;
/* Try to find FILE in data-directory, then x-bitmap-file-path. */
fd = openp (search_path, file, "", &file_found, 0);
- if (fd < 0)
+ if (fd == -1)
file_found = Qnil;
else
close (fd);
{":foreground", IMAGE_STRING_VALUE, 0},
{":background", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
int *ival;
{
int c;
+
+ loop:
/* Skip white space. */
while (*s < end && (c = *(*s)++, isspace (c)))
*s = *s - 1;
c = XBM_TK_IDENT;
}
+ else if (c == '/' && **s == '*')
+ {
+ /* C-style comment. */
+ ++*s;
+ while (**s && (**s != '*' || *(*s + 1) != '/'))
+ ++*s;
+ if (**s)
+ {
+ *s += 2;
+ goto loop;
+ }
+ }
return c;
}
depth);
xfree (data);
- if (img->pixmap == 0)
+ if (img->pixmap == None)
{
x_clear_image (f, img);
image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
{
struct image_keyword fmt[XBM_LAST];
Lisp_Object data;
- unsigned char *bitmap_data;
int depth;
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
char *bits;
- int parsed_p, height, width;
+ int parsed_p;
int in_memory_file_p = 0;
/* See if data looks like an in-memory XBM file. */
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
#ifdef ALLOC_XPM_COLORS
-static void xpm_init_color_cache P_ ((void));
+static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
static void xpm_free_color_cache P_ ((void));
static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
+static int xpm_color_bucket P_ ((char *));
+static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
+ XColor *, int));
/* An entry in a hash table used to cache color definitions of named
colors. This cache is necessary to speed up XPM image loading in
#define XPM_COLOR_CACHE_BUCKETS 1001
struct xpm_cached_color **xpm_color_cache;
-
/* Initialize the color cache. */
static void
-xpm_init_color_cache ()
+xpm_init_color_cache (f, attrs)
+ struct frame *f;
+ XpmAttributes *attrs;
{
size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
memset (xpm_color_cache, 0, nbytes);
init_color_table ();
+
+ if (attrs->valuemask & XpmColorSymbols)
+ {
+ int i;
+ XColor color;
+
+ for (i = 0; i < attrs->numsymbols; ++i)
+ if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ attrs->colorsymbols[i].value, &color))
+ {
+ color.pixel = lookup_rgb_color (f, color.red, color.green,
+ color.blue);
+ xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
+ }
+ }
}
}
+/* Return the bucket index for color named COLOR_NAME in the color
+ cache. */
+
+static int
+xpm_color_bucket (color_name)
+ char *color_name;
+{
+ unsigned h = 0;
+ char *s;
+
+ for (s = color_name; *s; ++s)
+ h = (h << 2) ^ *s;
+ return h %= XPM_COLOR_CACHE_BUCKETS;
+}
+
+
+/* On frame F, cache values COLOR for color with name COLOR_NAME.
+ BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
+ entry added. */
+
+static struct xpm_cached_color *
+xpm_cache_color (f, color_name, color, bucket)
+ struct frame *f;
+ char *color_name;
+ XColor *color;
+ int bucket;
+{
+ size_t nbytes;
+ struct xpm_cached_color *p;
+
+ if (bucket < 0)
+ bucket = xpm_color_bucket (color_name);
+
+ nbytes = sizeof *p + strlen (color_name);
+ p = (struct xpm_cached_color *) xmalloc (nbytes);
+ strcpy (p->name, color_name);
+ p->color = *color;
+ p->next = xpm_color_cache[bucket];
+ xpm_color_cache[bucket] = p;
+ return p;
+}
+
+
/* Look up color COLOR_NAME for frame F in the color cache. If found,
return the cached definition in *COLOR. Otherwise, make a new
entry in the cache and allocate the color. Value is zero if color
char *color_name;
XColor *color;
{
- unsigned h = 0;
- const char *s;
struct xpm_cached_color *p;
-
- for (s = color_name; *s; ++s)
- h = (h << 2) ^ *s;
- h %= XPM_COLOR_CACHE_BUCKETS;
+ int h = xpm_color_bucket (color_name);
for (p = xpm_color_cache[h]; p; p = p->next)
if (strcmp (p->name, color_name) == 0)
else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
color_name, color))
{
- size_t nbytes;
color->pixel = lookup_rgb_color (f, color->red, color->green,
color->blue);
- nbytes = sizeof *p + strlen (color_name);
- p = (struct xpm_cached_color *) xmalloc (nbytes);
- strcpy (p->name, color_name);
- p->color = *color;
- p->next = xpm_color_cache[h];
- xpm_color_cache[h] = p;
+ p = xpm_cache_color (f, color_name, color, h);
}
-
+
return p != NULL;
}
struct frame *f;
struct image *img;
{
- int rc, i;
+ int rc;
XpmAttributes attrs;
Lisp_Object specified_file, color_symbols;
/* Create a pixmap for the image, either from a file, or from a
string buffer containing data in the same format as an XPM file. */
#ifdef ALLOC_XPM_COLORS
- xpm_init_color_cache ();
+ xpm_init_color_cache (f, &attrs);
#endif
specified_file = image_spec_value (img->spec, QCfile, NULL);
#ifdef ALLOC_XPM_COLORS
img->colors = colors_in_color_table (&img->ncolors);
#else /* not ALLOC_XPM_COLORS */
+ int i;
+
img->ncolors = attrs.nalloc_pixels;
img->colors = (unsigned long *) xmalloc (img->ncolors
* sizeof *img->colors);
cmap = FRAME_X_COLORMAP (f);
color.pixel = pixel;
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+ x_query_color (f, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
if (rc)
static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
-/* Non-zero means draw a cross on images having `:algorithm
+/* Non-zero means draw a cross on images having `:conversion
disabled'. */
int cross_disabled_images;
p->pixel = XGetPixel (ximg, x, y);
if (rgb_p)
- XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- row, img->width);
+ x_query_colors (f, row, img->width);
}
XDestroyImage (ximg);
}
xfree (colors);
- x_clear_image (f, img);
+ x_clear_image_1 (f, img, 1, 0, 1);
x_put_x_image (f, oimg, pixmap, img->width, img->height);
x_destroy_x_image (oimg);
struct image *img;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
+
if (dpyinfo->n_planes >= 2)
{
/* Color (or grayscale). Convert to gray, and equalize. Just
if (img->mask)
{
XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
- img->mask = 0;
+ img->mask = None;
}
-
+
/* Create an image and pixmap serving as mask. */
rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
&mask_img, &img->mask);
PBM_ALGORITHM,
PBM_HEURISTIC_MASK,
PBM_MASK,
+ PBM_FOREGROUND,
+ PBM_BACKGROUND,
PBM_LAST
};
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_VALUE, 0},
+ {":background", IMAGE_STRING_VALUE, 0}
};
/* Structure describing the image type `pbm'. */
if (type == PBM_MONO)
{
int c = 0, g;
+ struct image_keyword fmt[PBM_LAST];
+ unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+ unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+
+ /* Parse the image specification. */
+ bcopy (pbm_format, fmt, sizeof fmt);
+ parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
+
+ /* Get foreground and background colors, maybe allocate colors. */
+ if (fmt[PBM_FOREGROUND].count)
+ fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
+ if (fmt[PBM_BACKGROUND].count)
+ bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
else
g = pbm_scan_number (&p, end);
- XPutPixel (ximg, x, y, (g
- ? FRAME_FOREGROUND_PIXEL (f)
- : FRAME_BACKGROUND_PIXEL (f)));
+ XPutPixel (ximg, x, y, g ? fg : bg);
}
}
else
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
cmap = FRAME_X_COLORMAP (f);
color.pixel = FRAME_BACKGROUND_PIXEL (f);
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+ x_query_color (f, &color);
bzero (&frame_background, sizeof frame_background);
frame_background.red = color.red;
{
x_destroy_x_image (ximg);
XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
- img->pixmap = 0;
+ img->pixmap = None;
goto error;
}
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
{
static int interlace_start[] = {0, 4, 2, 1};
static int interlace_increment[] = {8, 8, 4, 2};
- int pass, inc;
+ int pass;
int row = interlace_start[0];
pass = 0;
{":loader", IMAGE_FUNCTION_VALUE, 0},
{":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
{":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
- {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
/* Create the pixmap. */
- xassert (img->pixmap == 0);
+ xassert (img->pixmap == None);
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
img->width, img->height,
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
***********************************************************************/
/* If non-null, an asynchronous timer that, when it expires, displays
- a busy cursor on all frames. */
+ an hourglass cursor on all frames. */
-static struct atimer *busy_cursor_atimer;
+static struct atimer *hourglass_atimer;
-/* Non-zero means a busy cursor is currently shown. */
+/* Non-zero means an hourglass cursor is currently shown. */
-static int busy_cursor_shown_p;
+static int hourglass_shown_p;
-/* Number of seconds to wait before displaying a busy cursor. */
+/* Number of seconds to wait before displaying an hourglass cursor. */
-static Lisp_Object Vbusy_cursor_delay;
+static Lisp_Object Vhourglass_delay;
-/* Default number of seconds to wait before displaying a busy
+/* Default number of seconds to wait before displaying an hourglass
cursor. */
-#define DEFAULT_BUSY_CURSOR_DELAY 1
+#define DEFAULT_HOURGLASS_DELAY 1
/* Function prototypes. */
-static void show_busy_cursor P_ ((struct atimer *));
-static void hide_busy_cursor P_ ((void));
+static void show_hourglass P_ ((struct atimer *));
+static void hide_hourglass P_ ((void));
-/* Cancel a currently active busy-cursor timer, and start a new one. */
+/* Cancel a currently active hourglass timer, and start a new one. */
void
-start_busy_cursor ()
+start_hourglass ()
{
EMACS_TIME delay;
int secs, usecs = 0;
- cancel_busy_cursor ();
+ cancel_hourglass ();
- if (INTEGERP (Vbusy_cursor_delay)
- && XINT (Vbusy_cursor_delay) > 0)
- secs = XFASTINT (Vbusy_cursor_delay);
- else if (FLOATP (Vbusy_cursor_delay)
- && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
+ if (INTEGERP (Vhourglass_delay)
+ && XINT (Vhourglass_delay) > 0)
+ secs = XFASTINT (Vhourglass_delay);
+ else if (FLOATP (Vhourglass_delay)
+ && XFLOAT_DATA (Vhourglass_delay) > 0)
{
Lisp_Object tem;
- tem = Ftruncate (Vbusy_cursor_delay, Qnil);
+ tem = Ftruncate (Vhourglass_delay, Qnil);
secs = XFASTINT (tem);
- usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
+ usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
}
else
- secs = DEFAULT_BUSY_CURSOR_DELAY;
+ secs = DEFAULT_HOURGLASS_DELAY;
EMACS_SET_SECS_USECS (delay, secs, usecs);
- busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
- show_busy_cursor, NULL);
+ hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
+ show_hourglass, NULL);
}
-/* Cancel the busy cursor timer if active, hide a busy cursor if
+/* Cancel the hourglass cursor timer if active, hide a busy cursor if
shown. */
void
-cancel_busy_cursor ()
+cancel_hourglass ()
{
- if (busy_cursor_atimer)
+ if (hourglass_atimer)
{
- cancel_atimer (busy_cursor_atimer);
- busy_cursor_atimer = NULL;
+ cancel_atimer (hourglass_atimer);
+ hourglass_atimer = NULL;
}
- if (busy_cursor_shown_p)
- hide_busy_cursor ();
+ if (hourglass_shown_p)
+ hide_hourglass ();
}
-/* Timer function of busy_cursor_atimer. TIMER is equal to
- busy_cursor_atimer.
+/* Timer function of hourglass_atimer. TIMER is equal to
+ hourglass_atimer.
- Display a busy cursor on all frames by mapping the frames'
- busy_window. Set the busy_p flag in the frames' output_data.x
- structure to indicate that a busy cursor is shown on the
- frames. */
+ Display an hourglass pointer on all frames by mapping the frames'
+ hourglass_window. Set the hourglass_p flag in the frames'
+ output_data.x structure to indicate that an hourglass cursor is
+ shown on the frames. */
static void
-show_busy_cursor (timer)
+show_hourglass (timer)
struct atimer *timer;
{
/* The timer implementation will cancel this timer automatically
- after this function has run. Set busy_cursor_atimer to null
+ after this function has run. Set hourglass_atimer to null
so that we know the timer doesn't have to be canceled. */
- busy_cursor_atimer = NULL;
+ hourglass_atimer = NULL;
- if (!busy_cursor_shown_p)
+ if (!hourglass_shown_p)
{
Lisp_Object rest, frame;
BLOCK_INPUT;
FOR_EACH_FRAME (rest, frame)
- if (FRAME_X_P (XFRAME (frame)))
- {
- struct frame *f = XFRAME (frame);
-
- f->output_data.x->busy_p = 1;
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
+ {
+ Display *dpy = FRAME_X_DISPLAY (f);
+
+#ifdef USE_X_TOOLKIT
+ if (f->output_data.x->widget)
+#else
+ if (FRAME_OUTER_WINDOW (f))
+#endif
+ {
+ f->output_data.x->hourglass_p = 1;
- if (!f->output_data.x->busy_window)
- {
- unsigned long mask = CWCursor;
- XSetWindowAttributes attrs;
+ if (!f->output_data.x->hourglass_window)
+ {
+ unsigned long mask = CWCursor;
+ XSetWindowAttributes attrs;
- attrs.cursor = f->output_data.x->busy_cursor;
+ attrs.cursor = f->output_data.x->hourglass_cursor;
- f->output_data.x->busy_window
- = XCreateWindow (FRAME_X_DISPLAY (f),
- FRAME_OUTER_WINDOW (f),
- 0, 0, 32000, 32000, 0, 0,
- InputOnly,
- CopyFromParent,
- mask, &attrs);
- }
+ f->output_data.x->hourglass_window
+ = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
+ 0, 0, 32000, 32000, 0, 0,
+ InputOnly,
+ CopyFromParent,
+ mask, &attrs);
+ }
- XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
- XFlush (FRAME_X_DISPLAY (f));
- }
+ XMapRaised (dpy, f->output_data.x->hourglass_window);
+ XFlush (dpy);
+ }
+ }
+ }
- busy_cursor_shown_p = 1;
+ hourglass_shown_p = 1;
UNBLOCK_INPUT;
}
}
-/* Hide the busy cursor on all frames, if it is currently shown. */
+/* Hide the hourglass pointer on all frames, if it is currently
+ shown. */
static void
-hide_busy_cursor ()
+hide_hourglass ()
{
- if (busy_cursor_shown_p)
+ if (hourglass_shown_p)
{
Lisp_Object rest, frame;
if (FRAME_X_P (f)
/* Watch out for newly created frames. */
- && f->output_data.x->busy_window)
+ && f->output_data.x->hourglass_window)
{
- XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
- /* Sync here because XTread_socket looks at the busy_p flag
- that is reset to zero below. */
+ XUnmapWindow (FRAME_X_DISPLAY (f),
+ f->output_data.x->hourglass_window);
+ /* Sync here because XTread_socket looks at the
+ hourglass_p flag that is reset to zero below. */
XSync (FRAME_X_DISPLAY (f), False);
- f->output_data.x->busy_p = 0;
+ f->output_data.x->hourglass_p = 0;
}
}
- busy_cursor_shown_p = 0;
+ hourglass_shown_p = 0;
UNBLOCK_INPUT;
}
}
static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
Lisp_Object));
+static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
+ Lisp_Object, int *, int *));
-/* The frame of a currently visible tooltip, or null. */
+/* The frame of a currently visible tooltip. */
-struct frame *tip_frame;
+Lisp_Object tip_frame;
/* If non-nil, a timer started that hides the last tooltip when it
fires. */
Lisp_Object tip_timer;
Window tip_window;
+/* If non-nil, a vector of 3 elements containing the last args
+ with which x-show-tip was called. See there. */
+
+Lisp_Object last_show_tip_args;
+
+
+static Lisp_Object
+unwind_create_tip_frame (frame)
+ Lisp_Object frame;
+{
+ Lisp_Object deleted;
+
+ deleted = unwind_create_frame (frame);
+ if (EQ (deleted, Qt))
+ {
+ tip_window = None;
+ tip_frame = Qnil;
+ }
+
+ return deleted;
+}
+
+
/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. Value is the frame. */
+ PARMS is a list of frame parameters. Value is the frame.
+
+ Note that functions called here, esp. x_default_parameter can
+ signal errors, for instance when a specified color name is
+ undefined. We have to make sure that we're in a consistent state
+ when this happens. */
static Lisp_Object
x_create_tip_frame (dpyinfo, parms)
Lisp_Object name;
long window_prompting = 0;
int width, height;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
struct gcpro gcpro1, gcpro2, gcpro3;
struct kboard *kb;
+ int face_change_count_before = face_change_count;
check_x ();
frame = Qnil;
GCPRO3 (parms, name, frame);
- tip_frame = f = make_frame (1);
+ f = make_frame (1);
XSETFRAME (frame, f);
FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+ record_unwind_protect (unwind_create_tip_frame, frame);
+ /* By setting the output method, we're essentially saying that
+ the frame is live, as per FRAME_LIVE_P. If we get a signal
+ from this point on, x_destroy_window might screw up reference
+ counts etc. */
f->output_method = output_x_window;
f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
bzero (f->output_data.x, sizeof (struct x_output));
f->output_data.x->scroll_bar_background_pixel = -1;
f->icon_name = Qnil;
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+ image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
#ifdef MULTI_KBOARD
FRAME_KBOARD (f) = kb;
#endif
specbind (Qx_resource_name, name);
}
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
+ /* Extract the window parameters from the supplied values that are
+ needed to determine window geometry. */
{
Lisp_Object font;
unsigned long mask;
BLOCK_INPUT;
- mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
+ mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
+ if (DoesSaveUnders (dpyinfo->screen))
+ mask |= CWSaveUnder;
+
/* Window managers look at the override-redirect flag to determine
whether or net to give windows a decoration (Xlib spec, chapter
3.2.8). */
SET_FRAME_WIDTH (f, 0);
change_frame_size (f, height, width, 1, 0, 0);
+ /* Set up faces after all frame parameters are known. This call
+ also merges in face attributes specified for new frames.
+
+ Frame parameters may be changed if .Xdefaults contains
+ specifications for the default font. For example, if there is an
+ `Emacs.default.attributeBackground: pink', the `background-color'
+ attribute of the frame get's set, which let's the internal border
+ of the tooltip frame appear in pink. Prevent this. */
+ {
+ Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+
+ /* Set tip_frame here, so that */
+ tip_frame = frame;
+ call1 (Qface_set_after_frame_default, frame);
+
+ if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
+ Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
+ Qnil));
+ }
+
f->no_split = 1;
UNGCPRO;
its display. */
FRAME_X_DISPLAY_INFO (f)->reference_count++;
+ /* Setting attributes of faces of the tooltip frame from resources
+ and similar will increment face_change_count, which leads to the
+ clearing of all current matrices. Since this isn't necessary
+ here, avoid it by resetting face_change_count to the value it
+ had before we created the tip frame. */
+ face_change_count = face_change_count_before;
+
+ /* Discard the unwind_protect. */
return unbind_to (count, frame);
}
+/* Compute where to display tip frame F. PARMS is the list of frame
+ parameters for F. DX and DY are specified offsets from the current
+ location of the mouse. Return coordinates relative to the root
+ window of the display in *ROOT_X, and *ROOT_Y. */
+
+static void
+compute_tip_xy (f, parms, dx, dy, root_x, root_y)
+ struct frame *f;
+ Lisp_Object parms, dx, dy;
+ int *root_x, *root_y;
+{
+ Lisp_Object left, top;
+ int win_x, win_y;
+ Window root, child;
+ unsigned pmask;
+
+ /* User-specified position? */
+ left = Fcdr (Fassq (Qleft, parms));
+ top = Fcdr (Fassq (Qtop, parms));
+
+ /* Move the tooltip window where the mouse pointer is. Resize and
+ show it. */
+ BLOCK_INPUT;
+ XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
+ &root, &child, root_x, root_y, &win_x, &win_y, &pmask);
+ UNBLOCK_INPUT;
+
+ *root_x += XINT (dx);
+ *root_y += XINT (dy);
+
+ if (INTEGERP (left))
+ *root_x = XINT (left);
+ if (INTEGERP (top))
+ *root_y = XINT (top);
+}
+
+
DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
"Show STRING in a \"tooltip\" window on frame FRAME.\n\
A tooltip window is a small X window displaying a string.\n\
DX isn't specified). Likewise for the y-position; if a `top' frame\n\
parameter is specified, it determines the y-position of the tooltip\n\
window, otherwise it is displayed at the mouse position, with offset\n\
-DY added (default is -5).")
+DY added (default is -10).")
(string, frame, parms, timeout, dx, dy)
Lisp_Object string, frame, parms, timeout, dx, dy;
{
struct frame *f;
struct window *w;
- Window root, child;
Lisp_Object buffer, top, left;
+ int root_x, root_y;
struct buffer *old_buffer;
struct text_pos pos;
int i, width, height;
- int root_x, root_y, win_x, win_y;
- unsigned pmask;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
specbind (Qinhibit_redisplay, Qt);
CHECK_NUMBER (dx, 5);
if (NILP (dy))
- dy = make_number (-5);
+ dy = make_number (-10);
else
CHECK_NUMBER (dy, 6);
+ if (NILP (last_show_tip_args))
+ last_show_tip_args = Fmake_vector (make_number (3), Qnil);
+
+ if (!NILP (tip_frame))
+ {
+ Lisp_Object last_string = AREF (last_show_tip_args, 0);
+ Lisp_Object last_frame = AREF (last_show_tip_args, 1);
+ Lisp_Object last_parms = AREF (last_show_tip_args, 2);
+
+ if (EQ (frame, last_frame)
+ && !NILP (Fequal (last_string, string))
+ && !NILP (Fequal (last_parms, parms)))
+ {
+ struct frame *f = XFRAME (tip_frame);
+
+ /* Only DX and DY have changed. */
+ if (!NILP (tip_timer))
+ {
+ Lisp_Object timer = tip_timer;
+ tip_timer = Qnil;
+ call1 (Qcancel_timer, timer);
+ }
+
+ BLOCK_INPUT;
+ compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+ XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ root_x, root_y - PIXEL_HEIGHT (f));
+ UNBLOCK_INPUT;
+ goto start_timer;
+ }
+ }
+
/* Hide a previous tip, if any. */
Fx_hide_tip ();
+ ASET (last_show_tip_args, 0, string);
+ ASET (last_show_tip_args, 1, frame);
+ ASET (last_show_tip_args, 2, parms);
+
/* Add default values to frame parameters. */
if (NILP (Fassq (Qname, parms)))
parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
- tip_frame = f = XFRAME (frame);
+ f = XFRAME (frame);
/* Set up the frame's root window. Currently we use a size of 80
columns x 40 lines. If someone wants to show a larger tip, he
height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
- /* User-specified position? */
- left = Fcdr (Fassq (Qleft, parms));
- top = Fcdr (Fassq (Qtop, parms));
-
/* Move the tooltip window where the mouse pointer is. Resize and
show it. */
- BLOCK_INPUT;
- XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
- &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
- UNBLOCK_INPUT;
+ compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
- root_x += XINT (dx);
- root_y += XINT (dy);
-
- if (INTEGERP (left))
- root_x = XINT (left);
- if (INTEGERP (top))
- root_y = XINT (top);
-
BLOCK_INPUT;
XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
root_x, root_y - height, width, height);
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
UNBLOCK_INPUT;
-
+
/* Draw into the window. */
w->must_be_updated_p = 1;
update_single_window (w, 1);
set_buffer_internal_1 (old_buffer);
windows_or_buffers_changed = old_windows_or_buffers_changed;
+ start_timer:
/* Let the tip disappear after timeout seconds. */
tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
intern ("x-hide-tip"));
Value is t is tooltip was open, nil otherwise.")
()
{
- int count = specpdl_ptr - specpdl;
- int deleted_p = 0;
+ int count;
+ Lisp_Object deleted, frame, timer;
+ struct gcpro gcpro1, gcpro2;
+
+ /* Return quickly if nothing to do. */
+ if (NILP (tip_timer) && NILP (tip_frame))
+ return Qnil;
+ frame = tip_frame;
+ timer = tip_timer;
+ GCPRO2 (frame, timer);
+ tip_frame = tip_timer = deleted = Qnil;
+
+ count = BINDING_STACK_SIZE ();
specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
- if (!NILP (tip_timer))
- {
- call1 (intern ("cancel-timer"), tip_timer);
- tip_timer = Qnil;
- }
+ if (!NILP (timer))
+ call1 (Qcancel_timer, timer);
- if (tip_frame)
+ if (FRAMEP (frame))
{
- Lisp_Object frame;
-
- XSETFRAME (frame, tip_frame);
- Fdelete_frame (frame, Qt);
- tip_frame = NULL;
- deleted_p = 1;
+ Fdelete_frame (frame, Qnil);
+ deleted = Qt;
+
+#ifdef USE_LUCID
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over menu
+ items is unmapped. Redisplay the menu manually... */
+ {
+ struct frame *f = SELECTED_FRAME ();
+ Widget w = f->output_data.x->menubar_widget;
+ extern void xlwmenu_redisplay P_ ((Widget));
+
+ if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
+ && w != NULL)
+ {
+ BLOCK_INPUT;
+ xlwmenu_redisplay (w);
+ UNBLOCK_INPUT;
+ }
+ }
+#endif /* USE_LUCID */
}
- return unbind_to (count, deleted_p ? Qt : Qnil);
+ UNGCPRO;
+ return unbind_to (count, deleted);
}
XmListSetPos (list, item_pos);
}
-#ifdef HAVE_MOTIF_2_1
-
/* Process events until the user presses Cancel or OK. */
result = 0;
while (result == 0 || XtAppPending (Xt_app_con))
XtAppProcessEvent (Xt_app_con, XtIMAll);
-#else /* not HAVE_MOTIF_2_1 */
-
- /* Process all events until the user presses Cancel or OK. */
- for (result = 0; result == 0;)
- {
- XEvent event;
- Widget widget, parent;
-
- XtAppNextEvent (Xt_app_con, &event);
-
- /* See if the receiver of the event is one of the widgets of
- the file selection dialog. If so, dispatch it. If not,
- discard it. */
- widget = XtWindowToWidget (event.xany.display, event.xany.window);
- parent = widget;
- while (parent && parent != dialog)
- parent = XtParent (parent);
-
- if (parent == dialog
- || (event.type == Expose
- && !process_expose_from_menu (event)))
- XtDispatchEvent (&event);
- }
-
-#endif /* not HAVE_MOTIF_2_1 */
-
/* Get the result. */
if (result == XmCR_OK)
{
\f
+/***********************************************************************
+ Keyboard
+ ***********************************************************************/
+
+#ifdef HAVE_XKBGETKEYBOARD
+#include <X11/XKBlib.h>
+#include <X11/keysym.h>
+#endif
+
+DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
+ Sx_backspace_delete_keys_p, 0, 1, 0,
+ "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
+FRAME nil means use the selected frame.\n\
+Value is t if we know that both keys are present, and are mapped to the\n\
+usual X keysyms.")
+ (frame)
+ Lisp_Object frame;
+{
+#ifdef HAVE_XKBGETKEYBOARD
+ XkbDescPtr kb;
+ struct frame *f = check_x_frame (frame);
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Lisp_Object have_keys;
+ int major, minor, op, event, error;
+
+ BLOCK_INPUT;
+
+ /* Check library version in case we're dynamically linked. */
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+ if (!XkbLibraryVersion (&major, &minor))
+ {
+ UNBLOCK_INPUT;
+ return Qnil;
+ }
+
+ /* Check that the server supports XKB. */
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+ if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
+ {
+ UNBLOCK_INPUT;
+ return Qnil;
+ }
+
+ have_keys = Qnil;
+ kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
+ if (kb)
+ {
+ int delete_keycode = 0, backspace_keycode = 0, i;
+
+ if (XkbGetNames (dpy, XkbAllNamesMask, kb) == Success)
+ {
+ for (i = kb->min_key_code;
+ (i < kb->max_key_code
+ && (delete_keycode == 0 || backspace_keycode == 0));
+ ++i)
+ {
+ /* The XKB symbolic key names can be seen most easily
+ in the PS file generated by `xkbprint -label name $DISPLAY'. */
+ if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
+ delete_keycode = i;
+ else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
+ backspace_keycode = i;
+ }
+
+ XkbFreeNames (kb, 0, True);
+ }
+
+ XkbFreeClientMap (kb, 0, True);
+
+ if (delete_keycode
+ && backspace_keycode
+ && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
+ && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
+ have_keys = Qt;
+ }
+ UNBLOCK_INPUT;
+ return have_keys;
+#else /* not HAVE_XKBGETKEYBOARD */
+ return Qnil;
+#endif /* not HAVE_XKBGETKEYBOARD */
+}
+
+
+\f
/***********************************************************************
Initialization
***********************************************************************/
staticpro (&Qcenter);
Qcompound_text = intern ("compound-text");
staticpro (&Qcompound_text);
+ Qcancel_timer = intern ("cancel-timer");
+ staticpro (&Qcancel_timer);
/* This is the end of symbol initialization. */
/* Text property `display' should be nonsticky by default. */
DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
"Non-nil means always draw a cross over disabled images.\n\
-Disabled images are those having an `:algorithm disabled' property.\n\
+Disabled images are those having an `:conversion disabled' property.\n\
A cross is always drawn on black & white displays.");
cross_disabled_images = 0;
#endif
Vx_nontext_pointer_shape = Qnil;
- DEFVAR_LISP ("x-busy-pointer-shape", &Vx_busy_pointer_shape,
+ DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
"The shape of the pointer when Emacs is busy.\n\
This variable takes effect when you create a new frame\n\
or when you set the mouse color.");
- Vx_busy_pointer_shape = Qnil;
+ Vx_hourglass_pointer_shape = Qnil;
- DEFVAR_BOOL ("display-busy-cursor", &display_busy_cursor_p,
- "Non-zero means Emacs displays a busy cursor on window systems.");
- display_busy_cursor_p = 1;
+ DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+ "Non-zero means Emacs displays an hourglass pointer on window systems.");
+ display_hourglass_p = 1;
- DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
- "*Seconds to wait before displaying a busy-cursor.\n\
+ DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+ "*Seconds to wait before displaying an hourglass pointer.\n\
Value must be an integer or float.");
- Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
+ Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
#if 0 /* This doesn't really do anything. */
DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
or when you set the mouse color.");
Vx_sensitive_text_pointer_shape = Qnil;
+ DEFVAR_LISP ("x-window-horizontal-drag-cursor",
+ &Vx_window_horizontal_drag_shape,
+ "Pointer shape to use for indicating a window can be dragged horizontally.\n\
+This variable takes effect when you create a new frame\n\
+or when you set the mouse color.");
+ Vx_window_horizontal_drag_shape = Qnil;
+
DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
"A string indicating the foreground color of the cursor box.");
Vx_cursor_fore_pixel = Qnil;
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
defsubr (&Sx_focus_frame);
-
+ defsubr (&Sx_backspace_delete_keys_p);
+
/* Setting callback functions for fontset handler. */
get_font_info_func = x_get_font_info;
staticpro (&Qxbm);
QCtype = intern (":type");
staticpro (&QCtype);
- QCalgorithm = intern (":algorithm");
- staticpro (&QCalgorithm);
+ QCconversion = intern (":conversion");
+ staticpro (&QCconversion);
QCheuristic_mask = intern (":heuristic-mask");
staticpro (&QCheuristic_mask);
QCcolor_symbols = intern (":color-symbols");
defsubr (&Simage_size);
defsubr (&Simage_mask_p);
- busy_cursor_atimer = NULL;
- busy_cursor_shown_p = 0;
+ hourglass_atimer = NULL;
+ hourglass_shown_p = 0;
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
- staticpro (&tip_timer);
tip_timer = Qnil;
+ staticpro (&tip_timer);
+ tip_frame = Qnil;
+ staticpro (&tip_frame);
+
+ last_show_tip_args = Qnil;
+ staticpro (&last_show_tip_args);
#ifdef USE_MOTIF
defsubr (&Sx_file_dialog);