it.first_visible_x = 0;
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
- struct window *menu_w;
+ struct window *menu_window;
+
+ menu_window = NULL;
+
if (FRAME_WINDOW_P (f))
{
/* Menu bar lines are displayed in the desired matrix of the
dummy window menu_bar_window. */
- menu_w = XWINDOW (f->menu_bar_window);
- init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
+ menu_window = XWINDOW (f->menu_bar_window);
+ init_iterator (&it, menu_window, -1, -1,
+ menu_window->desired_matrix->rows,
MENU_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
/* With the non-toolkit version, modify the menu bar window height
accordingly. */
- if (FRAME_WINDOW_P (it.f))
+ if (FRAME_WINDOW_P (it.f) && menu_window)
{
- struct glyph_row *row = it.glyph_row;
- int delta_height = ((row->y + row->height)
- - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_w));
+ struct glyph_row *row;
+ int delta_height;
+
+ row = it.glyph_row;
+ delta_height
+ = ((row->y + row->height)
+ - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
+
if (delta_height != 0)
{
FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
/* Catch errors since interning lots of targets can potentially
generate a BadAlloc error. */
x_catch_errors (FRAME_X_DISPLAY (f));
- XInternAtoms (FRAME_X_DISPLAY (f), target_names,
- ntargets, False, target_atoms);
+ x_intern_atoms (FRAME_DISPLAY_INFO (f), target_names,
+ ntargets, target_atoms);
x_check_errors (FRAME_X_DISPLAY (f),
"Failed to intern target atoms: %s");
x_uncatch_errors_after_check ();
elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
data = xnmalloc (nelements, elsize);
- x_fill_property_data (FRAME_X_DISPLAY (f), value, data, nelements,
+ x_fill_property_data (FRAME_DISPLAY_INFO (f), value, data, nelements,
element_format);
}
else
lisp_data_to_selection_data (struct x_display_info *dpyinfo,
Lisp_Object obj, struct selection_data *cs)
{
- Lisp_Object type = Qnil;
+ Lisp_Object type;
+ char **name_buffer;
+
+ USE_SAFE_ALLOCA;
+
+ type = Qnil;
eassert (cs != NULL);
x_atoms = data;
cs->format = 32;
cs->size = size;
- for (i = 0; i < size; i++)
- x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
+
+ if (size == 1)
+ x_atoms[0] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
+ else
+ {
+ SAFE_NALLOCA (name_buffer, sizeof *x_atoms, size);
+
+ for (i = 0; i < size; i++)
+ name_buffer[i] = SSDATA (SYMBOL_NAME (AREF (obj, i)));
+
+ x_intern_atoms (dpyinfo, name_buffer, size,
+ x_atoms);
+ }
}
else
/* This vector is an INTEGER set, or something like it */
signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
cs->type = symbol_to_x_atom (dpyinfo, type);
+
+ SAFE_FREE ();
}
static Lisp_Object
XClientMessageEvent). */
void
-x_fill_property_data (Display *dpy, Lisp_Object data, void *ret,
- int nelements_max, int format)
+x_fill_property_data (struct x_display_info *dpyinfo, Lisp_Object data,
+ void *ret, int nelements_max, int format)
{
unsigned long val;
unsigned long *d32 = (unsigned long *) ret;
else if (STRINGP (o))
{
block_input ();
- val = XInternAtom (dpy, SSDATA (o), False);
+ val = x_intern_cached_atom (dpyinfo, SSDATA (o), false);
unblock_input ();
}
else
memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l));
/* event.xclient.data can hold 20 chars, 10 shorts, or 5 longs. */
- x_fill_property_data (dpyinfo->display, values, event.xclient.data.b,
+ x_fill_property_data (dpyinfo, values, event.xclient.data.b,
5 * 32 / event.xclient.format,
event.xclient.format);
return value;
}
+/* Intern an array of atoms, and do so quickly, avoiding extraneous
+ roundtrips to the X server.
+
+ Avoid sending atoms that have already been found to the X server.
+ This cannot do anything that will end up triggering garbage
+ collection. */
+
+void
+x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count,
+ Atom *atoms_return)
+{
+ int i, j, indices[256];
+ char *new_names[256];
+ Atom results[256], candidate;
+
+ if (count > 256)
+ /* Atoms array too big to inspect reasonably, just send it to the
+ server and back. */
+ XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return);
+ else
+ {
+ for (i = 0, j = 0; i < count; ++i)
+ {
+ candidate = x_intern_cached_atom (dpyinfo, names[i],
+ true);
+
+ if (candidate)
+ atoms_return[i] = candidate;
+ else
+ {
+ indices[j++] = i;
+ new_names[j - 1] = names[i];
+ }
+ }
+
+ if (!j)
+ return;
+
+ /* Now, get the results back from the X server. */
+ XInternAtoms (dpyinfo->display, new_names, j, False,
+ results);
+
+ for (i = 0; i < j; ++i)
+ atoms_return[indices[i]] = results[i];
+ }
+}
+
#ifndef USE_GTK
/* Set up XEmbed for F, and change its save set to handle the parent
extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
int *, int *, int *, unsigned int *);
+extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
+ bool);
+extern void x_intern_atoms (struct x_display_info *, char **, int, Atom *);
+extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
+ ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
#ifdef HAVE_GTK3
extern void x_scroll_bar_configure (GdkEvent *);
struct input_event *,
bool, int, int);
extern int x_check_property_data (Lisp_Object);
-extern void x_fill_property_data (Display *,
- Lisp_Object,
- void *,
- int,
- int);
+extern void x_fill_property_data (struct x_display_info *, Lisp_Object,
+ void *, int, int);
extern Lisp_Object x_property_data_to_lisp (struct frame *,
const unsigned char *,
Atom,
Lisp_Object);
extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Time);
-extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
- bool);
-extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
- ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
extern void mark_xselect (void);