/* Synched up with: Not in FSF. */
+/* 7-8-00 !!#### This file needs definite Mule review. */
+
/* Original authors: Jamie Zawinski and the FSF */
/* Rewritten by Ben Wing and Chuck Thompson. */
#include "sysfile.h"
#include "systime.h"
+#if defined(HAVE_SHLIB) && defined(LWLIB_USES_ATHENA) && !defined(HAVE_ATHENA_3D)
+#include "sysdll.h"
+#endif /* HAVE_SHLIB and LWLIB_USES_ATHENA and not HAVE_ATHENA_3D */
+
#ifdef HAVE_OFFIX_DND
#include "offix.h"
#endif
* Finally, if all else fails, return `xemacs', as it is more
* appropriate (X11R5 returns `main').
*/
-static char *
-compute_x_app_name (int argc, char **argv)
+static Extbyte *
+compute_x_app_name (int argc, Extbyte **argv)
{
int i;
- char *ptr;
+ Extbyte *ptr;
for (i = 1; i < argc - 1; i++)
if (!strncmp(argv[i], "-name", max (2, strlen (argv[1]))))
validify_resource_component (Dynarr_atp (cda, Dynarr_length (cda) - len), len);
}
+#if 0
+/* compare visual info for qsorting */
+static int
+x_comp_visual_info (const void *elem1, const void *elem2)
+{
+ XVisualInfo *left, *right;
+
+ left = (XVisualInfo *)elem1;
+ right = (XVisualInfo *)elem2;
+
+ if ( left == NULL )
+ return -1;
+ if ( right == NULL )
+ return 1;
+
+ if ( left->depth > right->depth ) {
+ return 1;
+ }
+ else if ( left->depth == right->depth ) {
+ if ( left->colormap_size > right->colormap_size )
+ return 1;
+ if ( left->class > right->class )
+ return 1;
+ else if ( left->class < right->class )
+ return -1;
+ else
+ return 0;
+ }
+ else {
+ return -1;
+ }
+
+}
+#endif /* if 0 */
+
+#define XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
+static Visual *
+x_try_best_visual_class (Screen *screen, int scrnum, int visual_class)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ XVisualInfo vi_in;
+ XVisualInfo *vi_out = NULL;
+ int out_count;
+
+ vi_in.class = visual_class;
+ vi_in.screen = scrnum;
+ vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
+ &vi_in, &out_count);
+ if ( vi_out )
+ {
+ int i, best;
+ Visual *visual;
+ for (i = 0, best = 0; i < out_count; i++)
+ /* It's better if it's deeper, or if it's the same depth with
+ more cells (does that ever happen? Well, it could...)
+ NOTE: don't allow pseudo color to get larger than 8! */
+ if (((vi_out [i].depth > vi_out [best].depth) ||
+ ((vi_out [i].depth == vi_out [best].depth) &&
+ (vi_out [i].colormap_size > vi_out [best].colormap_size)))
+#ifdef XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
+ /* For now, the image library doesn't like PseudoColor visuals
+ of depths other than 1 or 8. Depths greater than 8 only occur
+ on machines which have TrueColor anyway, so probably we'll end
+ up using that (it is the one that `Best' would pick) but if a
+ PseudoColor visual is explicitly specified, pick the 8 bit one.
+ */
+ && (visual_class != PseudoColor ||
+ vi_out [i].depth == 1 ||
+ vi_out [i].depth == 8)
+#endif
+
+ /* SGI has 30-bit deep visuals. Ignore them.
+ (We only have 24-bit data anyway.)
+ */
+ && (vi_out [i].depth <= 24)
+ )
+ best = i;
+ visual = vi_out[best].visual;
+ XFree ((char *) vi_out);
+ return visual;
+ }
+ else
+ return 0;
+}
+
+static int
+x_get_visual_depth (Display *dpy, Visual *visual)
+{
+ XVisualInfo vi_in;
+ XVisualInfo *vi_out;
+ int out_count, d;
+
+ vi_in.visualid = XVisualIDFromVisual (visual);
+ vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask,
+ &vi_in, &out_count);
+ if (! vi_out) abort ();
+ d = vi_out [0].depth;
+ XFree ((char *) vi_out);
+ return d;
+}
+
+static Visual *
+x_try_best_visual (Display *dpy, int scrnum)
+{
+ Visual *visual = NULL;
+ Screen *screen = ScreenOfDisplay (dpy, scrnum);
+ if ((visual = x_try_best_visual_class (screen, scrnum, TrueColor))
+ && x_get_visual_depth (dpy, visual) >= 16 )
+ return visual;
+ if ((visual = x_try_best_visual_class (screen, scrnum, PseudoColor)))
+ return visual;
+ if ((visual = x_try_best_visual_class (screen, scrnum, TrueColor)))
+ return visual;
+#ifdef DIRECTCOLOR_WORKS
+ if ((visual = x_try_best_visual_class (screen, scrnum, DirectColor)))
+ return visual;
+#endif
+
+ visual = DefaultVisualOfScreen (screen);
+ if ( x_get_visual_depth (dpy, visual) >= 8 )
+ return visual;
+
+ if ((visual = x_try_best_visual_class (screen, scrnum, StaticGray)))
+ return visual;
+ if ((visual = x_try_best_visual_class (screen, scrnum, GrayScale)))
+ return visual;
+ return DefaultVisualOfScreen (screen);
+}
+
+
static void
x_init_device (struct device *d, Lisp_Object props)
{
Display *dpy;
Widget app_shell;
int argc;
- char **argv;
- CONST char *app_class;
- CONST char *app_name;
- CONST char *disp_name;
+ Extbyte **argv;
+ const char *app_class;
+ const char *app_name;
+ const char *disp_name;
Visual *visual = NULL;
int depth = 8; /* shut up the compiler */
Colormap cmap;
int screen;
+ /* */
+ int best_visual_found = 0;
+
+#if defined(HAVE_SHLIB) && defined(LWLIB_USES_ATHENA) && !defined(HAVE_ATHENA_3D)
+ /*
+ * In order to avoid the lossage with flat Athena widgets dynamically
+ * linking to one of the ThreeD variants, using the dynamic symbol helpers
+ * to look for symbols that shouldn't be there and refusing to run if they
+ * are seems a less toxic idea than having XEmacs crash when we try and
+ * use a subclass of a widget that has changed size.
+ *
+ * It's ugly, I know, and not going to work everywhere. It seems better to
+ * do our damnedest to try and tell the user what to expect rather than
+ * simply blow up though.
+ *
+ * All the ThreeD variants I have access to define the following function
+ * symbols in the shared library. The flat Xaw library does not define them:
+ *
+ * Xaw3dComputeBottomShadowRGB
+ * Xaw3dComputeTopShadowRGB
+ *
+ * So far only Linux has shown this problem. This seems to be portable to
+ * all the distributions (certainly all the ones I checked - Debian and
+ * Redhat)
+ *
+ * This will only work, sadly, with dlopen() -- the other dynamic linkers
+ * are simply not capable of doing what is needed. :/
+ */
+
+ {
+ /* Get a dll handle to the main process. */
+ dll_handle xaw_dll_handle = dll_open (NULL);
+
+ /* Did that fail? If so, continue without error.
+ * We could die here but, well, that's unfriendly and all -- plus I feel
+ * better about some crashing somewhere rather than preventing a perfectly
+ * good configuration working just because dll_open failed.
+ */
+ if (xaw_dll_handle != NULL)
+ {
+ /* Look for the Xaw3d function */
+ dll_func xaw_function_handle =
+ dll_function (xaw_dll_handle, "Xaw3dComputeTopShadowRGB");
+
+ /* If we found it, warn the user in big, nasty, unfriendly letters */
+ if (xaw_function_handle != NULL)
+ {
+ warn_when_safe (Qdevice, Qerror, "\n"
+"It seems that XEmacs is built dynamically linked to the flat Athena widget\n"
+"library but it finds a 3D Athena variant with the same name at runtime.\n"
+"\n"
+"This WILL cause your XEmacs process to dump core at some point.\n"
+"You should not continue to use this binary without resolving this issue.\n"
+"\n"
+"This can be solved with the xaw-wrappers package under Debian\n"
+"(register XEmacs as incompatible with all 3d widget sets, see\n"
+"update-xaw-wrappers(8) and .../doc/xaw-wrappers/README.packagers). It\n"
+"can be verified by checking the runtime path in /etc/ld.so.conf and by\n"
+"using `ldd /path/to/xemacs' under other Linux distributions. One\n"
+"solution is to use LD_PRELOAD or LD_LIBRARY_PATH to force ld.so to\n"
+"load the flat Athena widget library instead of the aliased 3D widget\n"
+"library (see ld.so(8) for use of these environment variables).\n\n"
+ );
+
+ }
+
+ /* Otherwise release the handle to the library
+ * No error catch here; I can't think of a way to recover anyhow.
+ */
+ dll_close (xaw_dll_handle);
+ }
+ }
+#endif /* HAVE_SHLIB and LWLIB_USES_ATHENA and not HAVE_ATHENA_3D */
+
XSETDEVICE (device, d);
display = DEVICE_CONNECTION (d);
make_argc_argv (Vx_initial_argv_list, &argc, &argv);
- GET_C_STRING_CTEXT_DATA_ALLOCA (display, disp_name);
+ LISP_STRING_TO_EXTERNAL (display, disp_name, Qctext);
/*
* Break apart the old XtOpenDisplay call into XOpenDisplay and
* XtDisplayInitialize so we can figure out whether there
* are any XEmacs resources in the resource database before
- * we intitialize Xt. This is so we can automagically support
+ * we initialize Xt. This is so we can automagically support
* both `Emacs' and `XEmacs' application classes.
*/
slow_down_interrupts ();
if (STRINGP (Vx_emacs_application_class) &&
XSTRING_LENGTH (Vx_emacs_application_class) > 0)
- GET_C_STRING_CTEXT_DATA_ALLOCA (Vx_emacs_application_class, app_class);
+ LISP_STRING_TO_EXTERNAL (Vx_emacs_application_class, app_class, Qctext);
else
{
app_class = (NILP (Vx_emacs_application_class) &&
Yuck. */
XtDisplayInitialize (Xt_app_con, dpy, compute_x_app_name (argc, argv),
app_class, emacs_options,
- XtNumber (emacs_options), &argc, argv);
+ XtNumber (emacs_options), &argc, (char **) argv);
speed_up_interrupts ();
screen = DefaultScreen (dpy);
data-directory/app-defaults/$LANG/Emacs.
This is in addition to the standard app-defaults files, and
does not override resources defined elsewhere */
- CONST char *data_dir;
+ const char *data_dir;
char *path;
XrmDatabase db = XtDatabase (dpy); /* #### XtScreenDatabase(dpy) ? */
- CONST char *locale = XrmLocaleOfDatabase (db);
+ const char *locale = XrmLocaleOfDatabase (db);
if (STRINGP (Vx_app_defaults_directory) &&
XSTRING_LENGTH (Vx_app_defaults_directory) > 0)
{
- GET_C_STRING_FILENAME_DATA_ALLOCA(Vx_app_defaults_directory, data_dir);
+ LISP_STRING_TO_EXTERNAL (Vx_app_defaults_directory, data_dir, Qfile_name);
path = (char *)alloca (strlen (data_dir) + strlen (locale) + 7);
sprintf (path, "%s%s/Emacs", data_dir, locale);
if (!access (path, R_OK))
}
else if (STRINGP (Vdata_directory) && XSTRING_LENGTH (Vdata_directory) > 0)
{
- GET_C_STRING_FILENAME_DATA_ALLOCA (Vdata_directory, data_dir);
+ LISP_STRING_TO_EXTERNAL (Vdata_directory, data_dir, Qfile_name);
path = (char *)alloca (strlen (data_dir) + 13 + strlen (locale) + 7);
sprintf (path, "%sapp-defaults/%s/Emacs", data_dir, locale);
if (!access (path, R_OK))
XtGetApplicationNameAndClass (dpy, (char **) &app_name, (char **) &app_class);
/* search for a matching visual if requested by the user, or setup the display default */
{
- char *buf1 = (char *)alloca (strlen (app_name) + 17);
- char *buf2 = (char *)alloca (strlen (app_class) + 17);
+ int resource_name_length = max (sizeof (".emacsVisual"),
+ sizeof (".privateColormap"));
+ char *buf1 = alloca_array (char, strlen (app_name) + resource_name_length);
+ char *buf2 = alloca_array (char, strlen (app_class) + resource_name_length);
char *type;
XrmValue value;
sprintf (buf2, "%s.EmacsVisual", app_class);
if (XrmGetResource (XtDatabase (dpy), buf1, buf2, &type, &value) == True)
{
- int cnt = 0, vis_class = PseudoColor;
+ int cnt = 0;
+ int vis_class = PseudoColor;
XVisualInfo vinfo;
- char *res, *str = (char*)value.addr;
+ char *str = (char*) value.addr;
-#define CHECK_VIS_CLASS(class) \
- else if (strncmp (str, #class, sizeof (#class) - 1) == 0) \
- cnt = sizeof (#class) - 1, vis_class = class
+#define CHECK_VIS_CLASS(visual_class) \
+ else if (memcmp (str, #visual_class, sizeof (#visual_class) - 1) == 0) \
+ cnt = sizeof (#visual_class) - 1, vis_class = visual_class
if (1)
;
if (cnt)
{
- res = str + cnt;
- depth = atoi (res);
+ depth = atoi (str + cnt);
if (depth == 0)
{
stderr_out ("Invalid Depth specification in %s... ignoring...\n", str);
}
if (visual == NULL)
{
- visual = DefaultVisual (dpy, screen);
- depth = DefaultDepth (dpy, screen);
+ /*
+ visual = DefaultVisual(dpy, screen);
+ depth = DefaultDepth(dpy, screen);
+ */
+ visual = x_try_best_visual (dpy, screen);
+ depth = x_get_visual_depth (dpy, visual);
+ best_visual_found = (visual != DefaultVisual (dpy, screen));
}
/* If we've got the same visual as the default and it's PseudoColor,
}
else
{
- /* We have to create a matching colormap anyway...
- ### think about using standard colormaps (need the Xmu libs?) */
- cmap = XCreateColormap (dpy, RootWindow(dpy, screen), visual, AllocNone);
- XInstallColormap (dpy, cmap);
+ if ( best_visual_found )
+ {
+ cmap = XCreateColormap (dpy, RootWindow (dpy, screen), visual, AllocNone);
+ }
+ else
+ {
+ /* We have to create a matching colormap anyway...
+ #### think about using standard colormaps (need the Xmu libs?) */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, screen), visual, AllocNone);
+ XInstallColormap(dpy, cmap);
+ }
}
}
XtRealizeWidget (app_shell);
}
-#ifdef HAVE_SESSION
+#ifdef HAVE_WMCOMMAND
{
int new_argc;
- char **new_argv;
+ Extbyte **new_argv;
make_argc_argv (Vcommand_line_args, &new_argc, &new_argv);
- XSetCommand (XtDisplay (app_shell), XtWindow (app_shell), new_argv, new_argc);
+ XSetCommand (XtDisplay (app_shell), XtWindow (app_shell),
+ (char **) new_argv, new_argc);
free_argc_argv (new_argv);
}
-#endif /* HAVE_SESSION */
+#endif /* HAVE_WMCOMMAND */
#ifdef HAVE_OFFIX_DND
DEVICE_X_GC_CACHE (d) = make_gc_cache (dpy, XtWindow(app_shell));
DEVICE_X_GRAY_PIXMAP (d) = None;
Xatoms_of_device_x (d);
- Xatoms_of_xselect (d);
+ Xatoms_of_select_x (d);
Xatoms_of_objects_x (d);
x_init_device_class (d);
}
static void
-x_mark_device (struct device *d, void (*markobj) (Lisp_Object))
+x_mark_device (struct device *d)
{
- markobj (DEVICE_X_WM_COMMAND_FRAME (d));
- markobj (DEVICE_X_DATA (d)->x_keysym_map_hash_table);
+ mark_object (DEVICE_X_WM_COMMAND_FRAME (d));
+ mark_object (DEVICE_X_DATA (d)->x_keysym_map_hash_table);
}
\f
/* handle X errors */
/************************************************************************/
-CONST char *
+const char *
x_event_name (int event_type)
{
- static CONST char *events[] =
+ static const char *events[] =
{
"0: ERROR!",
"1: REPLY",
#endif /* 0 */
+/* strcasecmp() is not sufficiently portable or standard,
+ and it's easier just to write our own. */
+static int
+ascii_strcasecmp (const char *s1, const char *s2)
+{
+ while (1)
+ {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
+ if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
+ if (c1 != c2) return c1 - c2;
+ if (c1 == '\0') return 0;
+ }
+}
+
static char_dynarr *name_char_dynarr;
static char_dynarr *class_char_dynarr;
The sixth arg NOERROR, if non-nil, means do not signal an error if a
bogus resource specification was retrieved (e.g. if a non-integer was
given when an integer was requested). In this case, a warning is issued
- instead.
+ instead, unless NOERROR is t, in which case no warning is issued.
The resource names passed to this function are looked up relative to the
locale.
found. If the third arg is `string', a string is returned, and if it is
`integer', an integer is returned. If the third arg is `boolean', then the
returned value is the list (t) for true, (nil) for false, and is nil to
-mean ``unspecified.''
+mean ``unspecified''.
*/
- (name, class, type, locale, device, no_error))
+ (name, class, type, locale, device, noerror))
{
char* name_string, *class_string;
char *raw_result;
XrmDatabase db;
Display *display;
- Error_behavior errb = decode_error_behavior_flag (no_error);
+ Error_behavior errb = decode_error_behavior_flag (noerror);
CHECK_STRING (name);
CHECK_STRING (class);
return build_string (raw_result);
else if (EQ (type, Qboolean))
{
- if (!strcasecmp (raw_result, "off") ||
- !strcasecmp (raw_result, "false") ||
- !strcasecmp (raw_result, "no"))
+ if (!ascii_strcasecmp (raw_result, "off") ||
+ !ascii_strcasecmp (raw_result, "false") ||
+ !ascii_strcasecmp (raw_result, "no"))
return Fcons (Qnil, Qnil);
- if (!strcasecmp (raw_result, "on") ||
- !strcasecmp (raw_result, "true") ||
- !strcasecmp (raw_result, "yes"))
+ if (!ascii_strcasecmp (raw_result, "on") ||
+ !ascii_strcasecmp (raw_result, "true") ||
+ !ascii_strcasecmp (raw_result, "yes"))
return Fcons (Qt, Qnil);
return maybe_continuable_error
(Qresource, errb,
*/
(keysym))
{
- CONST char *keysym_ext;
+ const char *keysym_ext;
CHECK_STRING (keysym);
- GET_C_STRING_CTEXT_DATA_ALLOCA (keysym, keysym_ext);
+ LISP_STRING_TO_EXTERNAL (keysym, keysym_ext, Qctext);
return XStringToKeysym (keysym_ext) ? Qt : Qnil;
}
DEFUN ("x-keysym-hash-table", Fx_keysym_hash_table, 0, 1, 0, /*
-Return a hash table which contains a hash key for all keysyms which
-name keys on the keyboard. See `x-keysym-on-keyboard-p'.
+Return a hash table containing a key for all keysyms on DEVICE.
+DEVICE must be an X11 display device. See `x-keysym-on-keyboard-p'.
*/
(device))
{
So long as the keyboard is grabbed, all keyboard events will be delivered
to emacs -- it is not possible for other X clients to eavesdrop on them.
Ungrab the keyboard with `x-ungrab-keyboard' (use an unwind-protect).
-Returns t if the grab was successful; nil otherwise.
+Returns t if the grab is successful, nil otherwise.
*/
(device))
{
return Qnil;
}
+DEFUN ("x-get-font-path", Fx_get_font_path, 0, 1, 0, /*
+Get the X Server's font path.
+
+See also `x-set-font-path'.
+*/
+ (device))
+{
+ Display *dpy = get_x_display (device);
+ int ndirs_return;
+ const char **directories = (const char **) XGetFontPath (dpy, &ndirs_return);
+ Lisp_Object font_path = Qnil;
+
+ if (!directories)
+ signal_simple_error ("Can't get X font path", device);
+
+ while (ndirs_return--)
+ font_path = Fcons (build_ext_string (directories[ndirs_return],
+ Qfile_name),
+ font_path);
+
+ return font_path;
+}
+
+DEFUN ("x-set-font-path", Fx_set_font_path, 1, 2, 0, /*
+Set the X Server's font path to FONT-PATH.
+
+There is only one font path per server, not one per client. Use this
+sparingly. It uncaches all of the X server's font information.
+
+Font directories should end in the path separator and should contain
+a file called fonts.dir usually created with the program mkfontdir.
+
+Setting the FONT-PATH to nil tells the X server to use the default
+font path.
+
+See also `x-get-font-path'.
+*/
+ (font_path, device))
+{
+ Display *dpy = get_x_display (device);
+ Lisp_Object path_entry;
+ const char **directories;
+ int i=0,ndirs=0;
+
+ EXTERNAL_LIST_LOOP (path_entry, font_path)
+ {
+ CHECK_STRING (XCAR (path_entry));
+ ndirs++;
+ }
+
+ directories = alloca_array (const char *, ndirs);
+
+ EXTERNAL_LIST_LOOP (path_entry, font_path)
+ {
+ LISP_STRING_TO_EXTERNAL (XCAR (path_entry), directories[i++], Qfile_name);
+ }
+
+ expect_x_error (dpy);
+ XSetFontPath (dpy, (char **) directories, ndirs);
+ signal_if_x_error (dpy, 1/*resumable_p*/);
+
+ return Qnil;
+}
+
\f
/************************************************************************/
/* initialization */
DEFSUBR (Fx_grab_keyboard);
DEFSUBR (Fx_ungrab_keyboard);
+ DEFSUBR (Fx_get_font_path);
+ DEFSUBR (Fx_set_font_path);
+
defsymbol (&Qx_error, "x-error");
defsymbol (&Qinit_pre_x_win, "init-pre-x-win");
defsymbol (&Qinit_post_x_win, "init-post-x-win");
}
void
+reinit_console_type_create_device_x (void)
+{
+ /* Initialize variables to speed up X resource interactions */
+ const char *valid_resource_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ while (*valid_resource_chars)
+ valid_resource_char_p[(unsigned int) (*valid_resource_chars++)] = 1;
+
+ name_char_dynarr = Dynarr_new (char);
+ class_char_dynarr = Dynarr_new (char);
+}
+
+void
console_type_create_device_x (void)
{
+ reinit_console_type_create_device_x ();
CONSOLE_HAS_METHOD (x, init_device);
CONSOLE_HAS_METHOD (x, finish_init_device);
CONSOLE_HAS_METHOD (x, mark_device);
CONSOLE_HAS_METHOD (x, delete_device);
CONSOLE_HAS_METHOD (x, device_system_metrics);
+}
- {
- /* Initialize variables to speed up X resource interactions */
- CONST char *valid_resource_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
- while (*valid_resource_chars)
- valid_resource_char_p[(unsigned int) (*valid_resource_chars++)] = 1;
-
- name_char_dynarr = Dynarr_new (char);
- class_char_dynarr = Dynarr_new (char);
- }
+void
+reinit_vars_of_device_x (void)
+{
+ error_expected = 0;
+ error_occurred = 0;
+
+ in_resource_setting = 0;
}
void
vars_of_device_x (void)
{
+ reinit_vars_of_device_x ();
+
DEFVAR_LISP ("x-emacs-application-class", &Vx_emacs_application_class /*
The X application class of the XEmacs process.
This controls, among other things, the name of the `app-defaults' file
staticpro (&Vdefault_x_device);
Vdefault_x_device = Qnil;
-
- error_expected = 0;
- error_occurred = 0;
-
- in_resource_setting = 0;
}