/* Functions for the X window system.
- Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
- Free Software Foundation.
+ Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
-#include <signal.h>
#include <stdio.h>
#include <math.h>
int display_hourglass_p;
+/* Non-zero means prompt with the old GTK file selection dialog. */
+
+int x_gtk_use_old_file_dialog;
+
+/* If non-zero, by default show hidden files in the GTK file chooser. */
+
+int x_gtk_show_hidden_files;
+
+/* If non-zero, don't show additional help text in the GTK file chooser. */
+
+int x_gtk_file_dialog_help_text;
+
+/* If non-zero, don't collapse to tool bar when it is detached. */
+
+int x_gtk_whole_detached_tool_bar;
+
/* The background and shape of the mouse pointer, and shape when not
over text or in the modeline. */
int had_errors = 0;
Window win = f->output_data.x->parent_desc;
- int count;
-
BLOCK_INPUT;
- count = x_catch_errors (FRAME_X_DISPLAY (f));
+ x_catch_errors (FRAME_X_DISPLAY (f));
if (win == FRAME_X_DISPLAY_INFO (f)->root_window)
win = FRAME_OUTER_WINDOW (f);
if (! had_errors)
{
- int ign;
+ unsigned int ign;
Window child, rootw;
/* Get the real coordinates for the WM window upper left corner */
had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
}
- x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (x_defined_color (f, SDATA (color_name), &cdef, 1))
return cdef.pixel;
- Fsignal (Qerror, Fcons (build_string ("Undefined color"),
- Fcons (color_name, Qnil)));
- return 0;
+ signal_error ("Undefined color", color_name);
}
FRAME_PTR f;
Lisp_Object file;
{
- struct gcpro gcpro1;
int result = 0;
Lisp_Object found;
- GCPRO1 (found);
-
found = x_find_image_file (file);
if (! NILP (found))
{
GdkPixbuf *pixbuf;
GError *err = NULL;
- char *filename;
-
- filename = SDATA (found);
+ char *filename = (char *) SDATA (found);
BLOCK_INPUT;
pixbuf = gdk_pixbuf_new_from_file (filename, &err);
UNBLOCK_INPUT;
}
- UNGCPRO;
return result;
}
+
+int
+xg_set_icon_from_xpm_data (f, data)
+ FRAME_PTR f;
+ char **data;
+{
+ int result = 0;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) data);
+
+ if (!pixbuf)
+ return 0;
+
+ gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
+ g_object_unref (pixbuf);
+ return 1;
+}
#endif /* USE_GTK */
Display *dpy = FRAME_X_DISPLAY (f);
Cursor cursor, nontext_cursor, mode_cursor, hand_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 = x->background_pixel;
BLOCK_INPUT;
/* It's not okay to crash if the user selects a screwy cursor. */
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
if (!NILP (Vx_pointer_shape))
{
/* Check and report errors with the above calls. */
x_check_errors (dpy, "can't set cursor shape: %s");
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
{
XColor fore_color, back_color;
if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
return;
}
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
+ else if (!NILP (arg) || NILP (oldval))
return;
f->icon_name = arg;
int width = FRAME_PIXEL_WIDTH (f);
int y = nlines * FRAME_LINE_HEIGHT (f);
- BLOCK_INPUT;
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- 0, y, width, height, False);
- UNBLOCK_INPUT;
+ /* height can be zero here. */
+ if (height > 0 && width > 0)
+ {
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ UNBLOCK_INPUT;
+ }
if (WINDOWP (f->tool_bar_window))
clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
Otherwise store 0 in *STRINGP, which means that the `encoding' of
the result should be `COMPOUND_TEXT'. */
-unsigned char *
-x_encode_text (string, coding_system, selectionp, text_bytes, stringp)
+static unsigned char *
+x_encode_text (string, coding_system, selectionp, text_bytes, stringp, freep)
Lisp_Object string, coding_system;
int *text_bytes, *stringp;
int selectionp;
+ int *freep;
{
unsigned char *str = SDATA (string);
int chars = SCHARS (string);
/* No multibyte character in OBJ. We need not encode it. */
*text_bytes = bytes;
*stringp = 1;
+ *freep = 0;
return str;
}
*stringp = (charset_info == 1
|| (!EQ (coding_system, Qcompound_text)
&& !EQ (coding_system, Qcompound_text_with_extensions)));
+ *freep = 1;
return buf;
}
in the future which can encode all Unicode characters.
But, for the moment, there's no way to know that the
current window manager supports it or not. */
- text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
+ text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp,
+ &do_free_text_value);
text.encoding = (stringp ? XA_STRING
: FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
text.format = 8;
text.nitems = bytes;
- /* Check early, because ENCODE_UTF_8 below may GC and name may be
- relocated. */
- do_free_text_value = text.value != SDATA (name);
-
- if (NILP (f->icon_name))
+ if (!STRINGP (f->icon_name))
{
icon = text;
}
{
/* See the above comment "Note: Encoding strategy". */
icon.value = x_encode_text (f->icon_name, coding_system, 0,
- &bytes, &stringp);
+ &bytes, &stringp, &do_free_icon_value);
icon.encoding = (stringp ? XA_STRING
: FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
icon.format = 8;
icon.nitems = bytes;
- do_free_icon_value = icon.value != SDATA (f->icon_name);
}
#ifdef USE_GTK
gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- SDATA (ENCODE_UTF_8 (name)));
+ (char *) SDATA (ENCODE_UTF_8 (name)));
#else /* not USE_GTK */
XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
#endif /* not USE_GTK */
BLOCK_INPUT;
{
- Atom type, *atoms = 0;
+ Atom type;
+ unsigned char *catoms;
int format = 0;
unsigned long nitems = 0;
unsigned long bytes_after;
FRAME_X_DISPLAY_INFO (f)->Xatom_wm_protocols,
(long)0, (long)100, False, XA_ATOM,
&type, &format, &nitems, &bytes_after,
- (unsigned char **) &atoms)
+ &catoms)
== Success)
&& format == 32 && type == XA_ATOM)
- while (nitems > 0)
- {
- nitems--;
- if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
- need_delete = 0;
- else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
- need_focus = 0;
- else if (atoms[nitems] == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
- need_save = 0;
- }
- if (atoms) XFree ((char *) atoms);
+ {
+ Atom *atoms = (Atom *) catoms;
+ while (nitems > 0)
+ {
+ nitems--;
+ if (atoms[nitems]
+ == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_delete_window)
+ need_delete = 0;
+ else if (atoms[nitems]
+ == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_take_focus)
+ need_focus = 0;
+ else if (atoms[nitems]
+ == FRAME_X_DISPLAY_INFO (f)->Xatom_wm_save_yourself)
+ need_save = 0;
+ }
+ }
+ if (catoms)
+ XFree (catoms);
}
{
Atom props [10];
};
-/* Create an X fontset on frame F with base font name
- BASE_FONTNAME.. */
+/* Create an X fontset on frame F with base font name BASE_FONTNAME. */
+
+char xic_defaut_fontset[] = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
+
+/* Create an Xt fontset spec from the name of a base font.
+ If `motif' is True use the Motif syntax. */
+char *
+xic_create_fontsetname (base_fontname, motif)
+ char *base_fontname;
+ Bool motif;
+{
+ const char *sep = motif ? ";" : ",";
+ char *fontsetname;
+
+ /* Make a fontset name from the base font name. */
+ if (xic_defaut_fontset == base_fontname)
+ { /* There is no base font name, use the default. */
+ int len = strlen (base_fontname) + 2;
+ fontsetname = xmalloc (len);
+ bzero (fontsetname, len);
+ strcpy (fontsetname, base_fontname);
+ }
+ else
+ {
+ /* Make a fontset name from the base font name.
+ The font set will be made of the following elements:
+ - the base font.
+ - the base font where the charset spec is replaced by -*-*.
+ - the same but with the family also replaced with -*-*-. */
+ char *p = base_fontname;
+ int i;
+
+ for (i = 0; *p; p++)
+ if (*p == '-') i++;
+ if (i != 14)
+ { /* As the font name doesn't conform to XLFD, we can't
+ modify it to generalize it to allcs and allfamilies.
+ Use the specified font plus the default. */
+ int len = strlen (base_fontname) + strlen (xic_defaut_fontset) + 3;
+ fontsetname = xmalloc (len);
+ bzero (fontsetname, len);
+ strcpy (fontsetname, base_fontname);
+ strcat (fontsetname, sep);
+ strcat (fontsetname, xic_defaut_fontset);
+ }
+ else
+ {
+ int len;
+ char *p1 = NULL, *p2 = NULL, *p3 = NULL;
+ char *font_allcs = NULL;
+ char *font_allfamilies = NULL;
+ char *font_all = NULL;
+ char *allcs = "*-*-*-*-*-*-*";
+ char *allfamilies = "-*-*-";
+ char *all = "*-*-*-*-";
+ char *base;
+
+ for (i = 0, p = base_fontname; i < 8; p++)
+ {
+ if (*p == '-')
+ {
+ i++;
+ if (i == 3)
+ p1 = p + 1;
+ else if (i == 7)
+ p2 = p + 1;
+ else if (i == 6)
+ p3 = p + 1;
+ }
+ }
+ /* If base_fontname specifies ADSTYLE, make it a
+ wildcard. */
+ if (*p3 != '*')
+ {
+ int diff = (p2 - p3) - 2;
+
+ base = alloca (strlen (base_fontname) + 1);
+ bcopy (base_fontname, base, p3 - base_fontname);
+ base[p3 - base_fontname] = '*';
+ base[(p3 - base_fontname) + 1] = '-';
+ strcpy (base + (p3 - base_fontname) + 2, p2);
+ p = base + (p - base_fontname) - diff;
+ p1 = base + (p1 - base_fontname);
+ p2 = base + (p2 - base_fontname) - diff;
+ base_fontname = base;
+ }
+
+ /* Build the font spec that matches all charsets. */
+ len = p - base_fontname + strlen (allcs) + 1;
+ font_allcs = (char *) alloca (len);
+ bzero (font_allcs, len);
+ bcopy (base_fontname, font_allcs, p - base_fontname);
+ strcat (font_allcs, allcs);
+
+ /* Build the font spec that matches all families and
+ add-styles. */
+ len = p - p1 + strlen (allcs) + strlen (allfamilies) + 1;
+ font_allfamilies = (char *) alloca (len);
+ bzero (font_allfamilies, len);
+ strcpy (font_allfamilies, allfamilies);
+ bcopy (p1, font_allfamilies + strlen (allfamilies), p - p1);
+ strcat (font_allfamilies, allcs);
+
+ /* Build the font spec that matches all. */
+ len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 1;
+ font_all = (char *) alloca (len);
+ bzero (font_all, len);
+ strcpy (font_all, allfamilies);
+ strcat (font_all, all);
+ bcopy (p2, font_all + strlen (all) + strlen (allfamilies), p - p2);
+ strcat (font_all, allcs);
+
+ /* Build the actual font set name. */
+ len = strlen (base_fontname) + strlen (font_allcs)
+ + strlen (font_allfamilies) + strlen (font_all) + 5;
+ fontsetname = xmalloc (len);
+ bzero (fontsetname, len);
+ strcpy (fontsetname, base_fontname);
+ strcat (fontsetname, sep);
+ strcat (fontsetname, font_allcs);
+ strcat (fontsetname, sep);
+ strcat (fontsetname, font_allfamilies);
+ strcat (fontsetname, sep);
+ strcat (fontsetname, font_all);
+ }
+ }
+ if (motif)
+ strcat (fontsetname, ":");
+ return fontsetname;
+}
static XFontSet
xic_create_xfontset (f, base_fontname)
struct frame *f;
char *base_fontname;
{
- XFontSet xfs;
- char **missing_list;
+ XFontSet xfs = NULL;
+ char **missing_list = NULL;
int missing_count;
char *def_string;
+ Lisp_Object rest, frame;
+
+ if (!base_fontname)
+ base_fontname = xic_defaut_fontset;
+
+ /* See if there is another frame already using same fontset. */
+ FOR_EACH_FRAME (rest, frame)
+ {
+ struct frame *cf = XFRAME (frame);
+ if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
+ && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
+ && FRAME_XIC_BASE_FONTNAME (cf)
+ && !strcmp (FRAME_XIC_BASE_FONTNAME (cf), base_fontname))
+ {
+ xfs = FRAME_XIC_FONTSET (cf);
+ break;
+ }
+ }
- xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
- base_fontname, &missing_list,
- &missing_count, &def_string);
- if (missing_list)
- XFreeStringList (missing_list);
+ if (!xfs)
+ {
+ char *fontsetname = xic_create_fontsetname (base_fontname, False);
+
+ /* New fontset. */
+ xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
+ fontsetname, &missing_list,
+ &missing_count, &def_string);
+ if (missing_list)
+ XFreeStringList (missing_list);
+ if (! xfs)
+ {
+ /* FONTSETNAME contains a list of font names (specific fonts
+ first, general fonts last), but giving that to
+ XCreateFontSet at once occasionally fails (bug of X?).
+ So, we try to call XCreateFontSet for each fontname. */
+ char *p0 = fontsetname, *p1;
- /* No need to free def_string. */
+ while (p0)
+ {
+ p1 = strchr (p0, ',');
+ if (p1)
+ *p1 = '\0';
+ xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
+ p0, &missing_list,
+ &missing_count, &def_string);
+ if (missing_list)
+ XFreeStringList (missing_list);
+ if (xfs)
+ break;
+ p0 = p1 ? p1 + 1 : NULL;
+ }
+ }
+ xfree (fontsetname);
+ }
+
+ if (FRAME_XIC_BASE_FONTNAME (f))
+ xfree (FRAME_XIC_BASE_FONTNAME (f));
+ FRAME_XIC_BASE_FONTNAME (f) = xstrdup (base_fontname);
+
+ /* No need to free def_string. */
return xfs;
}
+/* Free the X fontset of frame F if it is the last frame using it. */
+
+void
+xic_free_xfontset (f)
+ struct frame *f;
+{
+ Lisp_Object rest, frame;
+ int shared_p = 0;
+
+ if (!FRAME_XIC_FONTSET (f))
+ return;
+
+ /* See if there is another frame sharing the same fontset. */
+ FOR_EACH_FRAME (rest, frame)
+ {
+ struct frame *cf = XFRAME (frame);
+ if (cf != f && FRAME_LIVE_P (f) && FRAME_X_P (cf)
+ && FRAME_X_DISPLAY_INFO (cf) == FRAME_X_DISPLAY_INFO (f)
+ && FRAME_XIC_FONTSET (cf) == FRAME_XIC_FONTSET (f))
+ {
+ shared_p = 1;
+ break;
+ }
+ }
+
+ if (!shared_p)
+ /* The fontset is not used anymore. It is safe to free it. */
+ XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+
+ if (FRAME_XIC_BASE_FONTNAME (f))
+ xfree (FRAME_XIC_BASE_FONTNAME (f));
+ FRAME_XIC_BASE_FONTNAME (f) = NULL;
+ FRAME_XIC_FONTSET (f) = NULL;
+}
+
/* Value is the best input style, given user preferences USER (already
checked to be supported by Emacs), and styles supported by the
if (FRAME_XIC (f))
return;
+ /* Create X fontset. */
+ xfs = xic_create_xfontset
+ (f, (FRAME_FONTSET (f) < 0) ? NULL
+ : (char *) SDATA (fontset_ascii (FRAME_FONTSET (f))));
+
xim = FRAME_X_XIM (f);
if (xim)
{
XPoint spot;
XVaNestedList preedit_attr;
XVaNestedList status_attr;
- char *base_fontname;
- int fontset;
s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
spot.x = 0; spot.y = 1;
- /* Create X fontset. */
- fontset = FRAME_FONTSET (f);
- if (fontset < 0)
- base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
- else
- {
- /* Determine the base fontname from the ASCII font name of
- FONTSET. */
- char *ascii_font = (char *) SDATA (fontset_ascii (fontset));
- char *p = ascii_font;
- int i;
-
- for (i = 0; *p; p++)
- if (*p == '-') i++;
- if (i != 14)
- /* As the font name doesn't conform to XLFD, we can't
- modify it to get a suitable base fontname for the
- frame. */
- base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
- else
- {
- int len = strlen (ascii_font) + 1;
- char *p1 = NULL;
-
- for (i = 0, p = ascii_font; i < 8; p++)
- {
- if (*p == '-')
- {
- i++;
- if (i == 3)
- p1 = p + 1;
- }
- }
- base_fontname = (char *) alloca (len);
- bzero (base_fontname, len);
- strcpy (base_fontname, "-*-*-");
- bcopy (p1, base_fontname + 5, p - p1);
- strcat (base_fontname, "*-*-*-*-*-*-*");
- }
- }
- xfs = xic_create_xfontset (f, base_fontname);
/* Determine XIC style. */
if (xic_style == 0)
return;
XDestroyIC (FRAME_XIC (f));
- if (FRAME_XIC_FONTSET (f))
- XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+ xic_free_xfontset (f);
FRAME_XIC (f) = NULL;
- FRAME_XIC_FONTSET (f) = NULL;
}
XVaNestedList attr;
XFontSet xfs;
+ xic_free_xfontset (f);
+
xfs = xic_create_xfontset (f, base_fontname);
attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
XFree (attr);
- if (FRAME_XIC_FONTSET (f))
- XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
FRAME_XIC_FONTSET (f) = xfs;
}
if (! EQ (icon_x, Qunbound))
x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
+#if 0 /* x_get_arg removes the visibility parameter as a side effect,
+ but x_create_frame still needs it. */
/* Start up iconic or window? */
x_wm_set_window_state
(f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL),
Qicon)
? IconicState
: NormalState));
+#endif
x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
? f->icon_name
x_free_frame_resources (f);
+#if GLYPH_DEBUG
/* Check that reference counts are indeed correct. */
xassert (dpyinfo->reference_count == dpyinfo_refcount);
xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+#endif
return Qt;
}
check_x ();
+ parms = Fcopy_alist (parms);
+
/* Use this general default value to start with
until we know if this frame has a specified name. */
Vx_resource_name = Vinvocation_name;
f->output_data.x->scroll_bar_top_shadow_pixel = -1;
f->output_data.x->scroll_bar_bottom_shadow_pixel = -1;
#endif /* USE_TOOLKIT_SCROLL_BARS */
- 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;
+
+ /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
+ record_unwind_protect (unwind_create_frame, frame);
#if GLYPH_DEBUG
image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
dpyinfo_refcount = dpyinfo->reference_count;
if (! STRINGP (font))
font = build_string ("fixed");
- x_default_parameter (f, parms, Qfont, font,
- "font", "Font", RES_TYPE_STRING);
+ x_set_frame_parameters (f, Fcons (Fcons (Qfont, font), Qnil));
}
#ifdef USE_LUCID
/* We need to do this after creating the X window, so that the
icon-creation functions can say whose icon they're describing. */
- x_default_parameter (f, parms, Qicon_type, Qnil,
+ x_default_parameter (f, parms, Qicon_type, Qt,
"bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
x_default_parameter (f, parms, Qauto_raise, Qnil,
FRAME_OUTER_WINDOW (f),
dpyinfo->Xatom_wm_client_leader,
XA_WINDOW, 32, PropModeReplace,
- (char *) &dpyinfo->client_leader_window, 1);
+ (unsigned char *) &dpyinfo->client_leader_window, 1);
UNBLOCK_INPUT;
}
+ /* Initialize `default-minibuffer-frame' in case this is the first
+ frame on this display device. */
+ if (FRAME_HAS_MINIBUF_P (f)
+ && (!FRAMEP (kb->Vdefault_minibuffer_frame)
+ || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
+ kb->Vdefault_minibuffer_frame = frame;
+
+ /* All remaining specified parameters, which have not been "used"
+ by x_get_arg and friends, now go in the misc. alist of the frame. */
+ for (tem = parms; !NILP (tem); tem = XCDR (tem))
+ if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+ f->param_alist = Fcons (XCAR (tem), f->param_alist);
+
UNGCPRO;
/* Make sure windows on this frame appear in calls to next-window
{
struct frame *f = check_x_frame (frame);
Display *dpy = FRAME_X_DISPLAY (f);
- int count;
BLOCK_INPUT;
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
RevertToParent, CurrentTime);
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
return Qnil;
CHECK_STRING (color);
if (x_defined_color (f, SDATA (color), &foo, 0))
- {
- Lisp_Object rgb[3];
-
- rgb[0] = make_number (foo.red);
- rgb[1] = make_number (foo.green);
- rgb[2] = make_number (foo.blue);
- return Flist (3, rgb);
- }
+ return list3 (make_number (foo.red),
+ make_number (foo.green),
+ make_number (foo.blue));
else
return Qnil;
}
}
DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
- doc: /* Returns the vendor ID string of the X server of display DISPLAY.
+ doc: /* Returns the "vendor ID" string of the X server of display DISPLAY.
+\(Labelling every distributor as a "vendor" embodies the false assumption
+that operating systems cannot be developed and distributed noncommercially.)
The optional argument DISPLAY specifies which display to ask about.
DISPLAY should be either a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display. */)
DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
doc: /* Returns the version numbers of the X server of display DISPLAY.
The value is a list of three integers: the major and minor
-version numbers of the X Protocol in use, and the vendor-specific release
+version numbers of the X Protocol in use, and the distributor-specific release
number. See also the function `x-server-vendor'.
The optional argument DISPLAY specifies which display to ask about.
x_destroy_all_bitmaps (dpyinfo);
XSetCloseDownMode (dpyinfo->display, DestroyAll);
+#ifdef USE_GTK
+ xg_display_close (dpyinfo->display);
+#else
#ifdef USE_X_TOOLKIT
XtCloseDisplay (dpyinfo->display);
#else
XCloseDisplay (dpyinfo->display);
#endif
+#endif /* ! USE_GTK */
x_delete_display (dpyinfo);
UNBLOCK_INPUT;
data = (unsigned char *) xmalloc (nelements);
else if (element_format == 16)
data = (unsigned char *) xmalloc (nelements*2);
- else
- data = (unsigned char *) xmalloc (nelements*4);
+ else /* format == 32 */
+ /* The man page for XChangeProperty:
+ "If the specified format is 32, the property data must be a
+ long array."
+ This applies even if long is more than 64 bits. The X library
+ converts to 32 bits before sending to the X server. */
+ data = (unsigned char *) xmalloc (nelements * sizeof(long));
x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
}
if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
else w = FRAME_X_WINDOW (f);
-
+
XChangeProperty (FRAME_X_DISPLAY (f), w,
prop_atom, target_type, element_format, PropModeReplace,
data, nelements);
Atom prop_atom;
int rc;
Lisp_Object prop_value = Qnil;
- char *tmp_data = NULL;
+ unsigned char *tmp_data = NULL;
Atom actual_type;
Atom target_type = XA_STRING;
int actual_format;
rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
prop_atom, 0, 0, False, target_type,
&actual_type, &actual_format, &actual_size,
- &bytes_remaining, (unsigned char **) &tmp_data);
+ &bytes_remaining, &tmp_data);
if (rc == Success)
{
int size = bytes_remaining;
! NILP (delete_p), target_type,
&actual_type, &actual_format,
&actual_size, &bytes_remaining,
- (unsigned char **) &tmp_data);
+ &tmp_data);
if (rc == Success && tmp_data)
{
+ /* The man page for XGetWindowProperty says:
+ "If the returned format is 32, the returned data is represented
+ as a long array and should be cast to that type to obtain the
+ elements."
+ This applies even if long is more than 32 bits, the X library
+ converts from 32 bit elements received from the X server to long
+ and passes the long array to us. Thus, for that case bcopy can not
+ be used. We convert to a 32 bit type here, because so much code
+ assume on that.
+
+ The bytes and offsets passed to XGetWindowProperty refers to the
+ property and those are indeed in 32 bit quantities if format is
+ 32. */
+
+ if (actual_format == 32 && actual_format < BITS_PER_LONG)
+ {
+ unsigned long i;
+ int *idata = (int *) tmp_data;
+ long *ldata = (long *) tmp_data;
+
+ for (i = 0; i < actual_size; ++i)
+ idata[i] = (int) ldata[i];
+ }
+
if (NILP (vector_ret_p))
prop_value = make_string (tmp_data, size);
else
prop_value = x_property_data_to_lisp (f,
- (unsigned char *) tmp_data,
+ tmp_data,
actual_type,
actual_format,
actual_size);
static void show_hourglass P_ ((struct atimer *));
static void hide_hourglass P_ ((void));
+/* Return non-zero if houglass timer has been started or hourglass is shown. */
+
+int
+hourglass_started ()
+{
+ return hourglass_shown_p || hourglass_atimer != NULL;
+}
+
/* Cancel a currently active hourglass timer, and start a new one. */
EMACS_TIME delay;
int secs, usecs = 0;
+ /* Don't bother for ttys. */
+ if (NILP (Vwindow_system))
+ return;
+
cancel_hourglass ();
if (INTEGERP (Vhourglass_delay)
{
unsigned long mask = CWCursor;
XSetWindowAttributes attrs;
-
+#ifdef USE_GTK
+ Window parent = FRAME_X_WINDOW (f);
+#else
+ Window parent = FRAME_OUTER_WINDOW (f);
+#endif
attrs.cursor = f->output_data.x->hourglass_cursor;
f->output_data.x->hourglass_window
- = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
+ = XCreateWindow (dpy, parent,
0, 0, 32000, 32000, 0, 0,
InputOnly,
CopyFromParent,
check_x ();
- /* Use this general default value to start with until we know if
- this frame has a specified name. */
- Vx_resource_name = Vinvocation_name;
+ parms = Fcopy_alist (parms);
#ifdef MULTI_KBOARD
kb = dpyinfo->kboard;
&& !EQ (name, Qunbound)
&& !NILP (name))
error ("Invalid frame name--not a string or nil");
- Vx_resource_name = name;
frame = Qnil;
GCPRO3 (parms, name, frame);
if (INTEGERP (top))
*root_y = XINT (top);
- else if (*root_y + XINT (dy) - height < 0)
- *root_y -= XINT (dy);
- else
- {
- *root_y -= height;
+ else if (*root_y + XINT (dy) <= 0)
+ *root_y = 0; /* Can happen for negative dy */
+ else if (*root_y + XINT (dy) + height <= FRAME_X_DISPLAY_INFO (f)->height)
+ /* It fits below the pointer */
*root_y += XINT (dy);
- }
+ else if (height + XINT (dy) <= *root_y)
+ /* It fits above the pointer. */
+ *root_y -= height + XINT (dy);
+ else
+ /* Put it on the top. */
+ *root_y = 0;
if (INTEGERP (left))
*root_x = XINT (left);
+ else if (*root_x + XINT (dx) <= 0)
+ *root_x = 0; /* Can happen for negative dx */
else if (*root_x + XINT (dx) + width <= FRAME_X_DISPLAY_INFO (f)->width)
/* It fits to the right of the pointer. */
*root_x += XINT (dx);
clear_glyph_matrix (w->desired_matrix);
clear_glyph_matrix (w->current_matrix);
SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
- try_window (FRAME_ROOT_WINDOW (f), pos);
+ try_window (FRAME_ROOT_WINDOW (f), pos, 0);
/* Compute width and height of the tooltip. */
width = height = 0;
File selection dialog
***********************************************************************/
-#ifdef USE_MOTIF
+DEFUN ("x-uses-old-gtk-dialog", Fx_uses_old_gtk_dialog,
+ Sx_uses_old_gtk_dialog,
+ 0, 0, 0,
+ doc: /* Return t if the old Gtk+ file selection dialog is used. */)
+ ()
+{
+#ifdef USE_GTK
+ extern int use_dialog_box;
+ extern int use_file_dialog;
+ if (use_dialog_box
+ && use_file_dialog
+ && have_menus_p ()
+ && xg_uses_old_file_dialog ())
+ return Qt;
+#endif
+ return Qnil;
+}
+
+
+#ifdef USE_MOTIF
/* Callback for "OK" and "Cancel" on file selection dialog. */
static void
*result = XmCR_CANCEL;
}
+static Lisp_Object
+clean_up_file_dialog (arg)
+ Lisp_Object arg;
+{
+ struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+ Widget dialog = (Widget) p->pointer;
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+ /* Clean up. */
+ BLOCK_INPUT;
+ XtUnmanageChild (dialog);
+ XtDestroyWidget (dialog);
+ x_menu_set_in_use (0);
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+
+
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
doc: /* Read file name, prompting with PROMPT in directory DIR.
-Use a file selection dialog.
-Select DEFAULT-FILENAME in the dialog's file selection box, if
-specified. Don't let the user enter a file name in the file
-selection dialog's entry field, if MUSTMATCH is non-nil. */)
- (prompt, dir, default_filename, mustmatch)
- Lisp_Object prompt, dir, default_filename, mustmatch;
+Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
+selection box, if specified. If MUSTMATCH is non-nil, the returned file
+or directory must exist. ONLY-DIR-P is ignored." */)
+ (prompt, dir, default_filename, mustmatch, only_dir_p)
+ Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
{
int result;
struct frame *f = SELECTED_FRAME ();
Lisp_Object file = Qnil;
- Widget dialog, text, list, help;
+ Lisp_Object decoded_file;
+ Widget dialog, text, help;
Arg al[10];
int ac = 0;
extern XtAppContext Xt_app_con;
XmString dir_xmstring, pattern_xmstring;
int count = SPECPDL_INDEX ();
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
+
+ check_x ();
+
+ GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
+
+ if (popup_activated ())
+ error ("Trying to use a menu from within a menu-entry");
- GCPRO5 (prompt, dir, default_filename, mustmatch, file);
CHECK_STRING (prompt);
CHECK_STRING (dir);
XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
(XtPointer) &result);
- /* Disable the help button since we can't display help. */
+ /* Remove the help button since we can't display help. */
help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
- XtSetSensitive (help, False);
+ XtUnmanageChild (help);
/* Mark OK button as default. */
XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
/* Manage the dialog, so that list boxes get filled. */
XtManageChild (dialog);
- /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
- must include the path for this to work. */
- list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
if (STRINGP (default_filename))
{
XmString default_xmstring;
- int item_pos;
+ Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
+ Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
- default_xmstring
- = XmStringCreateLocalized (SDATA (default_filename));
+ XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
+ XmTextFieldReplace (wtext, 0, last_pos,
+ (SDATA (Ffile_name_nondirectory (default_filename))));
- if (!XmListItemExists (list, default_xmstring))
- {
- /* Add a new item if DEFAULT_FILENAME is not in the list. */
- XmListAddItem (list, default_xmstring, 0);
- item_pos = 0;
- }
- else
- item_pos = XmListItemPos (list, default_xmstring);
- XmStringFree (default_xmstring);
+ /* Select DEFAULT_FILENAME in the files list box. DEFAULT_FILENAME
+ must include the path for this to work. */
+
+ default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
- /* Select the item and scroll it into view. */
- XmListSelectPos (list, item_pos, True);
- XmListSetPos (list, item_pos);
+ if (XmListItemExists (list, default_xmstring))
+ {
+ int item_pos = XmListItemPos (list, default_xmstring);
+ /* Select the item and scroll it into view. */
+ XmListSelectPos (list, item_pos, True);
+ XmListSetPos (list, item_pos);
+ }
+
+ XmStringFree (default_xmstring);
}
+ record_unwind_protect (clean_up_file_dialog, make_save_value (dialog, 0));
+
/* Process events until the user presses Cancel or OK. */
+ x_menu_set_in_use (1);
result = 0;
while (result == 0)
{
XEvent event;
+ x_menu_wait_for_event (0);
XtAppNextEvent (Xt_app_con, &event);
- (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f) );
+ if (event.type == KeyPress
+ && FRAME_X_DISPLAY (f) == event.xkey.display)
+ {
+ KeySym keysym = XLookupKeysym (&event.xkey, 0);
+
+ /* Pop down on C-g. */
+ if (keysym == XK_g && (event.xkey.state & ControlMask) != 0)
+ XtUnmanageChild (dialog);
+ }
+
+ (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f));
}
/* Get the result. */
else
file = Qnil;
- /* Clean up. */
- XtUnmanageChild (dialog);
- XtDestroyWidget (dialog);
UNBLOCK_INPUT;
UNGCPRO;
if (NILP (file))
Fsignal (Qquit, Qnil);
- return unbind_to (count, file);
+ decoded_file = DECODE_FILE (file);
+
+ return unbind_to (count, decoded_file);
}
#endif /* USE_MOTIF */
#ifdef USE_GTK
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
- "Read file name, prompting with PROMPT in directory DIR.\n\
-Use a file selection dialog.\n\
-Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
-specified. Don't let the user enter a file name in the file\n\
-selection dialog's entry field, if MUSTMATCH is non-nil.")
- (prompt, dir, default_filename, mustmatch)
- Lisp_Object prompt, dir, default_filename, mustmatch;
+static Lisp_Object
+clean_up_dialog (arg)
+ Lisp_Object arg;
+{
+ x_menu_set_in_use (0);
+
+ return Qnil;
+}
+
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
+ doc: /* Read file name, prompting with PROMPT in directory DIR.
+Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
+selection box, if specified. If MUSTMATCH is non-nil, the returned file
+or directory must exist. If ONLY-DIR-P is non-nil, the user can only select
+directories. */)
+ (prompt, dir, default_filename, mustmatch, only_dir_p)
+ Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
{
FRAME_PTR f = SELECTED_FRAME ();
char *fn;
Lisp_Object file = Qnil;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+ Lisp_Object decoded_file;
+ int count = SPECPDL_INDEX ();
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
char *cdef_file;
- GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+ check_x ();
+
+ GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
+
+ if (popup_activated ())
+ error ("Trying to use a menu from within a menu-entry");
+
CHECK_STRING (prompt);
CHECK_STRING (dir);
/* Prevent redisplay. */
specbind (Qinhibit_redisplay, Qt);
+ record_unwind_protect (clean_up_dialog, Qnil);
BLOCK_INPUT;
else
cdef_file = SDATA (dir);
- fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
+ fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
+ ! NILP (mustmatch),
+ ! NILP (only_dir_p));
if (fn)
{
if (NILP (file))
Fsignal (Qquit, Qnil);
- return unbind_to (count, file);
+ decoded_file = DECODE_FILE (file);
+
+ return unbind_to (count, decoded_file);
}
#endif /* USE_GTK */
doc: /* Check if both Backspace and Delete keys are on the keyboard of FRAME.
FRAME nil means use the selected frame.
Value is t if we know that both keys are present, and are mapped to the
-usual X keysyms. */)
+usual X keysyms. Value is `lambda' if we cannot determine if both keys are
+present and mapped to the usual X keysyms. */)
(frame)
Lisp_Object frame;
{
if (!XkbLibraryVersion (&major, &minor))
{
UNBLOCK_INPUT;
- return Qnil;
+ return Qlambda;
}
/* Check that the server supports XKB. */
if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
{
UNBLOCK_INPUT;
- return Qnil;
+ return Qlambda;
}
+ /* In this code we check that the keyboard has physical keys with names
+ that start with BKSP (Backspace) and DELE (Delete), and that they
+ generate keysym XK_BackSpace and XK_Delete respectively.
+ This function is used to test if normal-erase-is-backspace should be
+ turned on.
+ An alternative approach would be to just check if XK_BackSpace and
+ XK_Delete are mapped to any key. But if any of those are mapped to
+ some non-intuitive key combination (Meta-Shift-Ctrl-whatever) and the
+ user doesn't know about it, it is better to return false here.
+ It is more obvious to the user what to do if she/he has two keys
+ clearly marked with names/symbols and one key does something not
+ expected (i.e. she/he then tries the other).
+ The cases where Backspace/Delete is mapped to some other key combination
+ are rare, and in those cases, normal-erase-is-backspace can be turned on
+ manually. */
+
have_keys = Qnil;
kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
if (kb)
UNBLOCK_INPUT;
return have_keys;
#else /* not HAVE_XKBGETKEYBOARD */
- return Qnil;
+ return Qlambda;
#endif /* not HAVE_XKBGETKEYBOARD */
}
Chinese, Japanese, and Korean. */);
Vx_pixel_size_width_font_regexp = Qnil;
+/* This is not ifdef:ed, so other builds than GTK can customize it. */
+ DEFVAR_BOOL ("x-gtk-use-old-file-dialog", &x_gtk_use_old_file_dialog,
+ doc: /* *Non-nil means prompt with the old GTK file selection dialog.
+If nil or if the file selection dialog is not available, the new GTK file
+chooser is used instead. To turn off all file dialogs set the
+variable `use-file-dialog'. */);
+ x_gtk_use_old_file_dialog = 0;
+
+ DEFVAR_BOOL ("x-gtk-show-hidden-files", &x_gtk_show_hidden_files,
+ doc: /* *If non-nil, the GTK file chooser will by default show hidden files.
+Note that this is just the default, there is a toggle button on the file
+chooser to show or not show hidden files on a case by case basis. */);
+ x_gtk_show_hidden_files = 0;
+
+ DEFVAR_BOOL ("x-gtk-file-dialog-help-text", &x_gtk_file_dialog_help_text,
+ doc: /* *If non-nil, the GTK file chooser will show additional help text.
+If more space for files in the file chooser dialog is wanted, set this to nil
+to turn the additional text off. */);
+ x_gtk_file_dialog_help_text = 1;
+
+ DEFVAR_BOOL ("x-gtk-whole-detached-tool-bar", &x_gtk_whole_detached_tool_bar,
+ doc: /* *If non-nil, a detached tool bar is shown in full.
+The default is to just show an arrow and pressing on that arrow shows
+the tool bar buttons. */);
+ x_gtk_whole_detached_tool_bar = 0;
+
+ Fprovide (intern ("x"), Qnil);
+
#ifdef USE_X_TOOLKIT
Fprovide (intern ("x-toolkit"), Qnil);
#ifdef USE_MOTIF
last_show_tip_args = Qnil;
staticpro (&last_show_tip_args);
-#ifdef USE_MOTIF
+ defsubr (&Sx_uses_old_gtk_dialog);
+#if defined (USE_MOTIF) || defined (USE_GTK)
defsubr (&Sx_file_dialog);
#endif
}