/* 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 Free Software Foundation.
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_use_old_gtk_file_dialog;
+
/* The background and shape of the mouse pointer, and shape when not
over text or in the modeline. */
Lisp_Object tail, frame;
struct frame *f;
+ if (wdesc == None) return 0;
+
for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
{
frame = XCAR (tail);
struct frame *f, *found;
struct x_output *x;
+ if (wdesc == None) return NULL;
+
found = NULL;
for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
{
struct frame *f;
struct x_output *x;
+ if (wdesc == None) return 0;
+
for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
{
frame = XCAR (tail);
struct frame *f;
struct x_output *x;
+ if (wdesc == None) return 0;
+
for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
{
frame = XCAR (tail);
struct frame *f;
struct x_output *x;
+ if (wdesc == None) return 0;
+
for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
{
frame = XCAR (tail);
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);
}
\f
-/* Change the name of frame F to NAME. If NAME is nil, set F's name to
- x_id_name.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
+/* Set the WM name to NAME for frame F. Also set the icon name.
+ If the frame already has an icon name, use that, otherwise set the
+ icon name to NAME. */
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_name (f, name, explicit)
- struct frame *f;
+static void
+x_set_name_internal (f, name)
+ FRAME_PTR f;
Lisp_Object name;
- int explicit;
{
- /* Make sure that requests from lisp code override requests from
- Emacs redisplay code. */
- if (explicit)
- {
- /* If we're switching from explicit to implicit, we had better
- update the mode lines and thereby update the title. */
- if (f->explicit_name && NILP (name))
- update_mode_lines = 1;
-
- f->explicit_name = ! NILP (name);
- }
- else if (f->explicit_name)
- return;
-
- /* If NAME is nil, set the name to the x_id_name. */
- if (NILP (name))
- {
- /* Check for no change needed in this very common case
- before we do any consing. */
- if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
- SDATA (f->name)))
- return;
- name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
- }
- else
- CHECK_STRING (name);
-
- /* Don't change the name if it's already NAME. */
- if (! NILP (Fstring_equal (name, f->name)))
- return;
-
- f->name = name;
-
- /* For setting the frame title, the title parameter should override
- the name parameter. */
- if (! NILP (f->title))
- name = f->title;
-
if (FRAME_X_WINDOW (f))
{
BLOCK_INPUT;
{
XTextProperty text, icon;
int bytes, stringp;
+ int do_free_icon_value = 0, do_free_text_value = 0;
Lisp_Object coding_system;
+ coding_system = Qcompound_text;
/* Note: Encoding strategy
We encode NAME by compound-text and use "COMPOUND-TEXT" in
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. */
- coding_system = Qcompound_text;
text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
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))
{
icon = text;
: 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 (name));
+ SDATA (ENCODE_UTF_8 (name)));
#else /* not USE_GTK */
XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
#endif /* not USE_GTK */
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &icon);
- if (!NILP (f->icon_name)
- && icon.value != (unsigned char *) SDATA (f->icon_name))
+ if (do_free_icon_value)
xfree (icon.value);
- if (text.value != (unsigned char *) SDATA (name))
+ if (do_free_text_value)
xfree (text.value);
}
#else /* not HAVE_X11R4 */
}
}
+/* Change the name of frame F to NAME. If NAME is nil, set F's name to
+ x_id_name.
+
+ If EXPLICIT is non-zero, that indicates that lisp code is setting the
+ name; if NAME is a string, set F's name to NAME and set
+ F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
+
+ If EXPLICIT is zero, that indicates that Emacs redisplay code is
+ suggesting a new name, which lisp code should override; if
+ F->explicit_name is set, ignore the new name; otherwise, set it. */
+
+void
+x_set_name (f, name, explicit)
+ struct frame *f;
+ Lisp_Object name;
+ int explicit;
+{
+ /* Make sure that requests from lisp code override requests from
+ Emacs redisplay code. */
+ if (explicit)
+ {
+ /* If we're switching from explicit to implicit, we had better
+ update the mode lines and thereby update the title. */
+ if (f->explicit_name && NILP (name))
+ update_mode_lines = 1;
+
+ f->explicit_name = ! NILP (name);
+ }
+ else if (f->explicit_name)
+ return;
+
+ /* If NAME is nil, set the name to the x_id_name. */
+ if (NILP (name))
+ {
+ /* Check for no change needed in this very common case
+ before we do any consing. */
+ if (!strcmp (FRAME_X_DISPLAY_INFO (f)->x_id_name,
+ SDATA (f->name)))
+ return;
+ name = build_string (FRAME_X_DISPLAY_INFO (f)->x_id_name);
+ }
+ else
+ CHECK_STRING (name);
+
+ /* Don't change the name if it's already NAME. */
+ if (! NILP (Fstring_equal (name, f->name)))
+ return;
+
+ f->name = name;
+
+ /* For setting the frame title, the title parameter should override
+ the name parameter. */
+ if (! NILP (f->title))
+ name = f->title;
+
+ x_set_name_internal (f, name);
+}
+
/* This function should be called when the user's lisp code has
specified a name for the frame; the name will override any set by the
redisplay code. */
else
CHECK_STRING (name);
- if (FRAME_X_WINDOW (f))
- {
- BLOCK_INPUT;
-#ifdef HAVE_X11R4
- {
- XTextProperty text, icon;
- int bytes, stringp;
- Lisp_Object coding_system;
-
- coding_system = Qcompound_text;
- /* See the comment "Note: Encoding strategy" in x_set_name. */
- text.value = x_encode_text (name, coding_system, 0, &bytes, &stringp);
- text.encoding = (stringp ? XA_STRING
- : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
- text.format = 8;
- text.nitems = bytes;
-
- if (NILP (f->icon_name))
- {
- icon = text;
- }
- else
- {
- /* See the comment "Note: Encoding strategy" in x_set_name. */
- icon.value = x_encode_text (f->icon_name, coding_system, 0,
- &bytes, &stringp);
- icon.encoding = (stringp ? XA_STRING
- : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
- icon.format = 8;
- icon.nitems = bytes;
- }
-
-#ifdef USE_GTK
- gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
- SDATA (name));
-#else /* not USE_GTK */
- XSetWMName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
-#endif /* not USE_GTK */
-
- XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
- &icon);
-
- if (!NILP (f->icon_name)
- && icon.value != (unsigned char *) SDATA (f->icon_name))
- xfree (icon.value);
- if (text.value != (unsigned char *) SDATA (name))
- xfree (text.value);
- }
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- SDATA (name));
- XStoreName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- SDATA (name));
-#endif /* not HAVE_X11R4 */
- UNBLOCK_INPUT;
- }
+ x_set_name_internal (f, name);
}
void
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;
+ char *font_allcs = NULL;
+ char *font_allfamilies = NULL;
+ char *font_all = NULL;
+ char *allcs = "*-*-*-*-*-*-*";
+ char *allfamilies = "-*-*-";
+ char *all = "*-*-*-*-";
+
+ 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;
+ }
+ }
+ /* 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. */
+ 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;
- xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
- base_fontname, &missing_list,
- &missing_count, &def_string);
- if (missing_list)
- XFreeStringList (missing_list);
+ if (!base_fontname)
+ base_fontname = xic_defaut_fontset;
- /* No need to free def_string. */
+ /* 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;
+ }
+ }
+
+ 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);
+ 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;
}
#endif /* not USE_GTK */
#endif /* not USE_X_TOOLKIT */
+/* Verify that the icon position args for this window are valid. */
+
+static void
+x_icon_verify (f, parms)
+ struct frame *f;
+ Lisp_Object parms;
+{
+ Lisp_Object icon_x, icon_y;
+
+ /* Set the position of the icon. Note that twm groups all
+ icons in an icon window. */
+ icon_x = x_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
+ icon_y = x_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
+ if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
+ {
+ CHECK_NUMBER (icon_x);
+ CHECK_NUMBER (icon_y);
+ }
+ else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
+ error ("Both left and top icon corners of icon must be specified");
+}
+
/* Handle the icon stuff for this window. Perhaps later we might
want an x_set_icon_position which can be called interactively as
well. */
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;
}
tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
+ x_icon_verify (f, parms);
+
/* Create the X widget or window. */
#ifdef USE_X_TOOLKIT
x_window (f, window_prompting, minibuffer_only);
}
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.
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;
#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);
old_buffer = current_buffer;
set_buffer_internal_1 (XBUFFER (buffer));
current_buffer->truncate_lines = Qnil;
+ specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
Ferase_buffer ();
Finsert (1, &text);
set_buffer_internal_1 (old_buffer);
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;
*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;
+ 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;
+
+ 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));
+
+ 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);
+ }
- /* 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;
#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;
+ int count = SPECPDL_INDEX ();
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
char *cdef_file;
- GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+ 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)
{
return Qnil;
}
+ /* 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)
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-use-old-gtk-file-dialog", &x_use_old_gtk_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_use_old_gtk_file_dialog = 0;
+
#ifdef USE_X_TOOLKIT
Fprovide (intern ("x-toolkit"), Qnil);
#ifdef USE_MOTIF
#endif /* USE_X_TOOLKIT */
#ifdef USE_GTK
+ /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it
+ is not an X toolkit in that sense (USE_X_TOOLKIT is not defined).
+ But for a user it is a toolkit for X, and indeed, configure
+ accepts --with-x-toolkit=gtk. */
+ Fprovide (intern ("x-toolkit"), Qnil);
Fprovide (intern ("gtk"), Qnil);
DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
last_show_tip_args = Qnil;
staticpro (&last_show_tip_args);
-#ifdef USE_MOTIF
+#if defined (USE_MOTIF) || defined (USE_GTK)
defsubr (&Sx_file_dialog);
#endif
}