changeset 2586:196ee3cd1ac5

[xemacs-hg @ 2005-02-15 01:19:48 by ben] first check-in of ben-fixup branch
author ben
date Tue, 15 Feb 2005 01:21:24 +0000
parents a81fa696baa5
children 1e2a3710564c
files src/console-xlike.h src/dumper.h src/event-xlike.c src/gccache-gtk.h src/gccache-x.c src/gccache-xlike-inc.c src/intl-gtk.c src/objects-xlike-inc.c src/ui-gtk-inc.c src/universe.h src/xgccache.c src/xgccache.h
diffstat 12 files changed, 2101 insertions(+), 469 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console-xlike.h	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,51 @@
+/* Shared event code between X and GTK.
+   Copyright (C) 2003, 2005 Ben Wing.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+#ifndef INCLUDED_console_xlike_h_
+#define INCLUDED_console_xlike_h_
+
+#include <X11/Xlib.h>
+
+struct xlike_event_key_data
+{
+  int MetaMask, HyperMask, SuperMask, AltMask, ModeMask;
+  KeySym lock_interpretation;
+
+  XModifierKeymap *x_modifier_keymap;
+
+  KeySym *x_keysym_map;
+  int x_keysym_map_min_code;
+  int x_keysym_map_max_code;
+  int x_keysym_map_keysyms_per_code;
+  Lisp_Object x_keysym_map_hash_table;
+};
+
+void xlike_init_modifier_mapping (struct device *d,
+				  struct xlike_event_key_data *xd);
+void xlike_reset_key_mapping (struct device *d,
+			      struct xlike_event_key_data *xd);
+void xlike_reset_modifier_mapping (struct device *d,
+				   struct xlike_event_key_data *xd);
+void free_xlike_event_key_data (struct xlike_event_key_data *xd);
+Lisp_Object xlike_keysym_to_emacs_keysym (long keysym, int simple_p);
+
+#endif /* INCLUDED_console_xlike_h_ */
--- a/src/dumper.h	Mon Feb 14 22:51:46 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/* Portable data dumper for XEmacs.
-   Copyright (C) 1999-2000 Olivier Galibert
-
-This file is part of XEmacs.
-
-XEmacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-XEmacs is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* Synched up with: Not in FSF. */
-
-/* This file has been Mule-ized, Ben Wing, 10-7-04. */
-
-#ifndef INCLUDED_dumper_h
-#define INCLUDED_dumper_h
-
-BEGIN_C_DECLS
-
-void pdump_objects_unmark (void);
-void pdump (void);
-int pdump_load (const Wexttext *argv0);
-void pdump_backtrace (void);
-extern unsigned int dump_id;
-extern Rawbyte *pdump_start, *pdump_end;
-
-END_C_DECLS
-
-#endif /* INCLUDED_dumper_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/event-xlike.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,664 @@
+/* Shared event code between X and GTK.
+   Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1995 Sun Microsystems, Inc.
+   Copyright (C) 1996, 2001, 2002, 2003 Ben Wing.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+#include <config.h>
+#include "lisp.h"
+
+#include "charset.h"
+#include "elhash.h"
+#include "events.h"
+
+#ifdef HAVE_GTK
+#include "console-gtk-impl.h"
+#include <gdk/gdkx.h>
+#endif
+/* Unfortunately GTK currently needs to use some X-specific stuff so we
+   can't conditionalize the following on HAVE_X_WINDOWS, like we should.
+
+   #### BILL!!! Fix this please! */
+#include "console-x-impl.h"
+
+#include "device-impl.h"
+
+#include "toolbar-common.h"
+
+Lisp_Object Qkey_mapping;
+Lisp_Object Qsans_modifiers;
+
+
+/************************************************************************/
+/*                            keymap handling                           */
+/************************************************************************/
+
+/* X bogusly doesn't define the interpretations of any bits besides
+   ModControl, ModShift, and ModLock; so the Interclient Communication
+   Conventions Manual says that we have to bend over backwards to figure
+   out what the other modifier bits mean.  According to ICCCM:
+
+   - Any keycode which is assigned ModControl is a "control" key.
+
+   - Any modifier bit which is assigned to a keycode which generates Meta_L
+     or Meta_R is the modifier bit meaning "meta".  Likewise for Super, Hyper,
+     etc.
+
+   - Any keypress event which contains ModControl in its state should be
+     interpreted as a "control" character.
+
+   - Any keypress event which contains a modifier bit in its state which is
+     generated by a keycode whose corresponding keysym is Meta_L or Meta_R
+     should be interpreted as a "meta" character.  Likewise for Super, Hyper,
+     etc.
+
+   - It is illegal for a keysym to be associated with more than one modifier
+     bit.
+
+   This means that the only thing that emacs can reasonably interpret as a
+   "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
+   one of the modifier bits Mod1-Mod5.
+
+   Unfortunately, many keyboards don't have Meta keys in their default
+   configuration.  So, if there are no Meta keys, but there are "Alt" keys,
+   emacs will interpret Alt as Meta.  If there are both Meta and Alt keys,
+   then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
+   mean "Symbol," but that just confused the hell out of way too many people).
+
+   This works with the default configurations of the 19 keyboard-types I've
+   checked.
+
+   Emacs detects keyboard configurations which violate the above rules, and
+   prints an error message on the standard-error-output.  (Perhaps it should
+   use a pop-up-window instead.)
+ */
+
+static Display *
+xlike_device_to_display (struct device *d)
+{
+#ifdef HAVE_GTK
+  if (DEVICE_GTK_P (d))
+    return GDK_DISPLAY ();
+#endif /* HAVE_GTK */
+#ifdef HAVE_X_WINDOWS
+  if (DEVICE_GTK_P (d))
+    return DEVICE_X_DISPLAY (d);
+#endif /* HAVE_X_WINDOWS */
+  ABORT ();
+  return NULL;
+}
+
+/* For every key on the keyboard that has a known character correspondence,
+   we define the ascii-character property of the keysym, and make the
+   default binding for the key be self-insert-command.
+
+   The following magic is basically intimate knowledge of X11/keysymdef.h.
+   The keysym mappings defined by X11 are based on the iso8859 standards,
+   except for Cyrillic and Greek.
+
+   In a non-Mule world, a user can still have a multi-lingual editor, by doing
+   (set-face-font "...-iso8859-2" (current-buffer))
+   for all their Latin-2 buffers, etc.  */
+
+static Lisp_Object
+x_keysym_to_character (KeySym keysym)
+{
+#ifdef MULE
+  Lisp_Object charset = Qzero;
+#define USE_CHARSET(var,cs) \
+  ((var) = charset_by_leading_byte (LEADING_BYTE_##cs))
+#else
+#define USE_CHARSET(var,lb)
+#endif /* MULE */
+  int code = 0;
+
+  if ((keysym & 0xff) < 0xa0)
+    return Qnil;
+
+  switch (keysym >> 8)
+    {
+    case 0: /* ASCII + Latin1 */
+      USE_CHARSET (charset, LATIN_ISO8859_1);
+      code = keysym & 0x7f;
+      break;
+    case 1: /* Latin2 */
+      USE_CHARSET (charset, LATIN_ISO8859_2);
+      code = keysym & 0x7f;
+      break;
+    case 2: /* Latin3 */
+      USE_CHARSET (charset, LATIN_ISO8859_3);
+      code = keysym & 0x7f;
+      break;
+    case 3: /* Latin4 */
+      USE_CHARSET (charset, LATIN_ISO8859_4);
+      code = keysym & 0x7f;
+      break;
+    case 4: /* Katakana */
+      USE_CHARSET (charset, KATAKANA_JISX0201);
+      if ((keysym & 0xff) > 0xa0)
+	code = keysym & 0x7f;
+      break;
+    case 5: /* Arabic */
+      USE_CHARSET (charset, ARABIC_ISO8859_6);
+      code = keysym & 0x7f;
+      break;
+    case 6: /* Cyrillic */
+      {
+	static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
+	{0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
+	 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
+	 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
+	 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
+	 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
+	 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
+	 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
+	 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
+	 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
+	 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+	 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
+	 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a};
+	USE_CHARSET (charset, CYRILLIC_ISO8859_5);
+	code = cyrillic[(keysym & 0x7f) - 0x20];
+	break;
+      }
+    case 7: /* Greek */
+      {
+	static unsigned char const greek[] = /* 0x20 - 0x7f */
+	{0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
+	 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
+	 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
+	 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
+	 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
+	 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	USE_CHARSET (charset, GREEK_ISO8859_7);
+	code = greek[(keysym & 0x7f) - 0x20];
+	break;
+      }
+    case 8: /* Technical */
+      break;
+    case 9: /* Special */
+      break;
+    case 10: /* Publishing */
+      break;
+    case 11: /* APL */
+      break;
+    case 12: /* Hebrew */
+      USE_CHARSET (charset, HEBREW_ISO8859_8);
+      code = keysym & 0x7f;
+      break;
+    case 13: /* Thai */
+      /* #### This needs to deal with character composition. */
+      USE_CHARSET (charset, THAI_TIS620);
+      code = keysym & 0x7f;
+      break;
+    case 14: /* Korean Hangul */
+      break;
+    case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
+      break;
+    case 32: /* Currency */
+      break;
+    default:
+      break;
+    }
+
+  if (code == 0)
+    return Qnil;
+
+#ifdef MULE
+  return make_char (make_ichar (charset, code, 0));
+#else
+  return make_char (code + 0x80);
+#endif
+}
+
+/* See comment near character_to_event().
+*/
+static void
+maybe_define_x_key_as_self_inserting_character (KeySym keysym,
+						Lisp_Object symbol)
+{
+  Lisp_Object character = x_keysym_to_character (keysym);
+
+  if (CHARP (character))
+    {
+      extern Lisp_Object Vcurrent_global_map;
+      extern Lisp_Object Qascii_character;
+      if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil))) 
+        {
+	  Fput (symbol, Qascii_character, character);
+	  Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command); 
+        }
+    }
+}
+
+/* Currently, GDK keysyms are exactly like X keysyms.  If this ever
+   changes, we should rewrite this, but currently there's no point. */
+
+Lisp_Object
+xlike_keysym_to_emacs_keysym (long keysym, int simple_p)
+{
+  Ibyte *name;
+  if (keysym >= XK_exclam && keysym <= XK_asciitilde)
+    /* We must assume that the X keysym numbers for the ASCII graphic
+       characters are the same as their ASCII codes.  */
+    return make_char (keysym);
+
+  switch (keysym)
+    {
+      /* These would be handled correctly by the default case, but by
+	 special-casing them here we don't garbage a string or call
+	 intern().  */
+    case XK_BackSpace:	return QKbackspace;
+    case XK_Tab:	return QKtab;
+    case XK_Linefeed:	return QKlinefeed;
+    case XK_Return:	return QKreturn;
+    case XK_Escape:	return QKescape;
+    case XK_space:	return QKspace;
+    case XK_Delete:	return QKdelete;
+    case 0:		return Qnil;
+    default:
+      if (simple_p) return Qnil;
+      name = NEW_EXTERNAL_TO_C_STRING (XKeysymToString (keysym),
+				       Qx_keysym_encoding);
+      if (!name || !name[0])
+	/* This happens if there is a mismatch between the Xlib of
+           XEmacs and the Xlib of the X server...
+
+	   Let's hard-code in some knowledge of common keysyms introduced
+	   in recent X11 releases.  Snarfed from X11/keysymdef.h
+
+	   Probably we should add some stuff here for X11R6. */
+	switch (keysym)
+	  {
+	  case 0xFF95: return KEYSYM ("kp-home");
+	  case 0xFF96: return KEYSYM ("kp-left");
+	  case 0xFF97: return KEYSYM ("kp-up");
+	  case 0xFF98: return KEYSYM ("kp-right");
+	  case 0xFF99: return KEYSYM ("kp-down");
+	  case 0xFF9A: return KEYSYM ("kp-prior");
+	  case 0xFF9B: return KEYSYM ("kp-next");
+	  case 0xFF9C: return KEYSYM ("kp-end");
+	  case 0xFF9D: return KEYSYM ("kp-begin");
+	  case 0xFF9E: return KEYSYM ("kp-insert");
+	  case 0xFF9F: return KEYSYM ("kp-delete");
+
+	  case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */
+	  case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */
+	  default:
+	    {
+	      Ascbyte buf[64];
+	      sprintf (buf, "unknown-keysym-0x%X", (int) keysym);
+	      return KEYSYM (buf);
+	    }
+	  }
+      /* If it's got a one-character name, that's good enough. */
+      if (!* (name + itext_ichar_len (name)))
+	return make_char (itext_ichar (name));
+
+      /* If it's in the "Keyboard" character set, downcase it.
+	 The case of those keysyms is too totally random for us to
+	 force anyone to remember them.
+	 The case of the other character sets is significant, however.
+	 */
+      if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00))
+	{
+	  Ibyte *buf, *s1;
+
+	  IBYTE_STRING_TO_ALLOCA (name, buf);
+	  for (s1 = buf; *s1; s1++)
+	    if (*s1 == '_')
+	      *s1 = '-';
+	  return LISP_STRING_TO_KEYSYM (Fdowncase (build_intstring (buf),
+						   Qnil));
+	}
+      return KEYSYM ((CIbyte *) name);
+    }
+}
+
+static void
+xlike_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers)
+{
+  KeySym upper_lower[2];
+  int j;
+
+  if (keysym < 0x80) /* Optimize for ASCII keysyms */
+    return;
+
+  /* If you execute:
+     xmodmap -e 'keysym NN = scaron'
+     and then press (Shift scaron), X11 will return the different
+     keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
+     So we "register" both `scaron' and `Scaron'. */
+#ifdef HAVE_XCONVERTCASE
+  XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
+#else
+  upper_lower[0] = upper_lower[1] = keysym;
+#endif
+
+  for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
+    {
+      Extbyte *name = XKeysymToString (keysym);
+      keysym = upper_lower[j];
+
+      if (name)
+	{
+	  /* X guarantees NAME to be in the Host Portable Character Encoding */
+	  Lisp_Object sym = xlike_keysym_to_emacs_keysym (keysym, 0);
+	  Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
+	  Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
+
+	  if (! EQ (old_value, new_value)
+	      && ! (EQ (old_value, Qsans_modifiers) &&
+		    EQ (new_value, Qt)))
+	    {
+	      maybe_define_x_key_as_self_inserting_character (keysym, sym);
+	      Fputhash (build_ext_string (name, Qx_keysym_encoding), new_value,
+			hash_table);
+	      Fputhash (sym, new_value, hash_table);
+	    }
+	}
+    }
+}
+
+void
+xlike_reset_key_mapping (struct device *d, struct xlike_event_key_data *xd)
+{
+  KeySym *keysym, *keysym_end;
+  Lisp_Object hash_table;
+  int key_code_count, keysyms_per_code;
+  Display *display = xlike_device_to_display (d);
+
+  if (xd->x_keysym_map)
+    XFree ((char *) xd->x_keysym_map);
+  XDisplayKeycodes (display,
+		    &xd->x_keysym_map_min_code,
+		    &xd->x_keysym_map_max_code);
+  key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
+  xd->x_keysym_map =
+    (KeySym *)
+    XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count,
+			 &xd->x_keysym_map_keysyms_per_code);
+
+  hash_table = xd->x_keysym_map_hash_table;
+  if (HASH_TABLEP (hash_table))
+    Fclrhash (hash_table);
+  else
+    xd->x_keysym_map_hash_table = hash_table =
+      make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
+
+  for (keysym = xd->x_keysym_map,
+	 keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
+	 keysym_end = keysym + (key_code_count * keysyms_per_code);
+       keysym < keysym_end;
+       keysym += keysyms_per_code)
+    {
+      int j;
+      if (keysym[0] == NoSymbol)
+	continue;
+
+      xlike_has_keysym (keysym[0], hash_table, 0);
+
+      for (j = 1; j < keysyms_per_code; j++)
+	{
+	  if (keysym[j] != keysym[0] &&
+	      keysym[j] != NoSymbol)
+	    xlike_has_keysym (keysym[j], hash_table, 1);
+	}
+    }
+}
+
+static const char *
+index_to_name (int indice)
+{
+  switch (indice)
+    {
+    case ShiftMapIndex:   return "ModShift";
+    case LockMapIndex:    return "ModLock";
+    case ControlMapIndex: return "ModControl";
+    case Mod1MapIndex:    return "Mod1";
+    case Mod2MapIndex:    return "Mod2";
+    case Mod3MapIndex:    return "Mod3";
+    case Mod4MapIndex:    return "Mod4";
+    case Mod5MapIndex:    return "Mod5";
+    default:              return "???";
+    }
+}
+
+/* Boy, I really wish C had local functions... */
+struct c_doesnt_have_closures   /* #### not yet used */
+{
+  int warned_about_overlapping_modifiers;
+  int warned_about_predefined_modifiers;
+  int warned_about_duplicate_modifiers;
+  int meta_bit;
+  int hyper_bit;
+  int super_bit;
+  int alt_bit;
+  int mode_bit;
+};
+
+void
+xlike_reset_modifier_mapping (struct device *d,
+			      struct xlike_event_key_data *xd)
+{
+  int modifier_index, modifier_key, column, mkpm;
+  int warned_about_overlapping_modifiers = 0;
+  int warned_about_predefined_modifiers  = 0;
+  int warned_about_duplicate_modifiers   = 0;
+  int meta_bit  = 0;
+  int hyper_bit = 0;
+  int super_bit = 0;
+  int alt_bit   = 0;
+  int mode_bit  = 0;
+  Display *display = xlike_device_to_display (d);
+
+  xd->lock_interpretation = 0;
+
+  if (xd->x_modifier_keymap)
+    XFreeModifiermap (xd->x_modifier_keymap);
+
+  xlike_reset_key_mapping (d, xd);
+
+  xd->x_modifier_keymap = (XModifierKeymap *) XGetModifierMapping (display);
+
+  /* Boy, I really wish C had local functions...
+   */
+
+  /* The call to warn_when_safe must be on the same line as the string or
+     make-msgfile won't pick it up properly (the newline doesn't confuse
+     it, but the backslash does). */
+
+#define modwarn(name,old,other)						\
+  warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is generated by %s.",	\
+		  name, code, index_to_name (old), other),		\
+  warned_about_overlapping_modifiers = 1
+
+#define modbarf(name,other)						    \
+  warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
+		  name, code, other),					    \
+  warned_about_predefined_modifiers = 1
+
+#define check_modifier(name,mask)					      \
+  if ((1<<modifier_index) != mask)					      \
+    warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
+		    name, code, index_to_name (modifier_index)),	      \
+    warned_about_predefined_modifiers = 1
+
+#define store_modifier(name,old)					   \
+  if (old && old != modifier_index)					   \
+    warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates both %s and %s, which is nonsensical.",\
+		    name, code, index_to_name (old),			   \
+		    index_to_name (modifier_index)),			   \
+    warned_about_duplicate_modifiers = 1;				   \
+  if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift");	   \
+  else if (modifier_index == LockMapIndex) modbarf (name,"ModLock");	   \
+  else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
+  else if (sym == XK_Mode_switch)					   \
+    mode_bit = modifier_index; /* Mode_switch is special, see below... */  \
+  else if (modifier_index == meta_bit && old != meta_bit)		   \
+    modwarn (name, meta_bit, "Meta");					   \
+  else if (modifier_index == super_bit && old != super_bit)		   \
+    modwarn (name, super_bit, "Super");					   \
+  else if (modifier_index == hyper_bit && old != hyper_bit)		   \
+    modwarn (name, hyper_bit, "Hyper");					   \
+  else if (modifier_index == alt_bit && old != alt_bit)			   \
+    modwarn (name, alt_bit, "Alt");					   \
+  else									   \
+    old = modifier_index;
+
+  mkpm = (xd->x_modifier_keymap)->max_keypermod;
+  for (modifier_index = 0; modifier_index < 8; modifier_index++)
+    for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
+      KeySym last_sym = 0;
+      for (column = 0; column < 4; column += 2) {
+	KeyCode code =
+	  (xd->x_modifier_keymap)
+	  ->modifiermap[modifier_index * mkpm + modifier_key];
+	KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
+	if (sym == last_sym) continue;
+	last_sym = sym;
+	switch (sym) {
+	case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
+	case XK_Meta_L:     store_modifier ("Meta_L", meta_bit); break;
+	case XK_Meta_R:     store_modifier ("Meta_R", meta_bit); break;
+	case XK_Super_L:    store_modifier ("Super_L", super_bit); break;
+	case XK_Super_R:    store_modifier ("Super_R", super_bit); break;
+	case XK_Hyper_L:    store_modifier ("Hyper_L", hyper_bit); break;
+	case XK_Hyper_R:    store_modifier ("Hyper_R", hyper_bit); break;
+	case XK_Alt_L:      store_modifier ("Alt_L", alt_bit); break;
+	case XK_Alt_R:      store_modifier ("Alt_R", alt_bit); break;
+	case XK_Control_L:  check_modifier ("Control_L", ControlMask); break;
+	case XK_Control_R:  check_modifier ("Control_R", ControlMask); break;
+	case XK_Shift_L:    check_modifier ("Shift_L", ShiftMask); break;
+	case XK_Shift_R:    check_modifier ("Shift_R", ShiftMask); break;
+	case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask);
+	  xd->lock_interpretation = XK_Shift_Lock; break;
+	case XK_Caps_Lock:  check_modifier ("Caps_Lock", LockMask);
+	  xd->lock_interpretation = XK_Caps_Lock; break;
+
+	/* It probably doesn't make any sense for a modifier bit to be
+	   assigned to a key that is not one of the above, but OpenWindows
+	   assigns modifier bits to a couple of random function keys for
+	   no reason that I can discern, so printing a warning here would
+	   be annoying. */
+	}
+      }
+    }
+#undef store_modifier
+#undef check_modifier
+#undef modwarn
+#undef modbarf
+
+  /* If there was no Meta key, then try using the Alt key instead.
+     If there is both a Meta key and an Alt key, then the Alt key
+     is not disturbed and remains an Alt key. */
+  if (! meta_bit && alt_bit)
+    meta_bit = alt_bit, alt_bit = 0;
+
+  /* mode_bit overrides everything, since it's processed down inside of
+     XLookupString() instead of by us.  If Meta and Mode_switch both
+     generate the same modifier bit (which is an error), then we don't
+     interpret that bit as Meta, because we can't make XLookupString()
+     not interpret it as Mode_switch; and interpreting it as both would
+     be totally wrong. */
+  if (mode_bit)
+    {
+      const char *warn = 0;
+      if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
+      else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
+      else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
+      else if (mode_bit == alt_bit)   warn = "Alt",   alt_bit   = 0;
+      if (warn)
+	{
+	  warn_when_safe
+	    (Qkey_mapping, Qwarning,
+	     "XEmacs:  %s is being used for both Mode_switch and %s.",
+	     index_to_name (mode_bit), warn),
+	    warned_about_overlapping_modifiers = 1;
+	}
+    }
+#undef index_to_name
+
+  xd->MetaMask   = (meta_bit   ? (1 << meta_bit)  : 0);
+  xd->HyperMask  = (hyper_bit  ? (1 << hyper_bit) : 0);
+  xd->SuperMask  = (super_bit  ? (1 << super_bit) : 0);
+  xd->AltMask    = (alt_bit    ? (1 << alt_bit)   : 0);
+  xd->ModeMask   = (mode_bit   ? (1 << mode_bit)  : 0); /* unused */
+
+  if (warned_about_overlapping_modifiers)
+    warn_when_safe (Qkey_mapping, Qwarning, "\n"
+"	Two distinct modifier keys (such as Meta and Hyper) cannot generate\n"
+"	the same modifier bit, because Emacs won't be able to tell which\n"
+"	modifier was actually held down when some other key is pressed.  It\n"
+"	won't be able to tell Meta-x and Hyper-x apart, for example.  Change\n"
+"	one of these keys to use some other modifier bit.  If you intend for\n"
+"	these keys to have the same behavior, then change them to have the\n"
+"	same keysym as well as the same modifier bit.");
+
+  if (warned_about_predefined_modifiers)
+    warn_when_safe (Qkey_mapping, Qwarning, "\n"
+"	The semantics of the modifier bits ModShift, ModLock, and ModControl\n"
+"	are predefined.  It does not make sense to assign ModControl to any\n"
+"	keysym other than Control_L or Control_R, or to assign any modifier\n"
+"	bits to the \"control\" keysyms other than ModControl.  You can't\n"
+"	turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n"
+"	assigning the key a different modifier bit.  You must also make that\n"
+"	key generate an appropriate keysym (Control_L, Meta_L, etc).");
+
+  /* No need to say anything more for warned_about_duplicate_modifiers. */
+
+  if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
+    warn_when_safe (Qkey_mapping, Qwarning, "\n"
+"	The meanings of the modifier bits Mod1 through Mod5 are determined\n"
+"	by the keysyms used to control those bits.  Mod1 does NOT always\n"
+"	mean Meta, although some non-ICCCM-compliant programs assume that.");
+}
+
+void
+xlike_init_modifier_mapping (struct device *d, struct xlike_event_key_data *xd)
+{
+  xd->x_keysym_map_hash_table = Qnil;
+  xd->x_keysym_map = NULL;
+  xd->x_modifier_keymap = NULL;
+  xlike_reset_modifier_mapping (d, xd);
+}
+
+void
+free_xlike_event_key_data (struct xlike_event_key_data *xd)
+{
+  if (xd->x_modifier_keymap)
+    XFreeModifiermap (xd->x_modifier_keymap);
+  if (xd->x_keysym_map)
+    XFree ((char *) xd->x_keysym_map);
+}
+
+void
+syms_of_event_xlike (void)
+{
+  DEFSYMBOL (Qkey_mapping);
+  DEFSYMBOL (Qsans_modifiers);
+}
--- a/src/gccache-gtk.h	Mon Feb 14 22:51:46 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/* Efficient caching of X GCs (graphics contexts).
-   Copyright (C) 1993 Free Software Foundation, Inc.
-
-
-This file is part of XEmacs.
-
-XEmacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-XEmacs is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* Synched up with: Not in FSF. */
-
-/* Written by jwz, 14 jun 93 */
-/* Hacked by wmperry, apr 2000 */
-
-#ifndef _GCCACHE_GTK_H_
-#define _GCCACHE_GTK_H_
-
-struct gc_cache;
-struct gc_cache *make_gc_cache (GtkWidget *);
-void free_gc_cache (struct gc_cache *cache);
-GdkGC *gc_cache_lookup (struct gc_cache *, GdkGCValues *, unsigned long mask);
-
-#endif /* _XGCCACHE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gccache-x.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,26 @@
+/* Efficient caching of GCs (graphics contexts) -- shared code, X and GTK.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
+   Copyright (C) 2003 Ben Wing.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+#define THIS_IS_X
+#include "gccache-xlike-inc.c"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gccache-xlike-inc.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,395 @@
+/* Efficient caching of GCs (graphics contexts) -- shared code, X and GTK.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
+   Copyright (C) 2003, 2005 Ben Wing.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+/* Emacs uses a lot of different display attributes; for example, assume
+   that only four fonts are in use (normal, bold, italic, and bold-italic).
+   Then assume that one stipple or background is used for text selections,
+   and another is used for highlighting mousable regions.  That makes 16
+   GCs already.  Add in the fact that another GC may be needed to display
+   the text cursor in any of those regions, and you've got 32.  Add in
+   more fonts, and it keeps increasing exponentially.
+
+   We used to keep these GCs in a cache of merged (fully qualified) faces.
+   However, a lot of other code in xterm.c used XChangeGC of existing GCs,
+   which is kind of slow and kind of random.  Also, managing the face cache
+   was tricky because it was hard to know when a face was no longer visible
+   on the frame -- we had to mark all frames as garbaged whenever a face
+   was changed, which caused an unpleasant amount of flicker (since faces are
+   created/destroyed (= changed) whenever a frame is created/destroyed.
+
+   So this code maintains a cache at the GC level instead of at the face
+   level.  There is an upper limit on the size of the cache, after which we
+   will stop creating GCs and start reusing them (reusing the least-recently-
+   used ones first).  So if faces get changed, their GCs will eventually be
+   recycled.  Also more sharing of GCs is possible.
+
+   This code uses hash tables.  It could be that, if the cache size is small
+   enough, a linear search might be faster; but I doubt it, since we need
+   `equal' comparisons, not `eq', and I expect that the optimal cache size
+   will be ~100.
+
+   Written by jwz, 14 jun 93
+   Hacked by William Perry, apr 2000 for GTK and introduced code
+   duplication (a no-no)
+   Undid code duplication, Ben Wing, Jan 28, 2003.
+ */
+
+#include <config.h>
+#include "lisp.h"
+#include "hash.h"
+
+#ifndef THIS_IS_GTK
+#include <X11/Xlib.h>
+#else /* THIS_IS_GTK */
+#include <gtk/gtk.h>
+#endif /* THIS_IS_GTK */
+
+#define GC_CACHE_SIZE 100
+
+#define GCCACHE_HASH
+
+#ifndef THIS_IS_GTK
+#define ZZGCVALUES XGCValues
+#define ZZGC GC
+#define ZZ(z) x_##z
+#else
+#define ZZGCVALUES GdkGCValues
+#define ZZGC GdkGC *
+#define ZZ(z) gtk_##z
+#endif
+
+struct gcv_and_mask {
+  ZZGCVALUES gcv;
+  unsigned long mask;
+};
+
+struct gc_cache_cell {
+  ZZGC gc;
+  struct gcv_and_mask gcvm;
+  struct gc_cache_cell *prev, *next;
+};
+
+struct gc_cache {
+#ifndef THIS_IS_GTK
+  Display *dpy;		/* used only as arg to XCreateGC/XFreeGC */
+  Window window;	/* used only as arg to XCreateGC */
+#else /* THIS_IS_GTK */
+  GdkWindow *window;	/* used only as arg to XCreateGC */
+#endif /* THIS_IS_GTK */
+  int size;
+  struct gc_cache_cell *head;
+  struct gc_cache_cell *tail;
+#ifdef GCCACHE_HASH
+  struct hash_table *table;
+#endif
+
+  int create_count;
+  int delete_count;
+};
+
+#ifdef GCCACHE_HASH
+static Hashcode
+gc_cache_hash (const void *arg)
+{
+  const struct gcv_and_mask *gcvm = (const struct gcv_and_mask *) arg;
+  unsigned long *longs = (unsigned long *) &gcvm->gcv;
+  Hashcode hash = gcvm->mask;
+  int i;
+  /* This could look at the mask and only use the used slots in the
+     hash code.  That would win in that we wouldn't have to initialize
+     every slot of the gcv when calling gc_cache_lookup.  But we need
+     the hash function to be as fast as possible; some timings should
+     be done. */
+  for (i = 0; i < (int) (sizeof (ZZGCVALUES) /
+			 sizeof (unsigned long)); i++)
+    hash = (hash << 1) ^ *longs++;
+  return hash;
+}
+
+#endif /* GCCACHE_HASH */
+
+static int
+gc_cache_eql (const void *arg1, const void *arg2)
+{
+  /* See comment in gc_cache_hash */
+#ifndef THIS_IS_GTK
+  return !memcmp (arg1, arg2, sizeof (struct gcv_and_mask));
+#else /* THIS_IS_GTK */
+  const struct gcv_and_mask *gcvm1 = (const struct gcv_and_mask *) arg1;
+  const struct gcv_and_mask *gcvm2 = (const struct gcv_and_mask *) arg2;
+
+  return !memcmp (&gcvm1->gcv, &gcvm2->gcv, sizeof (gcvm1->gcv))
+    && gcvm1->mask == gcvm2->mask;
+#endif /* THIS_IS_GTK */
+}
+
+struct gc_cache *
+#ifndef THIS_IS_GTK
+ZZ (make_gc_cache) (Display *dpy, Window window)
+#else /* THIS_IS_GTK */
+ZZ (make_gc_cache) (GtkWidget *widget)
+#endif /* THIS_IS_GTK */
+{
+  struct gc_cache *cache = xnew (struct gc_cache);
+#ifndef THIS_IS_GTK
+  cache->dpy = dpy;
+  cache->window = window;
+#else /* THIS_IS_GTK */
+  cache->window = widget->window;
+#endif /* THIS_IS_GTK */
+  cache->size = 0;
+  cache->head = cache->tail = 0;
+  cache->create_count = cache->delete_count = 0;
+#ifdef GCCACHE_HASH
+  cache->table =
+    make_general_hash_table (GC_CACHE_SIZE, gc_cache_hash, gc_cache_eql);
+#endif
+  return cache;
+}
+
+void
+ZZ (free_gc_cache) (struct gc_cache *cache)
+{
+  struct gc_cache_cell *rest, *next;
+  rest = cache->head;
+  while (rest)
+    {
+#ifndef THIS_IS_GTK
+      XFreeGC (cache->dpy, rest->gc);
+#else /* THIS_IS_GTK */
+      gdk_gc_destroy (rest->gc);
+#endif /* THIS_IS_GTK */
+      next = rest->next;
+      xfree (rest, struct gc_cache_cell *);
+      rest = next;
+    }
+#ifdef GCCACHE_HASH
+  free_hash_table (cache->table);
+#endif
+  xfree (cache, struct gc_cache *);
+}
+
+ZZGC
+ZZ (gc_cache_lookup) (struct gc_cache *cache, ZZGCVALUES *gcv, unsigned long mask)
+{
+  struct gc_cache_cell *cell, *next, *prev;
+  struct gcv_and_mask gcvm;
+
+  if ((!!cache->head) != (!!cache->tail)) ABORT ();
+  if (cache->head && (cache->head->prev || cache->tail->next)) ABORT ();
+
+#ifdef THIS_IS_GTK
+  /* Gdk does not have the equivalent of 'None' for the clip_mask, so
+     we need to check it carefully, or gdk_gc_new_with_values will
+     coredump */
+  if ((mask & GDK_GC_CLIP_MASK) && !gcv->clip_mask)
+    mask = (GdkGCValuesMask) (mask & ~GDK_GC_CLIP_MASK);
+#endif /* THIS_IS_GTK */
+
+  gcvm.mask = mask;
+  gcvm.gcv = *gcv;	/* this copies... */
+
+#ifdef GCCACHE_HASH
+
+  if (gethash (&gcvm, cache->table, (const void **) &cell))
+
+#else /* !GCCACHE_HASH */
+
+  cell = cache->tail;	/* start at the end (most recently used) */
+  while (cell)
+    {
+      if (gc_cache_eql (&gcvm, &cell->gcvm))
+	break;
+      else
+	cell = cell->prev;
+    }
+
+  /* #### This whole file needs some serious overhauling. */
+#ifndef THIS_IS_GTK
+  if (!(mask | GCTile) && cell->gc->values.tile)
+#else /* THIS_IS_GTK */
+  if (!(mask | GDK_GC_TILE) && cell->gcvm.gcv.tile)
+#endif /* THIS_IS_GTK */
+    cell = 0;
+#ifndef THIS_IS_GTK
+  else if (!(mask | GCStipple) && cell->gc->values.stipple)
+#else /* THIS_IS_GTK */
+  else if (!(mask | GDK_GC_STIPPLE) && cell->gcvm.gcv.stipple)
+#endif /* THIS_IS_GTK */
+    cell = 0;
+
+  if (cell)
+
+#endif /* !GCCACHE_HASH */
+
+    {
+      /* Found a cell.  Move this cell to the end of the list, so that it
+	 will be less likely to be collected than a cell that was accessed
+	 less recently.
+       */
+      if (cell == cache->tail)
+	return cell->gc;
+
+      next = cell->next;
+      prev = cell->prev;
+      if (prev) prev->next = next;
+      if (next) next->prev = prev;
+      if (cache->head == cell) cache->head = next;
+      cell->next = 0;
+      cell->prev = cache->tail;
+      cache->tail->next = cell;
+      cache->tail = cell;
+      if (cache->head == cell) ABORT ();
+      if (cell->next) ABORT ();
+      if (cache->head->prev) ABORT ();
+      if (cache->tail->next) ABORT ();
+      return cell->gc;
+    }
+
+  /* else, cache miss. */
+
+  if (cache->size == GC_CACHE_SIZE)
+    /* Reuse the first cell on the list (least-recently-used).
+       Remove it from the list, and unhash it from the table.
+     */
+    {
+      cell = cache->head;
+      cache->head = cell->next;
+      cache->head->prev = 0;
+      if (cache->tail == cell) cache->tail = 0; /* only one */
+#ifndef THIS_IS_GTK
+      XFreeGC (cache->dpy, cell->gc);
+#else /* THIS_IS_GTK */
+      gdk_gc_destroy (cell->gc);
+#endif /* THIS_IS_GTK */
+      cache->delete_count++;
+#ifdef GCCACHE_HASH
+      remhash (&cell->gcvm, cache->table);
+#endif
+    }
+  else if (cache->size > GC_CACHE_SIZE)
+    ABORT ();
+  else
+    {
+      /* Allocate a new cell (don't put it in the list or table yet). */
+      cell = xnew (struct gc_cache_cell);
+      cache->size++;
+    }
+
+  /* Now we've got a cell (new or reused).  Fill it in. */
+  memcpy (&cell->gcvm.gcv, gcv, sizeof (ZZGCVALUES));
+  cell->gcvm.mask = mask;
+
+  /* Put the cell on the end of the list. */
+  cell->next = 0;
+  cell->prev = cache->tail;
+  if (cache->tail) cache->tail->next = cell;
+  cache->tail = cell;
+  if (! cache->head) cache->head = cell;
+
+  cache->create_count++;
+#ifdef GCCACHE_HASH
+  /* Hash it in the table */
+  puthash (&cell->gcvm, cell, cache->table);
+#endif
+
+  /* Now make and return the GC. */
+#ifndef THIS_IS_GTK
+  cell->gc = XCreateGC (cache->dpy, cache->window, mask, gcv);
+#else /* THIS_IS_GTK */
+  cell->gc = gdk_gc_new_with_values (cache->window, gcv, (GdkGCValuesMask) mask);
+#endif /* THIS_IS_GTK */
+
+  /* debug */
+  assert (cell->gc == ZZ (gc_cache_lookup) (cache, gcv, mask));
+
+  return cell->gc;
+}
+#ifndef THIS_IS_GTK
+
+
+#ifdef DEBUG_XEMACS
+
+void x_describe_gc_cache (struct gc_cache *cache);
+void
+x_describe_gc_cache (struct gc_cache *cache)
+{
+  int count = 0;
+  struct gc_cache_cell *cell = cache->head;
+  stderr_out ("\nsize:    %d", cache->size);
+  stderr_out ("\ncreated: %d", cache->create_count);
+  stderr_out ("\ndeleted: %d", cache->delete_count);
+  while (cell)
+  {
+    struct gc_cache_cell *cell2;
+    int i = 0;
+    stderr_out ("\n%d:\t0x%lx  GC: 0x%08lx  hash: 0x%08lx\n",
+	     count, (long) cell, (long) cell->gc, gc_cache_hash (&cell->gcvm));
+    for (cell2 = cache->head; cell2; cell2 = cell2->next, i++)
+      if (count != i &&
+	  gc_cache_hash (&cell->gcvm) == gc_cache_hash (&cell2->gcvm))
+	stderr_out ("\tHASH COLLISION with cell %d\n", i);
+    stderr_out ("\tmask:       %8lx\n", cell->gcvm.mask);
+
+#define FROB(field) do {						\
+  if ((int)cell->gcvm.gcv.field != (~0))				\
+    stderr_out ("\t%-12s%8x\n", #field ":", (int)cell->gcvm.gcv.field);	\
+} while (0)
+    FROB (function);
+    FROB (plane_mask);
+    FROB (foreground);
+    FROB (background);
+    FROB (line_width);
+    FROB (line_style);
+    FROB (cap_style);
+    FROB (join_style);
+    FROB (fill_style);
+    FROB (fill_rule);
+    FROB (arc_mode);
+    FROB (tile);
+    FROB (stipple);
+    FROB (ts_x_origin);
+    FROB (ts_y_origin);
+    FROB (font);
+    FROB (subwindow_mode);
+    FROB (graphics_exposures);
+    FROB (clip_x_origin);
+    FROB (clip_y_origin);
+    FROB (clip_mask);
+    FROB (dash_offset);
+#undef FROB
+
+    count++;
+    if (cell->next && cell == cache->tail)
+      stderr_out ("\nERROR!  tail is here!\n\n");
+    else if (!cell->next && cell != cache->tail)
+      stderr_out ("\nERROR!  tail is not at the end\n\n");
+    cell = cell->next;
+  }
+  if (count != cache->size)
+    stderr_out ("\nERROR!  count should be %d\n\n", cache->size);
+}
+
+#endif /* DEBUG_XEMACS */
+#endif /* ! THIS_IS_GTK */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/intl-gtk.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,54 @@
+/* GTK internationalization functions.
+   Copyright (C) 2003 Ben Wing.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+/* Authorship:
+
+   Current primary author: Ben Wing <ben@xemacs.org>
+   */
+
+#include <config.h>
+#include "lisp.h"
+
+#include "console-gtk.h"
+
+/* As best as I can determine from reading the source code, all GTK strings
+   (gchar *) are UTF-8 in GTK V2, but locale-encoded in GTK V1.2.  #### As
+   usual, the documentation on this is completely nonexistent.  There may
+   well be different encodings for particular kinds of data, e.g. selection
+   data, drag-n-drop data, etc. --ben */
+
+Lisp_Object Vgtk_text_encoding;
+
+void
+vars_of_intl_gtk (void)
+{
+  staticpro (&Vgtk_text_encoding);
+}
+
+void
+init_intl_gtk (void)
+{
+  if (gtk_major_version >= 2)
+    Vgtk_text_encoding = Qutf_8;
+  else
+    Vgtk_text_encoding = Qnative;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/objects-xlike-inc.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,613 @@
+/* Include file for common code, X and GTK colors and fonts.
+   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1995 Board of Trustees, University of Illinois.
+   Copyright (C) 1995 Tinker Systems.
+   Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2004, 2005 Ben Wing.
+   Copyright (C) 1995 Sun Microsystems, Inc.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* Synched up with: Not in FSF. */
+
+/* Authors: Jamie Zawinski, Chuck Thompson, Ben Wing */
+
+/* Extracted from objects-x.c, objects-gtk.c 2-13-05.
+   NOTE: There is an advantage to having the code coalesced this way
+   even when there is a fair amount of difference between the two versions,
+   provided that they are still parallel -- having them side by side ensures
+   that logic changes in one are propagated to the other, preventing bit-rot
+   --ben
+*/
+
+#ifndef THIS_IS_GTK
+#define ZZCOLOR_TYPE XColor
+#define ZZCOLOR_INSTANCE(name) COLOR_INSTANCE_X_##name
+#define ZZ(z) x_##z
+#define ZZEND(z) z##_x
+#define ZZCONSOLE_HAS_METHOD(name) CONSOLE_HAS_METHOD (x, name)
+#define UNUSED_IF_GTK(arg) arg
+#else
+#define ZZCOLOR_TYPE GdkColor
+#define ZZCOLOR_INSTANCE(name) COLOR_INSTANCE_GTK_##name
+#define ZZ(z) gtk_##z
+#define ZZEND(z) z##_gtk
+#define ZZCONSOLE_HAS_METHOD(name) CONSOLE_HAS_METHOD (gtk, name)
+#define UNUSED_IF_GTK(arg) UNUSED (arg)
+#endif
+
+
+/************************************************************************/
+/*                          color instances                             */
+/************************************************************************/
+
+static int
+ZZ (parse_nearest_color) (struct device *d, ZZCOLOR_TYPE *color,
+			  Lisp_Object name, Error_Behavior errb)
+{
+#ifndef THIS_IS_GTK
+  Display *dpy   = DEVICE_X_DISPLAY  (d);
+  Colormap cmap  = DEVICE_X_COLORMAP (d);
+  Visual *visual = DEVICE_X_VISUAL   (d);
+#else /* THIS_IS_GTK */
+  GdkColormap *cmap = DEVICE_GTK_COLORMAP (d);
+  GdkVisual *visual = DEVICE_GTK_VISUAL (d);
+#endif /* THIS_IS_GTK */
+  int result;
+
+  xzero (*color);
+
+#ifndef THIS_IS_GTK
+    result =
+      XParseColor (dpy, cmap,
+		   NEW_LISP_STRING_TO_EXTERNAL (name, Qx_color_name_encoding),
+		   color);
+#else /* THIS_IS_GTK */
+  result = gdk_color_parse (LISP_STRING_TO_GTK_TEXT (name), color);
+#endif /* THIS_IS_GTK */
+  if (!result)
+    {
+      maybe_signal_error (Qgui_error, "Unrecognized color",
+			  name, Qcolor, errb);
+      return 0;
+    }
+#ifndef THIS_IS_GTK
+  result = ZZ (allocate_nearest_color) (dpy, cmap, visual, color);
+#else /* THIS_IS_GTK */
+  result = ZZ (allocate_nearest_color) (cmap, visual, color);
+#endif /* THIS_IS_GTK */
+  if (!result)
+    {
+      maybe_signal_error (Qgui_error, "Couldn't allocate color",
+			  name, Qcolor, errb);
+      return 0;
+    }
+
+  return result;
+}
+
+static int
+ZZ (initialize_color_instance) (Lisp_Color_Instance *c, Lisp_Object name,
+				Lisp_Object device, Error_Behavior errb)
+{
+  ZZCOLOR_TYPE color;
+  int result;
+
+  result = ZZ (parse_nearest_color) (XDEVICE (device), &color, name, errb);
+
+  if (!result)
+    return 0;
+
+  /* Don't allocate the data until we're sure that we will succeed,
+     or the finalize method may get fucked. */
+  c->data = xnew (struct ZZ (color_instance_data));
+  if (result == 3)
+    ZZCOLOR_INSTANCE (DEALLOC) (c) = 0;
+  else
+    ZZCOLOR_INSTANCE (DEALLOC) (c) = 1;
+#ifndef THIS_IS_GTK
+  ZZCOLOR_INSTANCE (COLOR) (c) = color;
+#else /* THIS_IS_GTK */
+  ZZCOLOR_INSTANCE (COLOR) (c) = gdk_color_copy (&color);
+#endif /* THIS_IS_GTK */
+  return 1;
+}
+
+static void
+ZZ (print_color_instance) (Lisp_Color_Instance *c,
+			   Lisp_Object printcharfun,
+			   int UNUSED (escapeflag))
+{
+#ifndef THIS_IS_GTK
+  XColor color = COLOR_INSTANCE_X_COLOR (c);
+  write_fmt_string (printcharfun, " %ld=(%X,%X,%X)",
+		    color.pixel, color.red, color.green, color.blue);
+#else /* THIS_IS_GTK */
+  GdkColor *color = COLOR_INSTANCE_GTK_COLOR (c);
+  write_fmt_string (printcharfun, " %ld=(%X,%X,%X)",
+		    color->pixel, color->red, color->green, color->blue);
+#endif /* THIS_IS_GTK */
+}
+
+static void
+ZZ (finalize_color_instance) (Lisp_Color_Instance *c)
+{
+  if (c->data)
+    {
+      if (DEVICE_LIVE_P (XDEVICE (c->device)))
+	{
+	  if (ZZCOLOR_INSTANCE (DEALLOC) (c))
+	    {
+#ifndef THIS_IS_GTK
+	      XFreeColors (DEVICE_X_DISPLAY (XDEVICE (c->device)),
+			   DEVICE_X_COLORMAP (XDEVICE (c->device)),
+			   &COLOR_INSTANCE_X_COLOR (c).pixel, 1, 0);
+#else /* THIS_IS_GTK */
+	      gdk_colormap_free_colors (DEVICE_GTK_COLORMAP
+					(XDEVICE (c->device)),
+					COLOR_INSTANCE_GTK_COLOR (c), 1);
+#endif /* THIS_IS_GTK */
+	    }
+#ifdef THIS_IS_GTK
+	  gdk_color_free (COLOR_INSTANCE_GTK_COLOR (c));
+#endif /* THIS_IS_GTK */
+	}
+      xfree (c->data, void *);
+      c->data = 0;
+    }
+}
+
+/* Color instances are equal if they resolve to the same color on the
+   screen (have the same RGB values).  I imagine that
+   "same RGB values" == "same cell in the colormap."  Arguably we should
+   be comparing their names or pixel values instead. */
+
+static int
+ZZ (color_instance_equal) (Lisp_Color_Instance *c1,
+			   Lisp_Color_Instance *c2,
+			   int UNUSED (depth))
+{
+#ifndef THIS_IS_GTK
+  XColor color1 = COLOR_INSTANCE_X_COLOR (c1);
+  XColor color2 = COLOR_INSTANCE_X_COLOR (c2);
+  return ((color1.red == color2.red) &&
+	  (color1.green == color2.green) &&
+	  (color1.blue == color2.blue));
+#else /* THIS_IS_GTK */
+  return (gdk_color_equal (COLOR_INSTANCE_GTK_COLOR (c1),
+			   COLOR_INSTANCE_GTK_COLOR (c2)));
+#endif /* THIS_IS_GTK */
+}
+
+static Hashcode
+ZZ (color_instance_hash) (Lisp_Color_Instance *c, int UNUSED (depth))
+{
+#ifndef THIS_IS_GTK
+  XColor color = COLOR_INSTANCE_X_COLOR (c);
+  return HASH3 (color.red, color.green, color.blue);
+#else /* THIS_IS_GTK */
+  return (gdk_color_hash (COLOR_INSTANCE_GTK_COLOR (c), NULL));
+#endif /* THIS_IS_GTK */
+}
+
+static Lisp_Object
+ZZ (color_instance_rgb_components) (Lisp_Color_Instance *c)
+{
+#ifndef THIS_IS_GTK
+  XColor color = COLOR_INSTANCE_X_COLOR (c);
+  return (list3 (make_int (color.red),
+		 make_int (color.green),
+		 make_int (color.blue)));
+#else /* THIS_IS_GTK */
+  GdkColor *color = COLOR_INSTANCE_GTK_COLOR (c);
+  return (list3 (make_int (color->red),
+		 make_int (color->green),
+		 make_int (color->blue)));
+#endif /* THIS_IS_GTK */
+}
+
+static int
+ZZ (valid_color_name_p) (struct device *UNUSED_IF_GTK (d), Lisp_Object color)
+{
+#ifndef THIS_IS_GTK
+  XColor c;
+  Display *dpy = DEVICE_X_DISPLAY (d);
+  Colormap cmap = DEVICE_X_COLORMAP (d);
+  const Extbyte *extname;
+
+  LISP_STRING_TO_EXTERNAL (color, extname, Qx_color_name_encoding);
+
+  return XParseColor (dpy, cmap, extname, &c);
+#else /* THIS_IS_GTK */
+  GdkColor c;
+  const Extbyte *extname;
+
+  LISP_STRING_TO_EXTERNAL (color, extname, Vgtk_text_encoding);
+
+  if (gdk_color_parse (extname, &c) != TRUE)
+      return 0;
+  return 1;
+#endif /* THIS_IS_GTK */
+}
+
+static Lisp_Object
+ZZ (color_list) (void)
+{
+#ifdef THIS_IS_GTK
+  /* #### BILL!!!
+     Is this correct? */
+#endif /* THIS_IS_GTK */
+  return call0 (intern ("x-color-list-internal"));
+}
+
+
+/************************************************************************/
+/*                           font instances                             */
+/************************************************************************/
+
+static int
+ZZ (initialize_font_instance) (Lisp_Font_Instance *f,
+			       Lisp_Object UNUSED (name),
+			       Lisp_Object UNUSED_IF_GTK (device),
+			       Error_Behavior errb)
+{
+  XFontStruct *xf;
+  const Extbyte *extname;
+
+#ifndef THIS_IS_GTK
+  Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device));
+
+  LISP_STRING_TO_EXTERNAL (f->name, extname, Qx_font_name_encoding);
+  xf = XLoadQueryFont (dpy, extname);
+
+  if (!xf)
+    {
+      maybe_signal_error (Qgui_error, "Couldn't load font", f->name,
+			  Qfont, errb);
+      return 0;
+    }
+
+  if (!xf->max_bounds.width)
+    {
+      /* yes, this has been known to happen. */
+      XFreeFont (dpy, xf);
+      maybe_signal_error (Qgui_error, "X font is too small", f->name, Qfont,
+			  errb);
+
+      return 0;
+    }
+
+#else /* THIS_IS_GTK */
+  GdkFont *gf;
+
+  LISP_STRING_TO_EXTERNAL (f->name, extname, Vgtk_text_encoding);
+  gf = gdk_font_load (extname);
+
+  if (!gf)
+    {
+      maybe_signal_error (Qgui_error, "Couldn't load font", f->name,
+			  Qfont, errb);
+      return 0;
+    }
+
+  xf = (XFontStruct *) GDK_FONT_XFONT (gf);
+
+#endif /* THIS_IS_GTK */
+
+  /* Don't allocate the data until we're sure that we will succeed,
+     or the finalize method may get fucked. */
+
+#ifndef THIS_IS_GTK
+  f->data = xnew (struct x_font_instance_data);
+  FONT_INSTANCE_X_FONT (f) = xf;
+  f->ascent = xf->ascent;
+  f->descent = xf->descent;
+  f->height = xf->ascent + xf->descent;
+#else /* THIS_IS_GTK */
+  f->data = xnew (struct gtk_font_instance_data);
+  FONT_INSTANCE_GTK_FONT (f) = gf;
+  f->ascent = gf->ascent;
+  f->descent = gf->descent;
+  f->height = gf->ascent + gf->descent;
+#endif /* THIS_IS_GTK */
+
+  /* Now let's figure out the width of the font */
+
+  {
+    /* following change suggested by Ted Phelps <phelps@dstc.edu.au> */
+    int def_char = 'n'; /*xf->default_char;*/
+    int byte1, byte2;
+
+  once_more:
+    byte1 = def_char >> 8;
+    byte2 = def_char & 0xFF;
+
+    if (xf->per_char)
+      {
+	/* Old versions of the R5 font server have garbage (>63k) as
+	   def_char. 'n' might not be a valid character. */
+	if (byte1 < (int) xf->min_byte1         ||
+	    byte1 > (int) xf->max_byte1         ||
+	    byte2 < (int) xf->min_char_or_byte2 ||
+	    byte2 > (int) xf->max_char_or_byte2)
+	  f->width = 0;
+	else
+	  f->width = xf->per_char[(byte1 - xf->min_byte1) *
+				  (xf->max_char_or_byte2 -
+				   xf->min_char_or_byte2 + 1) +
+				  (byte2 - xf->min_char_or_byte2)].width;
+      }
+    else
+      f->width = xf->max_bounds.width;
+
+    /* Some fonts have a default char whose width is 0.  This is no good.
+       If that's the case, first try 'n' as the default char, and if n has
+       0 width too (unlikely) then just use the max width. */
+    if (f->width == 0)
+      {
+	if (def_char == (int) xf->default_char)
+	  f->width = xf->max_bounds.width;
+	else
+	  {
+	    def_char = xf->default_char;
+	    goto once_more;
+	  }
+      }
+  }
+  /* If all characters don't exist then there could potentially be
+     0-width characters lurking out there.  Not setting this flag
+     trips an optimization that would make them appear to have width
+     to redisplay.  This is bad.  So we set it if not all characters
+     have the same width or if not all characters are defined.
+     */
+  /* #### This sucks.  There is a measurable performance increase
+     when using proportional width fonts if this flag is not set.
+     Unfortunately so many of the fucking X fonts are not fully
+     defined that we could almost just get rid of this damn flag and
+     make it an assertion. */
+  f->proportional_p = (xf->min_bounds.width != xf->max_bounds.width ||
+		       (
+#ifndef THIS_IS_GTK
+			x_handle_non_fully_specified_fonts &&
+#else /* THIS_IS_GTK */
+			/* x_handle_non_fully_specified_fonts */ 0 &&
+#endif /* THIS_IS_GTK */
+			!xf->all_chars_exist));
+
+#if 0 /* THIS_IS_GTK */
+  f->width = gdk_char_width (gf, 'n');
+  f->proportional_p = (gdk_char_width (gf, '|') != gdk_char_width (gf, 'W'));
+#endif
+  return 1;
+}
+
+static void
+ZZ (print_font_instance) (Lisp_Font_Instance *f,
+			  Lisp_Object printcharfun,
+			  int UNUSED (escapeflag))
+{
+  write_fmt_string (printcharfun, " 0x%lx",
+#ifndef THIS_IS_GTK
+		    (unsigned long) FONT_INSTANCE_X_FONT (f)->fid);
+#else /* THIS_IS_GTK */
+		    (unsigned long) gdk_font_id (FONT_INSTANCE_GTK_FONT (f)));
+#endif /* THIS_IS_GTK */
+}
+
+static void
+ZZ (finalize_font_instance) (Lisp_Font_Instance *f)
+{
+  if (f->data)
+    {
+      if (DEVICE_LIVE_P (XDEVICE (f->device)))
+	{
+#ifndef THIS_IS_GTK
+	  XFreeFont (DEVICE_X_DISPLAY (XDEVICE (f->device)),
+		     FONT_INSTANCE_X_FONT (f));
+#else /* THIS_IS_GTK */
+	  gdk_font_unref (FONT_INSTANCE_GTK_FONT (f));
+#endif /* THIS_IS_GTK */
+	}
+      xfree (f->data, void *);
+      f->data = 0;
+    }
+}
+
+/* Unbounded, for sufficiently small values of infinity... */
+#define MAX_FONT_COUNT 5000
+
+#ifndef THIS_IS_GTK
+static Lisp_Object x_font_truename (Display *dpy, Extbyte *name,
+				    XFontStruct *font);
+#else
+Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp);
+#endif
+
+static Lisp_Object
+ZZ (font_instance_truename) (Lisp_Font_Instance *f, Error_Behavior errb)
+{
+  if (NILP (FONT_INSTANCE_TRUENAME (f)))
+    {
+#ifndef THIS_IS_GTK
+      FONT_INSTANCE_TRUENAME (f) =
+	x_font_truename (DEVICE_X_DISPLAY (XDEVICE (f->device)),
+			 NEW_LISP_STRING_TO_EXTERNAL
+			 (f->name, Qx_font_name_encoding),
+			 FONT_INSTANCE_X_FONT (f));
+#else
+      FONT_INSTANCE_TRUENAME (f) =
+	__get_gtk_font_truename (FONT_INSTANCE_GTK_FONT (f), 1);
+#endif /* THIS_IS_GTK */
+
+      if (NILP (FONT_INSTANCE_TRUENAME (f)))
+	{
+	  Lisp_Object font_instance = wrap_font_instance (f);
+
+
+	  maybe_signal_error (Qgui_error, "Couldn't determine font truename",
+			      font_instance, Qfont, errb);
+	  /* Ok, just this once, return the font name as the truename.
+	     (This is only used by Fequal() right now.) */
+	  return f->name;
+	}
+    }
+  return FONT_INSTANCE_TRUENAME (f);
+}
+
+#ifdef MULE
+
+static int
+ZZ (font_spec_matches_charset) (struct device *UNUSED (d), Lisp_Object charset,
+				const Ibyte *nonreloc, Lisp_Object reloc,
+				Bytecount offset, Bytecount length,
+				int stage)
+{
+  if (stage)
+    return 0;
+
+  if (UNBOUNDP (charset))
+    return 1;
+  /* Hack! Short font names don't have the registry in them,
+     so we just assume the user knows what they're doing in the
+     case of ASCII.  For other charsets, you gotta give the
+     long form; sorry buster.
+     */
+  if (EQ (charset, Vcharset_ascii))
+    {
+      const Ibyte *the_nonreloc = nonreloc;
+      int i;
+      Bytecount the_length = length;
+
+      if (!the_nonreloc)
+	the_nonreloc = XSTRING_DATA (reloc);
+      fixup_internal_substring (nonreloc, reloc, offset, &the_length);
+      the_nonreloc += offset;
+      if (!memchr (the_nonreloc, '*', the_length))
+	{
+	  for (i = 0;; i++)
+	    {
+	      const Ibyte *new_nonreloc = (const Ibyte *)
+		memchr (the_nonreloc, '-', the_length);
+	      if (!new_nonreloc)
+		break;
+	      new_nonreloc++;
+	      the_length -= new_nonreloc - the_nonreloc;
+	      the_nonreloc = new_nonreloc;
+	    }
+
+	  /* If it has less than 5 dashes, it's a short font.
+	     Of course, long fonts always have 14 dashes or so, but short
+	     fonts never have more than 1 or 2 dashes, so this is some
+	     sort of reasonable heuristic. */
+	  if (i < 5)
+	    return 1;
+	}
+    }
+
+  return (fast_string_match (XCHARSET_REGISTRY (charset),
+			     nonreloc, reloc, offset, length, 1,
+			     ERROR_ME, 0) >= 0);
+}
+
+/* find a font spec that matches font spec FONT and also matches
+   (the registry of) CHARSET. */
+static Lisp_Object
+ZZ (find_charset_font) (Lisp_Object device, Lisp_Object font,
+			Lisp_Object charset, int stage)
+{
+#ifdef THIS_IS_GTK
+  /* #### copied from x_find_charset_font */
+  /* #### BILL!!! Try to make this go away eventually */
+#endif /* THIS_IS_GTK */
+  Extbyte **names;
+  int count = 0;
+  Lisp_Object result = Qnil;
+  const Extbyte *patternext;
+  int i;
+
+  if (stage)
+    return Qnil;
+
+  LISP_STRING_TO_EXTERNAL (font, patternext, Qx_font_name_encoding);
+
+  names = XListFonts (
+#ifndef THIS_IS_GTK
+		      DEVICE_X_DISPLAY (XDEVICE (device)),
+#else
+		      GDK_DISPLAY (),
+#endif
+		      patternext, MAX_FONT_COUNT, &count);
+  /* #### This code seems awfully bogus -- mrb */
+  for (i = 0; i < count; i ++)
+    {
+      const Ibyte *intname;
+      Bytecount intlen;
+
+      EXTERNAL_TO_SIZED_C_STRING (names[i], intname, intlen,
+				  Qx_font_name_encoding);
+      if (ZZ (font_spec_matches_charset) (XDEVICE (device), charset,
+					  intname, Qnil, 0, -1, stage))
+	{
+	  result = make_string (intname, intlen);
+	  break;
+	}
+    }
+
+  if (names)
+    XFreeFontNames (names);
+
+  /* Check for a short font name. */
+  if (NILP (result)
+      && ZZ (font_spec_matches_charset) (XDEVICE (device), charset, 0,
+					 font, 0, -1, stage))
+    return font;
+
+  return result;
+}
+
+#endif /* MULE */
+
+
+/************************************************************************/
+/*                            initialization                            */
+/************************************************************************/
+
+void
+ZZEND (console_type_create_objects) (void)
+{
+  /* object methods */
+
+  ZZCONSOLE_HAS_METHOD (initialize_color_instance);
+  ZZCONSOLE_HAS_METHOD (print_color_instance);
+  ZZCONSOLE_HAS_METHOD (finalize_color_instance);
+  ZZCONSOLE_HAS_METHOD (color_instance_equal);
+  ZZCONSOLE_HAS_METHOD (color_instance_hash);
+  ZZCONSOLE_HAS_METHOD (color_instance_rgb_components);
+  ZZCONSOLE_HAS_METHOD (valid_color_name_p);
+  ZZCONSOLE_HAS_METHOD (color_list);
+
+  ZZCONSOLE_HAS_METHOD (initialize_font_instance);
+  ZZCONSOLE_HAS_METHOD (print_font_instance);
+  ZZCONSOLE_HAS_METHOD (finalize_font_instance);
+  ZZCONSOLE_HAS_METHOD (font_instance_truename);
+  ZZCONSOLE_HAS_METHOD (font_instance_properties);
+  ZZCONSOLE_HAS_METHOD (font_list);
+#ifdef MULE
+  ZZCONSOLE_HAS_METHOD (find_charset_font);
+  ZZCONSOLE_HAS_METHOD (font_spec_matches_charset);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ui-gtk-inc.c	Tue Feb 15 01:21:24 2005 +0000
@@ -0,0 +1,298 @@
+/* ui-gtk-inc.c
+**
+** Description: Include file for duplicated code in ui-gtk.c
+**
+** Created by: William M. Perry <wmperry@gnu.org>
+** Copyright (c) 2000 William M. Perry <wmperry@gnu.org>
+   Copyright (c) 2003 Ben Wing.
+**
+*/
+
+#undef GTK_LVALUE
+
+#ifdef GTK_CONVERT_NORMAL
+#define GTK_LVALUE(type) GTK_VALUE_##type (*arg)
+#else
+#define GTK_LVALUE(type) *(GTK_RETLOC_##type (*arg))
+#endif
+
+int
+#ifdef GTK_CONVERT_NORMAL
+lisp_to_gtk_type (Lisp_Object obj, GtkArg *arg)
+#else
+lisp_to_gtk_ret_type (Lisp_Object obj, GtkArg *arg)
+#endif
+{
+  switch (GTK_FUNDAMENTAL_TYPE (arg->type))
+    {
+      /* flag types */
+    case GTK_TYPE_NONE:
+      return (0);
+    case GTK_TYPE_CHAR:
+    case GTK_TYPE_UCHAR:
+      CHECK_CHAR_COERCE_INT (obj);
+      GTK_LVALUE (CHAR) = ichar_to_unicode (XCHAR (obj));
+      break;
+    case GTK_TYPE_BOOL:
+      GTK_LVALUE (BOOL) = NILP (obj) ? FALSE : TRUE;
+      break;
+    case GTK_TYPE_INT:
+    case GTK_TYPE_UINT:
+      if (NILP (obj) || EQ (Qt, obj))
+	{
+	  /* For we are a kind mistress and allow sending t/nil for
+             1/0 to stupid GTK functions that say they take guint or
+             gint in the header files, but actually treat it like a
+             bool.  *sigh*
+	  */
+	  GTK_LVALUE (INT) = NILP (obj) ? 0 : 1;
+	}
+      else
+	{
+	  CHECK_INT (obj);
+	  GTK_LVALUE (INT) = XINT (obj);
+	}
+      break;
+    case GTK_TYPE_LONG:
+    case GTK_TYPE_ULONG:
+      ABORT ();
+    case GTK_TYPE_FLOAT:
+      CHECK_INT_OR_FLOAT (obj);
+      GTK_LVALUE (FLOAT) = extract_float (obj);
+      break;
+    case GTK_TYPE_DOUBLE:
+      CHECK_INT_OR_FLOAT (obj);
+      GTK_LVALUE (DOUBLE) = extract_float (obj);
+      break;
+    case GTK_TYPE_STRING:
+      if (NILP (obj))
+	GTK_LVALUE (STRING) = NULL;
+      else
+	{
+	  CHECK_STRING (obj);
+#ifdef GTK_CONVERT_NORMAL
+	  LISP_STRING_TO_EXTERNAL_MALLOC (obj, GTK_LVALUE (STRING),
+					  Vgtk_text_encoding);
+#else
+	  /* #### BILL!! Is this correct?  It followed the old logic */
+	  LISP_STRING_TO_EXTERNAL (obj, GTK_LVALUE (STRING),
+				   Vgtk_text_encoding);
+#endif
+
+	}
+      break;
+    case GTK_TYPE_ENUM:
+    case GTK_TYPE_FLAGS:
+      /* Convert a lisp symbol to a GTK enum */
+      GTK_LVALUE (ENUM) = lisp_to_flag (obj, arg->type);
+      break;
+    case GTK_TYPE_BOXED:
+      if (NILP (obj))
+	{
+	  GTK_LVALUE (BOXED) = NULL;
+	}
+      else if (GTK_BOXEDP (obj))
+	{
+	  GTK_LVALUE (BOXED) = XGTK_BOXED (obj)->object;
+	}
+      else if (arg->type == GTK_TYPE_STYLE)
+	{
+	  obj = Ffind_face (obj);
+	  CHECK_FACE (obj);
+	  GTK_LVALUE (BOXED) = face_to_style (obj);
+	}
+      else if (arg->type == GTK_TYPE_GDK_GC)
+	{
+	  obj = Ffind_face (obj);
+	  CHECK_FACE (obj);
+	  GTK_LVALUE (BOXED) = face_to_gc (obj);
+	}
+      else if (arg->type == GTK_TYPE_GDK_WINDOW)
+	{
+	  if (GLYPHP (obj))
+	    {
+	      Lisp_Object window = Fselected_window (Qnil);
+	      Lisp_Object instance =
+		glyph_image_instance (obj, window, ERROR_ME_DEBUG_WARN, 1);
+	      struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (instance);
+
+	      switch (XIMAGE_INSTANCE_TYPE (instance))
+		{
+		case IMAGE_TEXT:
+		case IMAGE_POINTER:
+		case IMAGE_SUBWINDOW:
+		case IMAGE_NOTHING:
+		  GTK_LVALUE (BOXED) = NULL;
+		  break;
+
+		case IMAGE_MONO_PIXMAP:
+		case IMAGE_COLOR_PIXMAP:
+		  GTK_LVALUE (BOXED) = IMAGE_INSTANCE_GTK_PIXMAP (p);
+		  break;
+		}
+	    }
+	  else if (GTK_OBJECTP (obj) &&
+		   GTK_IS_WIDGET (XGTK_OBJECT (obj)->object))
+	    {
+	      GTK_LVALUE (BOXED) = GTK_WIDGET (XGTK_OBJECT (obj))->window;
+	    }
+	  else
+	    {
+	      invalid_argument
+		("Don't know how to convert object to GDK_WINDOW", obj);
+	    }
+	  break;
+	}
+      else if (arg->type == GTK_TYPE_GDK_COLOR)
+	{
+	  if (COLOR_SPECIFIERP (obj))
+	    {
+	      /* If it is a specifier, we just convert it to an
+                 instance, and let the ifs below handle it.
+	      */
+	      obj = Fspecifier_instance (obj, Qnil, Qnil, Qnil);
+	    }
+	  
+	  if (COLOR_INSTANCEP (obj))
+	    {
+	      /* Easiest one */
+	      GTK_LVALUE (BOXED) =
+		COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (obj));
+	    }
+	  else if (STRINGP (obj))
+	    {
+	      invalid_argument
+		("Please use a color specifier or instance, not a string",
+		 obj);
+	    }
+	  else
+	    {
+	      invalid_argument ("Don't know how to convert to GdkColor", obj);
+	    }
+	}
+      else if (arg->type == GTK_TYPE_GDK_FONT)
+	{
+	  if (SYMBOLP (obj))
+	    {
+	      /* If it is a symbol, we treat that as a face name */
+	      obj = Ffind_face (obj);
+	    }
+
+	  if (FACEP (obj))
+	    {
+	      /* If it is a face, we just grab the font specifier, and
+                 cascade down until we finally reach a FONT_INSTANCE
+	      */
+	      obj = Fget (obj, Qfont, Qnil);
+	    }
+
+	  if (FONT_SPECIFIERP (obj))
+	    {
+	      /* If it is a specifier, we just convert it to an
+                 instance, and let the ifs below handle it
+	      */
+	      obj = Fspecifier_instance (obj, Qnil, Qnil, Qnil);
+	    }
+
+	  if (FONT_INSTANCEP (obj))
+	    {
+	      /* Easiest one */
+	      GTK_LVALUE (BOXED) =
+		FONT_INSTANCE_GTK_FONT (XFONT_INSTANCE (obj));
+	    }
+	  else if (STRINGP (obj))
+	    {
+	      invalid_argument
+		("Please use a font specifier or instance, not a string", obj);
+	    }
+	  else
+	    {
+	      invalid_argument ("Don't know how to convert to GdkColor", obj);
+	    }
+	}
+      else
+	{
+	  /* Unknown type to convert to boxed */
+	  stderr_out ("Don't know how to convert to boxed!\n");
+	  GTK_LVALUE (BOXED) = NULL;
+	}
+      break;
+
+    case GTK_TYPE_POINTER:
+      if (NILP (obj))
+	GTK_LVALUE (POINTER) = NULL;
+      else
+	GTK_LVALUE (POINTER) = LISP_TO_VOID (obj);
+      break;
+
+      /* structured types */
+    case GTK_TYPE_SIGNAL:
+    case GTK_TYPE_ARGS: /* This we can do as a list of values */
+    case GTK_TYPE_C_CALLBACK:
+    case GTK_TYPE_FOREIGN:
+      stderr_out ("Do not know how to convert `%s' from lisp!\n",
+		  GTK_TEXT_TO_C_STRING (gtk_type_name (arg->type)));
+      return (-1);
+
+#if 0
+      /* #### BILL! */
+      /* #### This is not used, and GTK_RETLOC_CALLBACK does not exist */
+    case GTK_TYPE_CALLBACK:
+      {
+	GUI_ID id;
+
+	id = new_gui_id ();
+	obj = Fcons (Qnil, obj); /* Empty data */
+	obj = Fcons (make_int (id), obj);
+
+	gcpro_popup_callbacks (id, obj);
+
+	GTK_LVALUE (CALLBACK).marshal = __internal_callback_marshal;
+	GTK_LVALUE (CALLBACK).data = LISP_TO_VOID (obj);
+	GTK_LVALUE (CALLBACK).notify = __internal_callback_destroy;
+      }
+      break;
+#endif
+
+      /* base type of the object system */
+    case GTK_TYPE_OBJECT:
+      if (NILP (obj))
+	GTK_LVALUE (OBJECT) = NULL;
+      else
+	{
+	  CHECK_GTK_OBJECT (obj);
+	  if (XGTK_OBJECT (obj)->alive_p)
+	    GTK_LVALUE (OBJECT) = XGTK_OBJECT (obj)->object;
+	  else
+	    invalid_argument
+	      ("Attempting to pass dead object to GTK function", obj);
+	}
+      break;
+
+    default:
+      /* GTK_TYPE_ARRAY, GTK_TYPE_LISTOF not constants */
+      if (GTK_FUNDAMENTAL_TYPE_EQ (arg->type, GTK_TYPE_ARRAY))
+	{
+	  if (NILP (obj))
+	    GTK_LVALUE (POINTER) = NULL;
+	  else
+	    xemacs_list_to_array (obj, arg);
+	}
+      else if (GTK_FUNDAMENTAL_TYPE_EQ (arg->type, GTK_TYPE_LISTOF))
+	{
+	  if (NILP (obj))
+	    GTK_LVALUE (POINTER) = NULL;
+	  else
+	    xemacs_list_to_gtklist (obj, arg);
+	}
+      else
+	{
+	  stderr_out ("Do not know how to convert `%s' from lisp!\n",
+		      GTK_TEXT_TO_C_STRING (gtk_type_name (arg->type)));
+	  ABORT ();
+	}
+      break;
+    }
+
+  return (0);
+}
--- a/src/universe.h	Mon Feb 14 22:51:46 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
-
-This file is part of XEmacs.
-
-XEmacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-XEmacs is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* Synched up with: Not in FSF. */
-
-/* This is a helper for precompiled headers.
-   Pay no attention to the man behind the curtain. */
-
-#include <config.h>
-#include <X11/Xlib.h>
-#include "xintrinsicp.h"
-#include "lisp.h"
--- a/src/xgccache.c	Mon Feb 14 22:51:46 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,333 +0,0 @@
-/* Efficient caching of X GCs (graphics contexts).
-   Copyright (C) 1993 Free Software Foundation, Inc.
-   Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
-
-This file is part of XEmacs.
-
-XEmacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-XEmacs is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* Synched up with: Not in FSF. */
-
-/* Emacs uses a lot of different display attributes; for example, assume
-   that only four fonts are in use (normal, bold, italic, and bold-italic).
-   Then assume that one stipple or background is used for text selections,
-   and another is used for highlighting mousable regions.  That makes 16
-   GCs already.  Add in the fact that another GC may be needed to display
-   the text cursor in any of those regions, and you've got 32.  Add in
-   more fonts, and it keeps increasing exponentially.
-
-   We used to keep these GCs in a cache of merged (fully qualified) faces.
-   However, a lot of other code in xterm.c used XChangeGC of existing GCs,
-   which is kind of slow and kind of random.  Also, managing the face cache
-   was tricky because it was hard to know when a face was no longer visible
-   on the frame -- we had to mark all frames as garbaged whenever a face
-   was changed, which caused an unpleasant amount of flicker (since faces are
-   created/destroyed (= changed) whenever a frame is created/destroyed.
-
-   So this code maintains a cache at the GC level instead of at the face
-   level.  There is an upper limit on the size of the cache, after which we
-   will stop creating GCs and start reusing them (reusing the least-recently-
-   used ones first).  So if faces get changed, their GCs will eventually be
-   recycled.  Also more sharing of GCs is possible.
-
-   This code uses hash tables.  It could be that, if the cache size is small
-   enough, a linear search might be faster; but I doubt it, since we need
-   `equal' comparisons, not `eq', and I expect that the optimal cache size
-   will be ~100.
-
-   Written by jwz, 14 jun 93
- */
-
-#include <config.h>
-#include <X11/Xlib.h>
-#include "xgccache.h"
-
-
-#define GC_CACHE_SIZE 100
-
-#define GCCACHE_HASH
-
-
-#ifdef GCCACHE_HASH
-#include "lisp.h"
-#include "hash.h"
-#endif
-
-struct gcv_and_mask {
-  XGCValues gcv;
-  unsigned long mask;
-};
-
-struct gc_cache_cell {
-  GC gc;
-  struct gcv_and_mask gcvm;
-  struct gc_cache_cell *prev, *next;
-};
-
-struct gc_cache {
-  Display *dpy;		/* used only as arg to XCreateGC/XFreeGC */
-  Window window;	/* used only as arg to XCreateGC */
-  int size;
-  struct gc_cache_cell *head;
-  struct gc_cache_cell *tail;
-#ifdef GCCACHE_HASH
-  struct hash_table *table;
-#endif
-
-  int create_count;
-  int delete_count;
-};
-
-#ifdef GCCACHE_HASH
-static Hashcode
-gc_cache_hash (const void *arg)
-{
-  const struct gcv_and_mask *gcvm = (const struct gcv_and_mask *) arg;
-  unsigned long *longs = (unsigned long *) &gcvm->gcv;
-  Hashcode hash = gcvm->mask;
-  int i;
-  /* This could look at the mask and only use the used slots in the
-     hash code.  That would win in that we wouldn't have to initialize
-     every slot of the gcv when calling gc_cache_lookup.  But we need
-     the hash function to be as fast as possible; some timings should
-     be done. */
-  for (i = 0; i < (int) (sizeof (XGCValues) / sizeof (unsigned long)); i++)
-    hash = (hash << 1) ^ *longs++;
-  return hash;
-}
-
-#endif /* GCCACHE_HASH */
-
-static int
-gc_cache_eql (const void *arg1, const void *arg2)
-{
-  /* See comment in gc_cache_hash */
-  return !memcmp (arg1, arg2, sizeof (struct gcv_and_mask));
-}
-
-struct gc_cache *
-make_gc_cache (Display *dpy, Window window)
-{
-  struct gc_cache *cache = xnew (struct gc_cache);
-  cache->dpy = dpy;
-  cache->window = window;
-  cache->size = 0;
-  cache->head = cache->tail = 0;
-  cache->create_count = cache->delete_count = 0;
-#ifdef GCCACHE_HASH
-  cache->table =
-    make_general_hash_table (GC_CACHE_SIZE, gc_cache_hash, gc_cache_eql);
-#endif
-  return cache;
-}
-
-void
-free_gc_cache (struct gc_cache *cache)
-{
-  struct gc_cache_cell *rest, *next;
-  rest = cache->head;
-  while (rest)
-    {
-      XFreeGC (cache->dpy, rest->gc);
-      next = rest->next;
-      xfree (rest, struct gc_cache_cell *);
-      rest = next;
-    }
-#ifdef GCCACHE_HASH
-  free_hash_table (cache->table);
-#endif
-  xfree (cache, struct gc_cache *);
-}
-
-GC
-gc_cache_lookup (struct gc_cache *cache, XGCValues *gcv, unsigned long mask)
-{
-  struct gc_cache_cell *cell, *next, *prev;
-  struct gcv_and_mask gcvm;
-
-  if ((!!cache->head) != (!!cache->tail)) ABORT ();
-  if (cache->head && (cache->head->prev || cache->tail->next)) ABORT ();
-
-  gcvm.mask = mask;
-  gcvm.gcv = *gcv;	/* this copies... */
-
-#ifdef GCCACHE_HASH
-
-  /* The intermediate cast fools gcc into not outputting strict-aliasing
-     complaints */
-  if (gethash (&gcvm, cache->table, (const void **) (void *) &cell))
-
-#else /* !GCCACHE_HASH */
-
-  cell = cache->tail;	/* start at the end (most recently used) */
-  while (cell)
-    {
-      if (gc_cache_eql (&gcvm, &cell->gcvm))
-	break;
-      else
-	cell = cell->prev;
-    }
-
-  /* #### This whole file needs some serious overhauling. */
-  if (!(mask | GCTile) && cell->gc->values.tile)
-    cell = 0;
-  else if (!(mask | GCStipple) && cell->gc->values.stipple)
-    cell = 0;
-
-  if (cell)
-
-#endif /* !GCCACHE_HASH */
-
-    {
-      /* Found a cell.  Move this cell to the end of the list, so that it
-	 will be less likely to be collected than a cell that was accessed
-	 less recently.
-       */
-      if (cell == cache->tail)
-	return cell->gc;
-
-      next = cell->next;
-      prev = cell->prev;
-      if (prev) prev->next = next;
-      if (next) next->prev = prev;
-      if (cache->head == cell) cache->head = next;
-      cell->next = 0;
-      cell->prev = cache->tail;
-      cache->tail->next = cell;
-      cache->tail = cell;
-      if (cache->head == cell) ABORT ();
-      if (cell->next) ABORT ();
-      if (cache->head->prev) ABORT ();
-      if (cache->tail->next) ABORT ();
-      return cell->gc;
-    }
-
-  /* else, cache miss. */
-
-  if (cache->size == GC_CACHE_SIZE)
-    /* Reuse the first cell on the list (least-recently-used).
-       Remove it from the list, and unhash it from the table.
-     */
-    {
-      cell = cache->head;
-      cache->head = cell->next;
-      cache->head->prev = 0;
-      if (cache->tail == cell) cache->tail = 0; /* only one */
-      XFreeGC (cache->dpy, cell->gc);
-      cache->delete_count++;
-#ifdef GCCACHE_HASH
-      remhash (&cell->gcvm, cache->table);
-#endif
-    }
-  else if (cache->size > GC_CACHE_SIZE)
-    ABORT ();
-  else
-    {
-      /* Allocate a new cell (don't put it in the list or table yet). */
-      cell = xnew (struct gc_cache_cell);
-      cache->size++;
-    }
-
-  /* Now we've got a cell (new or reused).  Fill it in. */
-  memcpy (&cell->gcvm.gcv, gcv, sizeof (XGCValues));
-  cell->gcvm.mask = mask;
-
-  /* Put the cell on the end of the list. */
-  cell->next = 0;
-  cell->prev = cache->tail;
-  if (cache->tail) cache->tail->next = cell;
-  cache->tail = cell;
-  if (! cache->head) cache->head = cell;
-
-  cache->create_count++;
-#ifdef GCCACHE_HASH
-  /* Hash it in the table */
-  puthash (&cell->gcvm, cell, cache->table);
-#endif
-
-  /* Now make and return the GC. */
-  cell->gc = XCreateGC (cache->dpy, cache->window, mask, gcv);
-
-  /* debug */
-  assert (cell->gc == gc_cache_lookup (cache, gcv, mask));
-
-  return cell->gc;
-}
-
-
-#ifdef DEBUG_XEMACS
-
-void describe_gc_cache (struct gc_cache *cache);
-void
-describe_gc_cache (struct gc_cache *cache)
-{
-  int count = 0;
-  struct gc_cache_cell *cell = cache->head;
-  stderr_out ("\nsize:    %d", cache->size);
-  stderr_out ("\ncreated: %d", cache->create_count);
-  stderr_out ("\ndeleted: %d", cache->delete_count);
-  while (cell)
-  {
-    struct gc_cache_cell *cell2;
-    int i = 0;
-    stderr_out ("\n%d:\t0x%lx  GC: 0x%08lx  hash: 0x%08lx\n",
-	     count, (long) cell, (long) cell->gc, gc_cache_hash (&cell->gcvm));
-    for (cell2 = cache->head; cell2; cell2 = cell2->next, i++)
-      if (count != i &&
-	  gc_cache_hash (&cell->gcvm) == gc_cache_hash (&cell2->gcvm))
-	stderr_out ("\tHASH COLLISION with cell %d\n", i);
-    stderr_out ("\tmask:       %8lx\n", cell->gcvm.mask);
-
-#define FROB(field) do {						\
-  if ((int)cell->gcvm.gcv.field != (~0))				\
-    stderr_out ("\t%-12s%8x\n", #field ":", (int)cell->gcvm.gcv.field);	\
-} while (0)
-    FROB (function);
-    FROB (plane_mask);
-    FROB (foreground);
-    FROB (background);
-    FROB (line_width);
-    FROB (line_style);
-    FROB (cap_style);
-    FROB (join_style);
-    FROB (fill_style);
-    FROB (fill_rule);
-    FROB (arc_mode);
-    FROB (tile);
-    FROB (stipple);
-    FROB (ts_x_origin);
-    FROB (ts_y_origin);
-    FROB (font);
-    FROB (subwindow_mode);
-    FROB (graphics_exposures);
-    FROB (clip_x_origin);
-    FROB (clip_y_origin);
-    FROB (clip_mask);
-    FROB (dash_offset);
-#undef FROB
-
-    count++;
-    if (cell->next && cell == cache->tail)
-      stderr_out ("\nERROR!  tail is here!\n\n");
-    else if (!cell->next && cell != cache->tail)
-      stderr_out ("\nERROR!  tail is not at the end\n\n");
-    cell = cell->next;
-  }
-  if (count != cache->size)
-    stderr_out ("\nERROR!  count should be %d\n\n", cache->size);
-}
-
-#endif /* DEBUG_XEMACS */
--- a/src/xgccache.h	Mon Feb 14 22:51:46 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/* Efficient caching of X GCs (graphics contexts).
-   Copyright (C) 1993 Free Software Foundation, Inc.
-
-
-This file is part of XEmacs.
-
-XEmacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-XEmacs is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* Synched up with: Not in FSF. */
-
-/* Written by jwz, 14 jun 93 */
-
-#ifndef INCLUDED_xgccache_h_
-#define INCLUDED_xgccache_h_
-
-struct gc_cache;
-struct gc_cache *make_gc_cache (Display *, Window);
-void free_gc_cache (struct gc_cache *cache);
-GC gc_cache_lookup (struct gc_cache *, XGCValues *, unsigned long mask);
-
-#endif /* INCLUDED_xgccache_h_ */