changeset 49322:2cbb0b823e83

GTK version
author Jan Djärv <jan.h.d@swipnet.se>
date Sun, 19 Jan 2003 21:50:03 +0000
parents 2b92ca3f78f6
children 078b78ea8e76
files ChangeLog INSTALL configure configure.in man/ChangeLog man/xresources.texi src/ChangeLog src/Makefile.in src/alloc.c src/config.in src/dispnew.c src/fileio.c src/frame.h src/keyboard.c src/lisp.h src/xdisp.c src/xfns.c src/xmenu.c src/xterm.c src/xterm.h
diffstat 20 files changed, 2363 insertions(+), 577 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Jan 19 20:03:42 2003 +0000
+++ b/ChangeLog	Sun Jan 19 21:50:03 2003 +0000
@@ -1,3 +1,9 @@
+2003-01-19  Jan D.  <jan.h.d@swipnet.se>
+
+	* configure.in: Add --with-gtk, --with-x-toolkit=gtk
+
+	* INSTALL (DETAILED BUILDING AND INSTALLATION): Add text about GTK.
+
 2003-01-14  Francesco Potort,Al(B  <pot@gnu.org>
 
 	* configure.in (m68k-motorola-sysv): Removed (obsolete).
--- a/INSTALL	Sun Jan 19 20:03:42 2003 +0000
+++ b/INSTALL	Sun Jan 19 21:50:03 2003 +0000
@@ -270,7 +270,7 @@
 
 To get more attractive menus, you can specify an X toolkit when you
 configure Emacs; use the option `--with-x-toolkit=TOOLKIT', where
-TOOLKIT is `athena' or `motif' (`yes' and `lucid' are synonyms for
+TOOLKIT is `athena', `motif' or `gtk' (`yes' and `lucid' are synonyms for
 `athena').  On some systems, it does not work to use a toolkit with
 shared libraries.  A free implementation of Motif, called LessTif, is
 available ftom <http://www.lesstif.org>.  Compiling with LessTif or
@@ -280,6 +280,11 @@
 installed (see "Image support libraries" above for Xaw3d
 availability).
 
+If `--with-x-toolkit=gtk' is specified, you can tell configure where
+to search for GTK by specifying `--with-pkg-config-prog=PATH' where
+PATH is the pathname to pkg-config.  Note that GTK version 2.0 or
+newer is required for Emacs.
+
 The `--with-gcc' option specifies that the build process should
 compile Emacs using GCC.  If you don't want to use GCC, specify
 `--with-gcc=no'.  If you omit this option, `configure' will search
--- a/configure	Sun Jan 19 20:03:42 2003 +0000
+++ b/configure	Sun Jan 19 21:50:03 2003 +0000
@@ -309,7 +309,7 @@
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB INSTALL_INFO EGREP LIBSOUND SET_MAKE ALLOCA liblockfile LIBOBJS NEED_SETGID KMEM_GROUP GETLOADAVG_LIBS version configuration canonical srcdir lispdir locallisppath lisppath x_default_search_path etcdir archlibdir docdir bitmapdir gamedir gameuser c_switch_system c_switch_machine LD_SWITCH_X_SITE LD_SWITCH_X_SITE_AUX C_SWITCH_X_SITE X_TOOLKIT_TYPE machfile opsysfile carbon_appdir LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB INSTALL_INFO EGREP LIBSOUND SET_MAKE PKG_CONFIG GTK_CFLAGS GTK_LIBS ALLOCA liblockfile LIBOBJS NEED_SETGID KMEM_GROUP GETLOADAVG_LIBS version configuration canonical srcdir lispdir locallisppath lisppath x_default_search_path etcdir archlibdir docdir bitmapdir gamedir gameuser c_switch_system c_switch_machine LD_SWITCH_X_SITE LD_SWITCH_X_SITE_AUX C_SWITCH_X_SITE X_TOOLKIT_TYPE machfile opsysfile carbon_appdir LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -866,12 +866,15 @@
   --with-kerberos5        support Kerberos version 5 authenticated POP
   --with-hesiod           support Hesiod to get the POP server host
   --without-sound         don't compile with sound support
-  --with-x-toolkit=KIT    use an X toolkit (KIT = yes/lucid/athena/motif/no)
+  --with-x-toolkit=KIT    use an X toolkit
+                              (KIT = yes/lucid/athena/motif/gtk/no)
   --with-xpm              use -lXpm for displaying XPM images
   --with-jpeg             use -ljpeg for displaying JPEG images
   --with-tiff             use -ltiff for displaying TIFF images
   --with-gif              use -lungif for displaying GIF images
   --with-png              use -lpng for displaying PNG images
+  --with-gtk              use GTK (same as --with-x-toolkit=gtk)
+  --with-pkg-config-prog  Path to pkg-config to use for finding GTK
   --without-toolkit-scroll-bars
                           don't use Motif or Xaw3d scroll bars
   --without-xim           don't use X11 XIM
@@ -1402,12 +1405,13 @@
 	    l | lu | luc | luci | lucid )	val=lucid ;;
 	    a | at | ath | athe | athen | athena )	val=athena ;;
 	    m | mo | mot | moti | motif )	val=motif ;;
+	    g | gt | gtk  )	val=gtk ;;
 	    * )
 { { echo "$as_me:$LINENO: error: \`--with-x-toolkit=$withval' is invalid\;
-this option's value should be \`yes', \`no', \`lucid', \`athena', or \`motif'.
+this option's value should be \`yes', \`no', \`lucid', \`athena', \`motif' or \`gtk'.
 Currently, \`yes', \`athena' and \`lucid' are synonyms." >&5
 echo "$as_me: error: \`--with-x-toolkit=$withval' is invalid\;
-this option's value should be \`yes', \`no', \`lucid', \`athena', or \`motif'.
+this option's value should be \`yes', \`no', \`lucid', \`athena', \`motif' or \`gtk'.
 Currently, \`yes', \`athena' and \`lucid' are synonyms." >&2;}
    { (exit 1); exit 1; }; }
 	    ;;
@@ -1446,6 +1450,18 @@
 
 fi;
 
+# Check whether --with-gtk or --without-gtk was given.
+if test "${with_gtk+set}" = set; then
+  withval="$with_gtk"
+
+fi;
+
+# Check whether --with-pkg-config-prog or --without-pkg-config-prog was given.
+if test "${with_pkg_config_prog+set}" = set; then
+  withval="$with_pkg_config_prog"
+
+fi;
+
 # Check whether --with-toolkit-scroll-bars or --without-toolkit-scroll-bars was given.
 if test "${with_toolkit_scroll_bars+set}" = set; then
   withval="$with_toolkit_scroll_bars"
@@ -6800,6 +6816,8 @@
     case "${with_x_toolkit}" in
       athena | lucid ) USE_X_TOOLKIT=LUCID ;;
       motif ) USE_X_TOOLKIT=MOTIF ;;
+      gtk ) with_gtk=yes
+            USE_X_TOOLKIT=none ;;
       no ) USE_X_TOOLKIT=none ;;
       * ) USE_X_TOOLKIT=maybe ;;
     esac
@@ -8058,6 +8076,134 @@
   fi
 fi
 
+
+
+HAVE_GTK=no
+if test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "gtk"; then
+  if test "$USE_X_TOOLKIT" != "none"; then
+    { { echo "$as_me:$LINENO: error: Conflicting options, --with-gtk is incompatible with --with-x-toolkit=${with_x_toolkit}" >&5
+echo "$as_me: error: Conflicting options, --with-gtk is incompatible with --with-x-toolkit=${with_x_toolkit}" >&2;}
+   { (exit 1); exit 1; }; };
+  fi
+  GLIB_REQUIRED=2.0.1
+  GTK_REQUIRED=2.0.1
+  GTK_MODULES="gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
+
+    if test "X${with_pkg_config_prog}" != X; then
+    PKG_CONFIG="${with_pkg_config_prog}"
+  fi
+
+  succeeded=no
+
+  if test -z "$PKG_CONFIG"; then
+    # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+
+if test -n "$PKG_CONFIG"; then
+  echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+echo "${ECHO_T}$PKG_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  fi
+
+  if test "$PKG_CONFIG" = "no" ; then
+     echo "*** The pkg-config script could not be found. Make sure it is"
+     echo "*** in your path, or give the full path to pkg-config with"
+     echo "*** the PKG_CONFIG environment variable or --with-pkg-config-prog."
+     echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+  else
+     PKG_CONFIG_MIN_VERSION=0.9.0
+     if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+        echo "$as_me:$LINENO: checking for $GTK_MODULES" >&5
+echo $ECHO_N "checking for $GTK_MODULES... $ECHO_C" >&6
+
+        if $PKG_CONFIG --exists "$GTK_MODULES" ; then
+            echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+            succeeded=yes
+
+            echo "$as_me:$LINENO: checking GTK_CFLAGS" >&5
+echo $ECHO_N "checking GTK_CFLAGS... $ECHO_C" >&6
+            GTK_CFLAGS=`$PKG_CONFIG --cflags "$GTK_MODULES"`
+            echo "$as_me:$LINENO: result: $GTK_CFLAGS" >&5
+echo "${ECHO_T}$GTK_CFLAGS" >&6
+
+            echo "$as_me:$LINENO: checking GTK_LIBS" >&5
+echo $ECHO_N "checking GTK_LIBS... $ECHO_C" >&6
+            GTK_LIBS=`$PKG_CONFIG --libs "$GTK_MODULES"`
+            echo "$as_me:$LINENO: result: $GTK_LIBS" >&5
+echo "${ECHO_T}$GTK_LIBS" >&6
+        else
+            GTK_CFLAGS=""
+            GTK_LIBS=""
+            ## If we have a custom action on failure, don't print errors, but
+            ## do set a variable so people can do so.
+            GTK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$GTK_MODULES"`
+            echo $GTK_PKG_ERRORS
+        fi
+
+
+
+     else
+        echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+        echo "*** See http://www.freedesktop.org/software/pkgconfig"
+     fi
+  fi
+
+  if test $succeeded = yes; then
+     :
+  else
+     { { echo "$as_me:$LINENO: error: Library requirements ($GTK_MODULES) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&5
+echo "$as_me: error: Library requirements ($GTK_MODULES) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+
+
+
+  C_SWITCH_X_SITE="$C_SWITCH_X_SITE $GTK_CFLAGS"
+  HAVE_GTK=yes
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GTK 1
+_ACEOF
+
+  USE_X_TOOLKIT=none
+
+      with_toolkit_scroll_bars=yes
+fi
+
 if test x"${USE_X_TOOLKIT}" = xmaybe; then
   if test x"${HAVE_X11R5}" = xyes; then
     echo "$as_me:$LINENO: checking X11 version 5 with Xaw" >&5
@@ -8650,6 +8796,12 @@
 
       USE_TOOLKIT_SCROLL_BARS=yes
     fi
+  elif test "${HAVE_GTK}" = "yes"; then
+    cat >>confdefs.h <<\_ACEOF
+#define USE_TOOLKIT_SCROLL_BARS 1
+_ACEOF
+
+    USE_TOOLKIT_SCROLL_BARS=yes
   fi
 fi
 
@@ -17845,6 +17997,13 @@
 
 
 #### Report on what we decided to do.
+#### Report GTK as a toolkit, even if it doesn't use Xt.
+#### It makes printing result more understandable as using GTK sets
+#### toolkit_scroll_bars to yes by default.
+if test "${HAVE_GTK}" = "yes"; then
+  USE_X_TOOLKIT=GTK
+fi
+
 echo "
 Configured for \`${canonical}'.
 
@@ -18566,6 +18725,9 @@
 s,@EGREP@,$EGREP,;t t
 s,@LIBSOUND@,$LIBSOUND,;t t
 s,@SET_MAKE@,$SET_MAKE,;t t
+s,@PKG_CONFIG@,$PKG_CONFIG,;t t
+s,@GTK_CFLAGS@,$GTK_CFLAGS,;t t
+s,@GTK_LIBS@,$GTK_LIBS,;t t
 s,@ALLOCA@,$ALLOCA,;t t
 s,@liblockfile@,$liblockfile,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
--- a/configure.in	Sun Jan 19 20:03:42 2003 +0000
+++ b/configure.in	Sun Jan 19 21:50:03 2003 +0000
@@ -77,13 +77,15 @@
 dnl added later on when we find the path of X, and it's best to
 dnl keep them together visually.
 AC_ARG_WITH(x-toolkit,
-[  --with-x-toolkit=KIT    use an X toolkit (KIT = yes/lucid/athena/motif/no)],
+[  --with-x-toolkit=KIT    use an X toolkit 
+                              (KIT = yes/lucid/athena/motif/gtk/no)],
 [	  case "${withval}" in
 	    y | ye | yes )	val=athena ;;
 	    n | no )		val=no  ;;
 	    l | lu | luc | luci | lucid )	val=lucid ;;
 	    a | at | ath | athe | athen | athena )	val=athena ;;
 	    m | mo | mot | moti | motif )	val=motif ;;
+	    g | gt | gtk  )	val=gtk ;;
 dnl These don't currently work.
 dnl	    o | op | ope | open | open- | open-l | open-lo \
 dnl		| open-loo | open-look )	val=open-look ;;
@@ -91,7 +93,7 @@
 dnl AC_MSG_ERROR([the `--with-x-toolkit' option is supposed to have a value
 dnl which is `yes', `no', `lucid', `athena', `motif' or `open-look'.])
 AC_MSG_ERROR([`--with-x-toolkit=$withval' is invalid\;
-this option's value should be `yes', `no', `lucid', `athena', or `motif'.
+this option's value should be `yes', `no', `lucid', `athena', `motif' or `gtk'.
 Currently, `yes', `athena' and `lucid' are synonyms.])
 	    ;;
 	  esac
@@ -107,6 +109,10 @@
 [  --with-gif              use -lungif for displaying GIF images])
 AC_ARG_WITH(png,
 [  --with-png              use -lpng for displaying PNG images])
+AC_ARG_WITH(gtk,
+[  --with-gtk              use GTK (same as --with-x-toolkit=gtk)])
+AC_ARG_WITH(pkg-config-prog,
+[  --with-pkg-config-prog  Path to pkg-config to use for finding GTK])
 AC_ARG_WITH(toolkit-scroll-bars,
 [  --without-toolkit-scroll-bars
                           don't use Motif or Xaw3d scroll bars])
@@ -1570,6 +1576,10 @@
       athena | lucid ) USE_X_TOOLKIT=LUCID ;;
       motif ) USE_X_TOOLKIT=MOTIF ;;
 dnl      open-look ) USE_X_TOOLKIT=OPEN_LOOK ;;
+      gtk ) with_gtk=yes
+dnl Dont set this for GTK.  A lot of tests below assumes Xt when
+dnl USE_X_TOOLKIT is set.
+            USE_X_TOOLKIT=none ;;
       no ) USE_X_TOOLKIT=none ;;
 dnl If user did not say whether to use a toolkit,
 dnl make this decision later: use the toolkit if we have X11R5 or newer.
@@ -1781,6 +1791,89 @@
   fi
 fi
 
+dnl This function defintion taken from Gnome 2.0
+dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+dnl also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN(PKG_CHECK_MODULES, [
+  succeeded=no
+
+  if test -z "$PKG_CONFIG"; then
+    AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+  fi
+
+  if test "$PKG_CONFIG" = "no" ; then
+     echo "*** The pkg-config script could not be found. Make sure it is"
+     echo "*** in your path, or give the full path to pkg-config with"
+     echo "*** the PKG_CONFIG environment variable or --with-pkg-config-prog."
+     echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+  else
+     PKG_CONFIG_MIN_VERSION=0.9.0
+     if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+        AC_MSG_CHECKING(for $2)
+
+        if $PKG_CONFIG --exists "$2" ; then
+            AC_MSG_RESULT(yes)
+            succeeded=yes
+
+            AC_MSG_CHECKING($1_CFLAGS)
+            $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+            AC_MSG_RESULT($$1_CFLAGS)
+
+            AC_MSG_CHECKING($1_LIBS)
+            $1_LIBS=`$PKG_CONFIG --libs "$2"`
+            AC_MSG_RESULT($$1_LIBS)
+        else
+            $1_CFLAGS=""
+            $1_LIBS=""
+            ## If we have a custom action on failure, don't print errors, but 
+            ## do set a variable so people can do so.
+            $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+            ifelse([$4], ,echo $$1_PKG_ERRORS,)
+        fi
+
+        AC_SUBST($1_CFLAGS)
+        AC_SUBST($1_LIBS)
+     else
+        echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+        echo "*** See http://www.freedesktop.org/software/pkgconfig"
+     fi
+  fi
+
+  if test $succeeded = yes; then
+     ifelse([$3], , :, [$3])
+  else
+     ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+  fi
+])
+
+HAVE_GTK=no
+if test "${with_gtk}" = "yes" || test "$USE_X_TOOLKIT" = "gtk"; then
+  if test "$USE_X_TOOLKIT" != "none"; then
+    AC_MSG_ERROR([Conflicting options, --with-gtk is incompatible with --with-x-toolkit=${with_x_toolkit}]);
+  fi
+  GLIB_REQUIRED=2.0.1
+  GTK_REQUIRED=2.0.1
+  GTK_MODULES="gtk+-2.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED"
+
+  dnl Check if --with-pkg-config-prog has been given.
+  if test "X${with_pkg_config_prog}" != X; then
+    PKG_CONFIG="${with_pkg_config_prog}"
+  fi
+  dnl Checks for libraries.
+  PKG_CHECK_MODULES(GTK, $GTK_MODULES)
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+  C_SWITCH_X_SITE="$C_SWITCH_X_SITE $GTK_CFLAGS"
+  HAVE_GTK=yes
+  AC_DEFINE(HAVE_GTK, 1, [Define to 1 if using GTK.])
+  USE_X_TOOLKIT=none
+
+  dnl  GTK scrollbars resembles toolkit scrollbars alot, so to avoid
+  dnl  a lot if #ifdef:s, say we have toolkit scrollbars.
+  with_toolkit_scroll_bars=yes
+fi
+
 dnl Do not put whitespace before the #include statements below.
 dnl Older compilers (eg sunos4 cc) choke on it.
 if test x"${USE_X_TOOLKIT}" = xmaybe; then
@@ -1903,7 +1996,7 @@
   fi
 fi
   
-dnl Use toolkit scroll bars if configured for X toolkit and either
+dnl Use toolkit scroll bars if configured for GTK or X toolkit and either
 dnl using Motif or Xaw3d is available, and unless
 dnl --with-toolkit-scroll-bars=no was specified.
 
@@ -1920,6 +2013,9 @@
       AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
       USE_TOOLKIT_SCROLL_BARS=yes
     fi
+  elif test "${HAVE_GTK}" = "yes"; then
+    AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
+    USE_TOOLKIT_SCROLL_BARS=yes
   fi
 fi
 
@@ -2745,6 +2841,13 @@
 ])dnl
 
 #### Report on what we decided to do.
+#### Report GTK as a toolkit, even if it doesn't use Xt.
+#### It makes printing result more understandable as using GTK sets
+#### toolkit_scroll_bars to yes by default.
+if test "${HAVE_GTK}" = "yes"; then
+  USE_X_TOOLKIT=GTK
+fi
+
 echo "
 Configured for \`${canonical}'.
 
--- a/man/ChangeLog	Sun Jan 19 20:03:42 2003 +0000
+++ b/man/ChangeLog	Sun Jan 19 21:50:03 2003 +0000
@@ -1,3 +1,10 @@
+2003-01-19  Jan D.  <jan.h.d@swipnet.se>
+
+	* xresources.texi (GTK resources): New node.
+	(GTK widget names): New node.
+	(GTK names in Emacs): New node.
+	(GTK styles): New node.
+
 2003-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
 	* gnus.texi: Do not use `path' in several locations.
--- a/man/xresources.texi	Sun Jan 19 20:03:42 2003 +0000
+++ b/man/xresources.texi	Sun Jan 19 21:50:03 2003 +0000
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1987,93,94,95,1997,2001 Free Software Foundation, Inc.
+@c Copyright (C) 1987,93,94,95,1997,2001,03 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node X Resources, Antinews, Command Arguments, Top
 @appendix X Options and Resources
@@ -18,6 +18,7 @@
 * Face Resources::      X resources for customizing faces.
 * Lucid Resources::     X resources for Lucid menus.
 * LessTif Resources::   X resources for LessTif and Motif menus.
+* GTK resources::       Resources for GTK widgets.
 @end menu
 
 @node Resources
@@ -520,3 +521,395 @@
 @item topShadowColor
 The color for the border shadow, on the top and the left.
 @end table
+
+
+@node GTK resources
+@appendixsec GTK resources
+@cindex GTK resources and customization
+@cindex resource files for GTK
+@cindex @file{~/.gtkrc-2.0} file
+@cindex @file{~/.emacs.d/gtkrc} file
+
+  If the Emacs installed at your site was built to use the GTK widget set,
+then the menu bar, scroll bar and the dialogs can be customized with
+the standard GTK @file{~/.gtkrc-2.0} file or with the Emacs specific
+@file{~/.emacs.d/gtkrc} file; note that these files are only for 
+customizing specific GTK widget features.  To customize Emacs font,
+background, faces etc., use the normal X resources, see @ref{Resources}.
+
+In these files you first defines a style and then how to apply that style
+to widgets (@pxref{GTK widget names}).  Here is an example of how to
+change the font for Emacs menus:
+
+@smallexample
+# This is a comment.
+style "menufont"
+@{
+  font_name = "helvetica bold 14"  # This is a Pango font name
+@}
+
+widget "*emacs-menuitem*" style "menufont"
+
+@end smallexample
+
+  There are some things you can set without using any style or widget name,
+which affect GTK as a whole.  Most of these are poorly documented, but can
+be found in the `Properties' section of the documentation page for
+@code{GtkSetting}, in the GTK document references below.
+
+One property of interest is @code{gtk-font-name} which sets the default
+font for GTK; you must use Pango font names (@pxref{GTK styles}).  A
+@file{~/.gtkrc-2.0} file that just sets a default font looks like this:
+
+@smallexample
+gtk-font-name = "courier 12"
+@end smallexample
+
+
+  If GTK at your site is installed under @var{prefix},
+the resource file syntax is fully described in the GTK API
+document 
+@file{@var{prefix}/share/gtk-doc/html/gtk/gtk-resource-files.html}.
+@var{prefix} is usually @file{/usr} or @file{/usr/local}.
+You can find the same document online at
+@uref{http://developer.gnome.org/doc/API/2.0/gtk/gtk-Resource-Files.html}.
+
+
+@menu
+* GTK widget names::      How widgets in GTK are named in general.
+* GTK names in Emacs::    GTK widget names in Emacs.
+* GTK styles::            What can be customized in a GTK widget.
+@end menu
+
+
+@node GTK widget names
+@appendixsubsec GTK widget names
+@cindex GTK widget names
+
+  Widgets are specified by widget class or by widget name. 
+The widget class is the type of the widget, for example @code{GtkMenuBar}.
+The widget name is the name given to a specific widget within a program.
+A widget always have a class but it is not mandatory to give a name to
+a widget.  Absolute names are sequences of widget names or
+widget classes, corresponding to hierarchies of widgets embedded within
+other widgets.  For example, if a @code{GtkWindow} contains a @code{GtkVBox}
+which in turn contains a @code{GtkMenuBar}, the absolute class name
+is @code{GtkWindow.GtkVBox.GtkMenuBar}.
+
+@noindent
+If the widgets are named ``top'', ``box'' and ``menubar'', the absolute
+widget name is @code{top.box.menubar},
+
+  When assigning a style to a widget, you can use the absolute class
+name or the absolute widget name.
+There are two commands:  @code{widget_class} will assign a style to
+widgets, matching only against the absolute class name.
+The command @code{widget} will match the absolute widget name,
+but if there is no name for a widget in the hierarchy, the class is matched.
+These commands require the absolute name and the style name to be
+within  double quotes.  These commands are written at the top level in a
+@file{~/.gtkrc-2.0} file, like this:
+
+@smallexample
+style "menufont"
+@{
+  font_name = "helvetica bold 14"
+@}
+
+widget "top.box.menubar" style "menufont"
+widget_class "GtkWindow.GtkVBox.GtkMenuBar" style "menufont"
+@end smallexample
+
+
+  Matching of absolute names is done with shell ``glob'' syntax, that is
+@samp{*} matches zero or more characters and @samp{?} matches one character.
+So the following would assign @code{base_style} to all widgets:
+
+@smallexample
+widget "*" style "base_style"
+@end smallexample
+
+  Given the absolute class name @code{GtkWindow.GtkVBox.GtkMenuBar}
+and the corresponding absolute widget name @code{top.box.menubar},
+the following all assign @code{my_style} to the menu bar:
+
+@smallexample
+widget_class "GtkWindow.GtkVBox.GtkMenuBar" style "my_style"
+widget_class "GtkWindow.*.GtkMenuBar" style "my_style"
+widget_class "*GtkMenuBar" style "my_style"
+widget "top.box.menubar" style "my_style"
+widget "*box*menubar" style "my_style"
+widget "*menubar" style "my_style"
+widget "*menu*" style "my_style"
+@end smallexample
+
+@node GTK names in Emacs
+@appendixsubsec GTK names in Emacs
+@cindex GTK widget names
+@cindex GTK widget classes
+
+  In Emacs the top level widget for a frame is a @code{GtkWindow} that
+contains a @code{GtkVBox}.  The @code{GtkVBox} contains the 
+@code{GtkMenuBar} and a @code{GtkFixed} widget.  
+The vertical scroll bars, @code{GtkVScrollbar},
+are contained in the @code{GtkFixed} widget.
+The text you write in Emacs is drawn in the @code{GtkFixed} widget.
+
+  Dialogs in Emacs are @code{GtkDialog} widgets.  The file dialog is a
+@code{GtkFileSelection} widget.
+
+@noindent
+To set a style for the menu bar using the absolute class name, use:
+
+@smallexample
+widget_class "GtkWindow.GtkVBox.GtkMenuBar" style "my_style"
+@end smallexample
+
+@noindent
+For the scroll bar, the absolute class name is:
+
+@smallexample
+widget_class 
+  "GtkWindow.GtkVBox.GtkFixed.GtkVScrollbar"
+     style "my_style"
+@end smallexample
+
+@noindent
+The names for the emacs widgets, and their classes, are:
+
+@multitable {@code{verticalScrollbar plus}} {@code{GtkFileSelection} and some}
+@item @code{emacs-filedialog}
+@tab @code{GtkFileSelection}
+@item @code{emacs-dialog}
+@tab @code{GtkDialog}
+@item @code{Emacs}
+@tab @code{GtkWindow}
+@item @code{pane}
+@tab @code{GtkVHbox}
+@item @code{emacs}
+@tab @code{GtkFixed}
+@item @code{menubar}
+@tab @code{GtkMenuBar}
+@item @code{verticalScrollbar}
+@tab @code{GtkVScrollbar}
+@item @code{emacs-menuitem}
+@tab anything in menus
+@end multitable
+
+@noindent
+Thus, for Emacs you can write the two examples above as:
+
+@smallexample
+widget "Emacs.pane.menubar" style "my_style"
+widget "Emacs.pane.emacs.verticalScrollbar" style "my_style"
+@end smallexample
+
+  GTK absolute names are quite strange when it comes to menus
+and dialogs.  The names do not start with @samp{Emacs}, as they are 
+free-standing windows and not contained (in the GTK sense) by the
+Emacs GtkWindow.  To customize the dialogs and menus, use wildcards like this:
+
+@smallexample
+widget "*emacs-dialog*" style "my_dialog_style"
+widget "*emacs-filedialog* style "my_file_style"
+widget "*emacs-menuitem* style "my_menu_style"
+@end smallexample
+
+  An alternative is to put customization into @file{~/.emacs.d/gtkrc}.
+This file is only read by Emacs, so anything in @file{~/.emacs.d/gtkrc}
+affects Emacs but leaves other applications unaffected.
+For example, the drop down menu in the file dialog can not
+be customized by any absolute widget name, only by an absolute
+class name.  This is so because the widgets in the drop down menu does not 
+have names and the menu is not contained in the Emacs GtkWindow.
+To have all menus in Emacs look the same, use this in @file{~/.emacs.d/gtkrc}:
+
+@smallexample
+widget_class "*Menu*" style "my_menu_style"
+@end smallexample
+
+@node GTK styles
+@appendixsubsec GTK styles
+@cindex GTK styles
+
+  In a GTK style you specify the appearance widgets shall have.  You
+can specify foreground and background color, background pixmap and font.
+The edit widget (where you edit the text) in Emacs is a GTK widget,
+but trying to specify a style for the edit widget will have no effect.
+This is so that Emacs compiled for GTK is compatible with Emacs compiled
+for other X toolkits.  The settings for foreground, background and font
+for the edit widget is taken from the X resources; @pxref{Resources}.
+Here is an example of two style declarations, ``default'' and ``ruler'':
+
+@smallexample
+
+pixmap_path "/usr/share/pixmaps:/usr/include/X11/pixmaps"
+
+style "default"
+@{
+  font_name = "helvetica 12"
+
+  bg[NORMAL] = @{ 0.83, 0.80, 0.73 @}
+  bg[SELECTED] = @{ 0.0, 0.55, 0.55 @}
+  bg[INSENSITIVE] = @{ 0.77, 0.77, 0.66 @}
+  bg[ACTIVE] = @{ 0.0, 0.55, 0.55 @}
+  bg[PRELIGHT] = @{ 0.0, 0.55, 0.55 @}
+
+  fg[NORMAL] = "black"
+  fg[SELECTED] = @{ 0.9, 0.9, 0.9 @}
+  fg[ACTIVE] = "black"
+  fg[PRELIGHT] = @{ 0.9, 0.9, 0.9 @}
+
+  base[INSENSITIVE] = "#777766"
+  text[INSENSITIVE] = @{ 0.60, 0.65, 0.57 @}
+
+  bg_pixmap[NORMAL] = "background.xpm"
+  bg_pixmap[INSENSITIVE] = "background.xpm"
+  bg_pixmap[ACTIVE] = "background.xpm"
+  bg_pixmap[PRELIGHT] = "<none>" 
+
+@}
+
+style "ruler" = "default"
+@{
+  font_name = "helvetica 8"
+@}
+
+@end smallexample
+
+  The style ``ruler'' inherits from ``default''.  This way you can build
+on existing styles.  The syntax for fonts and colors is described below.
+
+  As this example shows, it is possible to specify several values
+for foreground and background depending on which state the widget has.
+The possible states are
+@table @code
+@item NORMAL
+This is the default state for widgets.
+@item ACTIVE
+This is the state for a widget that is ready to do something.  It is
+also for the trough of a scroll bar, i.e.  @code{bg[ACTIVE] = "red"} 
+sets the scroll bar trough to red.  Buttons that have been pressed but
+not released yet (``armed'') are in this state.
+@item PRELIGHT
+This is the state when widgets that can be manipulated have the mouse
+pointer over them.  For example when the mouse is over the thumb in the
+scroll bar or over a menu item.  When the mouse is over a button that
+is not pressed, the button is in this state.
+@item SELECTED
+This is the state when some data has been selected by the user.  It can
+be selected text or items selected in a list.
+There is no place in Emacs where this setting has any effect.
+@item INSENSITIVE
+This is the state for widgets that are visible, but they can not be
+manipulated like they normally can.  For example, buttons that can't be
+pressed and menu items that can't be selected.
+Text for menu items that are not available can be set to yellow with
+@code{fg[INSENSITIVE] = "yellow"}.
+@end table
+
+Here are the things that can go in a style declaration:
+
+@table @code
+@item bg[@var{state}] = @var{color}
+This is the background color widgets use.  This background is not used for
+editable text, use @code{base} for that.
+
+@item base[@var{state}] = @var{color}
+This is the background color for editable text.
+In Emacs, this color is used for the background of the text fields in the 
+file dialog.
+
+@item bg_pixmap[@var{state}] = "@var{pixmap}"
+You can specify a pixmap to be used instead of the background color.
+@var{pixmap} is a file name.  GTK can use a number of file formats,
+including XPM, XBM, GIF, JPEG and PNG.  If you want a widget to use the same
+pixmap as its parent, use @samp{<parent>}.  If you don't want any
+pixmap use @samp{<none>}.  Using @samp{<none>} can be useful
+if your style inherits a style that does specify a pixmap.
+
+  GTK looks for the pixmap in directories specified in @code{pixmap_path}.
+It is not possible to refer to a file by its absolute path name.
+@code{pixmap_path} is a colon-separated list of directories within double
+quotes, specified at the top level in a @file{gtkrc} file (i.e. not inside
+a style definition; see example above):
+
+@smallexample
+pixmap_path "/usr/share/pixmaps:/usr/include/X11/pixmaps"
+@end smallexample
+
+@item fg[@var{state}] = @var{color}
+This is the foreground color widgets use.  This is the color
+of text in menus and buttons.  It is also the color for the arrows in the
+scroll bar.  For editable text, use @code{text}.
+
+@item text[@var{state}] = @var{color}
+This is the color for editable text.  In Emacs, this color is used for the 
+text fields in the file dialog.
+
+@item font_name = "@var{font}"
+This is the font a widget shall use.  @var{font} is a Pango font name,
+for example ``Sans Italic 10'', ``Helvetica Bold 12'', ``Courier 14'',
+``Times 18''.  See below for exact syntax.  The names are case insensitive.
+@end table
+
+  Colors are specified in three ways, a name, a hexadecimal form or
+an RGB triplet.
+
+@noindent
+A color name is written within double quotes, for example @code{"red"}.
+
+@noindent
+A hexadecimal form is written within double quotes.  There are four forms,
+@code{#rrrrggggbbbb}, @code{#rrrgggbbb}, 
+@code{#rrggbb}, or @code{#rgb}.  In each of these r, g and b are hex digits.
+
+@noindent
+An RGB triplet looks like @code{@{ r, g, b @}}, where r, g and b are either
+integers in the range 0-65535 or floats in the range 0.0-1.0.
+
+  Pango font names have the form ``@var{family-list} @var{style-options}
+@var{size}''.
+@cindex Pango font name
+@noindent
+@var{family-list} is a comma separated list of font families optionally
+terminated by a comma.  This way you can specify several families and the
+first one found will be used.  @var{family} corresponds to the second part in
+an X font name, for example in
+
+@smallexample
+-adobe-times-medium-r-normal--12-120-75-75-p-64-iso10646-1
+@end smallexample
+
+@noindent
+the family name is ``times''.
+
+@noindent
+@var{style-options} is a whitespace separated list of words where each word
+is a style, variant, weight, or stretch.  The default value for all of
+these is @code{normal}.
+
+@noindent
+A `style' corresponds to the fourth part of an X font name.  In X font
+names it is the character ``r'', ``i'' or ``o''; in Pango font names the
+corresponding values are @code{normal}, @code{italic}, or @code{oblique}.
+
+@noindent
+A `variant' is either @code{normal} or @code{small-caps}.
+Small caps is a font with the lower case characters replaced by
+smaller variants of the capital characters.
+
+@noindent
+Weight describes the ``boldness'' of a font.  It corresponds to the third
+part of an X font name.  It is one of @code{ultra-light}, @code{light},
+@code{normal}, @code{bold}, @code{ultra-bold}, or @code{heavy}.
+
+@noindent
+Stretch gives the width of the font relative to other designs within a
+family.  It corresponds to the fifth part of an X font name.  It is one of
+@code{ultra-condensed}, @code{extra-condensed}, @code{condensed},
+@code{semi-condensed}, @code{normal}, @code{semi-expanded},
+@code{expanded}, @code{extra-expanded}, or @code{ultra-expanded}.
+
+@noindent
+@var{size} is a decimal number that describes the font size in points.
--- a/src/ChangeLog	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/ChangeLog	Sun Jan 19 21:50:03 2003 +0000
@@ -1,3 +1,113 @@
+2003-01-19  Jan D.  <jan.h.d@swipnet.se>
+
+	* Makefile.in (XOBJ): Add gtkutil.o if USE_GTK
+	(gtkutil.o): New file.
+	(TOOLKIT_DEFINES): Set to -DUSE_GTK if HAVE_GTK.
+	(LIBW): Set to @GTK_LIBS@ if USE_GTK.
+
+	* gtkutil.c: New file for GTK version.
+
+	* gtkutil.h: New file for GTK version.
+
+	* xterm.h: Add xt_or_gtk_widget.
+	Include gtk files for USE_GTK.
+	(struct x_output): Add toolbar_height.
+	(struct x_output): Add GTK widgets and Gdk size_hints.
+	(GTK_WIDGET_TO_X_WIN, FRAME_GTK_OUTER_WIDGET, FRAME_GTK_WIDGET)
+	(FRAME_OUTER_WINDOW): New macros for USE_GTK.
+	(FRAME_OUTER_TO_INNER_DIFF_Y): Add FRAME_TOOLBAR_HEIGHT to calculation.
+
+	* xterm.c: Include gtkutil.h for USE_GTK.
+	Declare extern void free_frame_menubar for USE_GTK.
+	(note_mouse_highlight): Check popup_activated for USE_GTK.
+	(xt_action_hook): Don't compile if USE_GTK.
+	(x_scroll_bar_to_input_event): Use CurrentTime for USE_GTK.
+	(xg_scroll_callback): New function.
+	(x_create_toolkit_scroll_bar): Call xg_create_scroll_bar for USE_GTK.
+	(x_set_toolkit_scroll_bar_thumb): Call xg_set_toolkit_scroll_bar_thumb
+	for USE_GTK.
+	(x_scroll_bar_create): Call xg_update_scrollbar_pos and
+	xg_show_scroll_bar for USE_GTK.
+	(x_scroll_bar_remove): Call xg_remove_scroll_bar for USE_GTK.
+	(XTset_vertical_scroll_bar): Call xg_update_scrollbar_pos for USE_GTK.
+	(event_handler_gdk): New function for USE_GTK.
+	(handle_one_xevent): Call xg_resize_widgets for USE_GTK.
+	(handle_one_xevent): Make sure widget is mapped before
+	calling x_real_positions for USE_GTK.
+	(XTread_socket): Add GTK event loop for USE_GTK.
+	(x_set_window_size): Call xg_frame_set_char_size for USE_GTK.
+	(x_make_frame_visible): Call gtk_widget_show_all for USE_GTK.
+	(x_make_frame_invisible): Call gtk_widget_hide for USE_GTK.
+	(x_iconify_frame): Add code for USE_GTK.
+	(x_free_frame_resources): Call gtk_widget_destroy for USE_GTK.
+	(x_wm_set_size_hint): Only compile if not USE_GTK.  GTK version
+	is in gtkutil.c.
+	(x_term_init): Add initialization for GTK.
+	(syms_of_xterm): Set Vx_toolkit_scroll_bars for USE_GTK.
+
+	* xmenu.c: Include gtkutil.h for USE_GTK.
+	(Fx_popup_menu): Use current position if x and y is NIL.
+	(single_menu_item, single_menu_item, Fx_popup_dialog): Check
+	for USE_GTK.
+	(popup_widget_loop): New function for USE_GTK.
+	(x_activate_menubar): Add code for USE_GTK.
+	(popup_activate_callback, popup_deactivate_callback)
+	(menu_highlight_callback, menubar_selection_callback): USE_GTK versions
+	added.
+	(update_frame_menubar): Call xg_update_frame_menubar for USE_GTK.
+	(set_frame_menubar): Call xg_modify_menubar_widgets for USE_GTK.
+	(free_frame_menubar): Only compile if not USE_GTK.  GTK version
+	is in gtkutil.c.
+	(popup_selection_callback): New version for USE_GTK.
+	(create_and_show_popup_menu): New fuction, one USE_GTK version and
+ 	one USE_X_TOOLKIT version.
+	(xmenu_show): Call create_and_show_popup_menu.
+	(dialog_selection_callback): New version for USE_GTK.
+	(create_and_show_dialog): New fuction, one USE_GTK version and
+ 	one USE_X_TOOLKIT version.
+	(xdialog_show): Call create_and_show_dialog.
+
+	* xfns.c: Include gtkutil for USE_GTK.
+	(x_window_to_frame, x_any_window_to_frame)
+	(x_non_menubar_window_to_frame, x_menubar_window_to_frame)
+	(x_top_window_to_frame): Add code for USE_GTK.
+	(x_set_background_color): Call xg_set_background_color for GTK.
+	(x_set_menu_bar_lines): Check for USE_GTK.
+	(x_set_tool_bar_lines): Call update_frame_tool_bar for USE_GTK.
+	(x_set_name, x_set_title): Call gtk_window_set_title for USE_GTK.
+	(x_window): Call xg_create_frame_widgets for USE_GTK.
+	(Fx_create_frame): Check for USE_GTK
+	(Fx_file_dialog): New implementation for USE_GTK.
+	
+
+	* xdisp.c: Add check for USE_GTK for extern void set_frame_menubar.
+	(update_menu_bar): Add check for USE_GTK.
+	(update_tool_bar): Add check for USE_GTK and external tool bar.
+	(redisplay_tool_bar): Add check for USE_GTK and external tool bar.
+	(redisplay_internal): Add check for USE_GTK and popup_activated.
+	(redisplay_window): Add check for USE_GTK and FRAME_EXTERNAL_MENU_BAR.
+	(redisplay_window): Add check for USE_GTK and FRAME_EXTERNAL_TOOL_BAR.
+	(display_menu_bar): Add check for USE_GTK
+
+	* lisp.h: Declare Vx_resource_name extern.
+
+	* keyboard.c (kbd_buffer_get_event):  Check MENU_BAR_ACTIVATE_EVENT
+	for USE_GTK.
+	(make_lispy_event): Check MENU_BAR_EVENT for USE_GTK.
+
+	* frame.h (struct frame): Add external_tool_bar.  Check for USE_GTK.
+	(FRAME_EXTERNAL_TOOL_BAR): New macro.
+	(FRAME_EXTERNAL_MENU_BAR): Check for USE_GTK.
+
+	* fileio.c (Fread_file_name): Add check for USE_GTK.
+
+	* dispnew.c (adjust_frame_glyphs_for_window_redisplay): Add
+	check for USE_GTK.
+
+	* config.in: Added HAVE_GTK
+
+	* alloc.c (Fgarbage_collect): Call xg_mark_data for GTK.
+
 2003-01-18  Stefan Monnier  <monnier@cs.yale.edu>
 
 	* charset.h (Funibyte_char_to_multibyte): Export.
--- a/src/Makefile.in	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/Makefile.in	Sun Jan 19 21:50:03 2003 +0000
@@ -252,12 +252,19 @@
 #define C_SWITCH_ASM
 #endif
 
+#if HAVE_GTK
+#define USE_GTK
+TOOLKIT_DEFINES = -DUSE_GTK
+#endif
+
 #ifdef USE_X_TOOLKIT
 #define USE_@X_TOOLKIT_TYPE@
 TOOLKIT_DEFINES = -DUSE_@X_TOOLKIT_TYPE@
 #else
+#ifndef USE_GTK
 TOOLKIT_DEFINES =
 #endif
+#endif
 
 /* DO NOT use -R.  There is a special hack described in lastfile.c
    which is used instead.  Some initialized data areas are modified
@@ -300,7 +307,12 @@
 #ifdef HAVE_MENUS
 
 /* Include xmenu.o in the list of X object files.  */
+
+#ifdef USE_GTK
+XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o gtkutil.o
+#else
 XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o
+#endif
 
 /* The X Menu stuff is present in the X10 distribution, but missing
    from X11.  If we have X10, just use the installed library;
@@ -372,10 +384,17 @@
 #endif /* not LIBXT_STATIC */
 
 #else /* not USE_X_TOOLKIT */
+
+#ifdef USE_GTK
+LIBW=@GTK_LIBS@
+OLDXMENU=
+LIBXMENU=
+#endif /* USE_GTK */
+
 #ifdef HAVE_X_SM
-LIBXT=-lSM -lICE
+LIBXT=$(LIBW) -lSM -lICE
 #else
-LIBXT=
+LIBXT=$(LIBW)
 #endif
 #endif /* not USE_X_TOOLKIT */
 
@@ -1150,18 +1169,21 @@
    window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h $(config_h)
 xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
    $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
-   charset.h $(config_h)
+   charset.h gtkutil.h $(config_h)
 xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \
    keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \
-   msdos.h $(config_h)
+   gtkutil.h msdos.h $(config_h)
 xterm.o: xterm.c xterm.h termhooks.h termopts.h termchar.h window.h buffer.h \
   dispextern.h frame.h disptab.h blockinput.h atimer.h systime.h syssignal.h \
   keyboard.h gnu.h charset.h ccl.h fontset.h composite.h \
-  coding.h process.h $(config_h)
+  coding.h process.h gtkutil.h $(config_h)
 xselect.o: xselect.c process.h dispextern.h frame.h xterm.h blockinput.h \
   charset.h coding.h ccl.h buffer.h atimer.h systime.h $(config_h)
 xrdb.o: xrdb.c $(config_h) epaths.h
 xsmfns.o: xsmfns.c $(config_h) systime.h sysselect.h termhooks.h
+gtkutil.o:  gtkutil.c gtkutil.h xterm.h lisp.h frame.h $(config_h) \
+  blockinput.h window.h atimer.h termhooks.h
+
 hftctl.o: hftctl.c $(config_h)
 sound.o: sound.c dispextern.h $(config_h)
 atimer.o: atimer.c atimer.h systime.h $(config_h)
--- a/src/alloc.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/alloc.c	Sun Jan 19 21:50:03 2003 +0000
@@ -4266,6 +4266,13 @@
   mark_stack ();
 #endif
 
+#ifdef USE_GTK
+  {
+    extern void xg_mark_data ();
+    xg_mark_data ();
+  }
+#endif
+
   gc_sweep ();
 
   /* Clear the mark bits that we set in certain root slots.  */
--- a/src/config.in	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/config.in	Sun Jan 19 21:50:03 2003 +0000
@@ -205,6 +205,9 @@
 /* Define to 1 if you have the `grantpt' function. */
 #undef HAVE_GRANTPT
 
+/* Define to 1 if using GTK. */
+#undef HAVE_GTK
+
 /* Define to 1 if netdb.h declares h_errno. */
 #undef HAVE_H_ERRNO
 
--- a/src/dispnew.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/dispnew.c	Sun Jan 19 21:50:03 2003 +0000
@@ -2371,7 +2371,7 @@
 
   /* Allocate/ reallocate matrices of the dummy window used to display
      the menu bar under X when no X toolkit support is available.  */
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   {
     /* Allocate a dummy window if not already done.  */
     if (NILP (f->menu_bar_window))
@@ -2394,6 +2394,7 @@
   }
 #endif /* not USE_X_TOOLKIT */
 
+#ifndef USE_GTK
   /* Allocate/ reallocate matrices of the tool bar window.  If we
      don't have a tool bar window yet, make one.  */
   if (NILP (f->tool_bar_window))
@@ -2411,6 +2412,7 @@
   XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
   XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
   allocate_matrices_for_window_redisplay (w);
+#endif
 }
 
 
--- a/src/fileio.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/fileio.c	Sun Jan 19 21:50:03 2003 +0000
@@ -6116,8 +6116,8 @@
 	    (NILP (predicate) ? Qfile_exists_p : predicate));
 
   GCPRO2 (insdef, default_filename);
-
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI)
+  
+#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
       && use_dialog_box
       && have_menus_p ())
--- a/src/frame.h	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/frame.h	Sun Jan 19 21:50:03 2003 +0000
@@ -215,6 +215,11 @@
      be used for output.  */
   unsigned glyphs_initialized_p : 1;
 
+#if defined (USE_GTK)
+  /* Nonzero means using a tool bar that comes from the toolkit.  */
+  int external_tool_bar;
+#endif
+
   /* Margin at the top of the frame.  Used to display the tool-bar.  */
   int tool_bar_lines;
 
@@ -270,7 +275,8 @@
   /* Number of lines of menu bar.  */
   int menu_bar_lines;
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
   /* Nonzero means using a menu bar that comes from the X toolkit.  */
   int external_menu_bar;
 #endif
@@ -457,10 +463,19 @@
    These lines are counted in FRAME_HEIGHT.  */
 #define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines
 
+/* Nonzero if this frame should display a tool bar
+   in a way that does not use any text lines.  */
+#if defined (USE_GTK)
+#define FRAME_EXTERNAL_TOOL_BAR(f) (f)->external_tool_bar
+#else
+#define FRAME_EXTERNAL_TOOL_BAR(f) 0
+#endif
+
 /* Number of lines of frame F used for the tool-bar.  */
 
 #define FRAME_TOOL_BAR_LINES(f) (f)->tool_bar_lines
 
+
 /* Lines above the top-most window in frame F.  */
 
 #define FRAME_TOP_MARGIN(F) \
@@ -468,7 +483,8 @@
 
 /* Nonzero if this frame should display a menu bar
    in a way that does not use any text lines.  */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
 #define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
 #else
 #define FRAME_EXTERNAL_MENU_BAR(f) 0
--- a/src/keyboard.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/keyboard.c	Sun Jan 19 21:50:03 2003 +0000
@@ -3878,7 +3878,8 @@
 	  XSETBUFFER (obj, current_buffer);
 	  kbd_fetch_ptr = event + 1;
 	}
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
       else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
 	{
 	  kbd_fetch_ptr = event + 1;
@@ -3985,7 +3986,8 @@
 	    {
 	      obj = make_lispy_event (event);
 	      
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
+    || defined (USE_GTK)
 	      /* If this was a menu selection, then set the flag to inhibit
 		 writing to last_nonmenu_event.  Don't do this if the event
 		 we're returning is (menu-bar), though; that indicates the
@@ -5048,7 +5050,7 @@
  	    pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
 	 			   &column, &row, NULL, 1);
 
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 	    /* In the non-toolkit version, clicks on the menu bar
 	       are ordinary button events in the event buffer.
 	       Distinguish them, and invoke the menu.
@@ -5100,7 +5102,7 @@
 
 		return Fcons (item, Fcons (position, Qnil));
 	      }
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
 
 	    /* Set `window' to the window under frame pixel coordinates
 	       event->x/event->y.  */
@@ -5589,7 +5591,8 @@
       }
 #endif /* HAVE_MOUSE */
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
     case MENU_BAR_EVENT:
       if (EQ (event->arg, event->frame_or_window))
 	/* This is the prefix key.  We translate this to
--- a/src/lisp.h	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/lisp.h	Sun Jan 19 21:50:03 2003 +0000
@@ -3136,6 +3136,7 @@
 extern void syms_of_xfns P_ ((void));
 extern void init_xfns P_ ((void));
 extern Lisp_Object Vx_resource_name;
+extern Lisp_Object Vx_resource_class;
 EXFUN (Fxw_display_color_p, 1);
 EXFUN (Fx_file_dialog, 4);
 #endif /* HAVE_X_WINDOWS */
--- a/src/xdisp.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/xdisp.c	Sun Jan 19 21:50:03 2003 +0000
@@ -200,7 +200,8 @@
 
 #define INFINITY 10000000
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
 extern void set_frame_menubar P_ ((struct frame *f, int, int));
 extern int pending_menu_activation;
 #endif
@@ -7518,7 +7519,8 @@
 
   if (FRAME_WINDOW_P (f)
       ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
       FRAME_EXTERNAL_MENU_BAR (f)
 #else
       FRAME_MENU_BAR_LINES (f) > 0
@@ -7569,7 +7571,8 @@
 	  FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
 
 	  /* Redisplay the menu bar in case we changed it.  */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
 	  if (FRAME_WINDOW_P (f)
 #if defined (MAC_OS)
               /* All frames on Mac OS share the same menubar.  So only the
@@ -7582,11 +7585,11 @@
 	    /* On a terminal screen, the menu bar is an ordinary screen
 	       line, and this makes it get updated.  */
 	    w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
+#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
 	  /* In the non-toolkit version, the menu bar is an ordinary screen
 	     line, and this makes it get updated.  */
 	  w->update_mode_line = Qt;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
+#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
 
 	  unbind_to (count, Qnil);
 	  set_buffer_internal_1 (prev);
@@ -7612,8 +7615,14 @@
      struct frame *f;
      int save_match_data;
 {
-  if (WINDOWP (f->tool_bar_window)
-      && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
+#ifdef USE_GTK
+  int do_update = FRAME_EXTERNAL_TOOL_BAR(f);
+#else
+  int do_update = WINDOWP (f->tool_bar_window)
+    && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0;
+#endif
+
+  if (do_update)
     {
       Lisp_Object window;
       struct window *w;
@@ -7991,6 +8000,12 @@
   struct it it;
   struct glyph_row *row;
   int change_height_p = 0;
+  
+#ifdef USE_GTK
+  if (FRAME_EXTERNAL_TOOL_BAR(f))
+    update_frame_tool_bar (f);
+  return 0;
+#endif
 
   /* If frame hasn't a tool-bar window or if it is zero-height, don't
      do anything.  This means you must start with tool-bar-lines
@@ -7998,7 +8013,7 @@
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-	  XFASTINT (w->height) == 0))
+          XFASTINT (w->height) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
@@ -8550,7 +8565,7 @@
 	return;
     }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (popup_activated ())
     return;
 #endif
@@ -10785,10 +10800,12 @@
       && EQ (FRAME_SELECTED_WINDOW (f), window))
     {
       int redisplay_menu_p = 0;
+      int redisplay_tool_bar_p = 0;
 
       if (FRAME_WINDOW_P (f))
 	{
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (USE_GTK)
 	  redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
 	  redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
@@ -10801,10 +10818,17 @@
         display_menu_bar (w);
 
 #ifdef HAVE_WINDOW_SYSTEM
-      if (WINDOWP (f->tool_bar_window)
-	  && (FRAME_TOOL_BAR_LINES (f) > 0
-	      || auto_resize_tool_bars_p))
-	redisplay_tool_bar (f);
+#ifdef USE_GTK
+      redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
+#else
+      redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
+        && (FRAME_TOOL_BAR_LINES (f) > 0
+            || auto_resize_tool_bars_p);
+      
+#endif
+
+      if (redisplay_tool_bar_p)
+        redisplay_tool_bar (f);
 #endif
     }
 
@@ -13535,7 +13559,7 @@
   if (!NILP (Vwindow_system))
     return;
 #endif
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (FRAME_X_P (f))
     return;
 #endif
--- a/src/xfns.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/xfns.c	Sun Jan 19 21:50:03 2003 +0000
@@ -65,6 +65,10 @@
 #include "[.bitmaps]gray.xbm"
 #endif
 
+#ifdef USE_GTK
+#include "gtkutil.h"
+#endif
+
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
 
@@ -284,11 +288,11 @@
      Lisp_Object frame;
 {
   struct x_display_info *dpyinfo = NULL;
-
+  
   if (NILP (frame))
     {
       struct frame *sf = XFRAME (selected_frame);
-
+      
       if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
 	dpyinfo = FRAME_X_DISPLAY_INFO (sf);
       else if (x_display_list != 0)
@@ -332,7 +336,7 @@
       if (f->output_data.x->hourglass_window == wdesc)
 	return f;
 #ifdef USE_X_TOOLKIT
-      if ((f->output_data.x->edit_widget
+      if ((f->output_data.x->edit_widget 
 	   && XtWindow (f->output_data.x->edit_widget) == wdesc)
 	  /* A tooltip frame?  */
 	  || (!f->output_data.x->edit_widget
@@ -340,6 +344,15 @@
           || f->output_data.x->icon_desc == wdesc)
         return f;
 #else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+      if (f->output_data.x->edit_widget)
+      {
+        GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+        struct x_output *x = f->output_data.x;
+        if (gwdesc != 0 && gwdesc == x->edit_widget)
+          return f;
+      }
+#endif /* USE_GTK */
       if (FRAME_X_WINDOW (f) == wdesc
           || f->output_data.x->icon_desc == wdesc)
         return f;
@@ -348,7 +361,7 @@
   return 0;
 }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 /* Like x_window_to_frame but also compares the window with the widget's
    windows.  */
 
@@ -367,7 +380,7 @@
       frame = XCAR (tail);
       if (!GC_FRAMEP (frame))
         continue;
-
+      
       f = XFRAME (frame);
       if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
 	{
@@ -377,20 +390,30 @@
 	    found = f;
 	  else if (x->widget)
 	    {
-	      if (wdesc == XtWindow (x->widget)
-		  || wdesc == XtWindow (x->column_widget)
+#ifdef USE_GTK
+              GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+              if (gwdesc != 0
+                  && (gwdesc == x->widget
+                      || gwdesc == x->edit_widget
+                      || gwdesc == x->vbox_widget
+                      || gwdesc == x->menubar_widget))
+                found = f;
+#else
+	      if (wdesc == XtWindow (x->widget) 
+		  || wdesc == XtWindow (x->column_widget) 
 		  || wdesc == XtWindow (x->edit_widget))
 		found = f;
 	      /* Match if the window is this frame's menubar.  */
 	      else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
 		found = f;
+#endif
 	    }
 	  else if (FRAME_X_WINDOW (f) == wdesc)
 	    /* A tooltip frame.  */
 	    found = f;
 	}
     }
-
+  
   return found;
 }
 
@@ -419,10 +442,19 @@
 	return f;
       else if (x->widget)
 	{
-	  if (wdesc == XtWindow (x->widget)
-	      || wdesc == XtWindow (x->column_widget)
+#ifdef USE_GTK
+          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          if (gwdesc != 0
+              && (gwdesc == x->widget
+                  || gwdesc == x->edit_widget
+                  || gwdesc == x->vbox_widget))
+            return f;
+#else
+	  if (wdesc == XtWindow (x->widget) 
+	      || wdesc == XtWindow (x->column_widget) 
 	      || wdesc == XtWindow (x->edit_widget))
 	    return f;
+#endif
 	}
       else if (FRAME_X_WINDOW (f) == wdesc)
 	/* A tooltip frame.  */
@@ -452,9 +484,25 @@
 	continue;
       x = f->output_data.x;
       /* Match if the window is this frame's menubar.  */
+#ifdef USE_GTK
+      if (x->menubar_widget)
+        {
+          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          int found = 0;
+          
+          BLOCK_INPUT;
+          if (gwdesc != 0
+              && (gwdesc == x->menubar_widget
+                  || gtk_widget_get_parent (gwdesc) == x->menubar_widget))
+            found = 1;
+          UNBLOCK_INPUT;
+          if (found) return f;
+        }
+#else
       if (x->menubar_widget
 	  && lw_window_is_in_menubar (wdesc, x->menubar_widget))
 	return f;
+#endif
     }
   return 0;
 }
@@ -484,16 +532,22 @@
       if (x->widget)
 	{
 	  /* This frame matches if the window is its topmost widget.  */
+#ifdef USE_GTK
+          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          if (gwdesc == x->widget)
+            return f;
+#else
 	  if (wdesc == XtWindow (x->widget))
 	    return f;
 #if 0 /* I don't know why it did this,
 	 but it seems logically wrong,
 	 and it causes trouble for MapNotify events.  */
 	  /* Match if the window is this frame's menubar.  */
-	  if (x->menubar_widget
+	  if (x->menubar_widget 
 	      && wdesc == XtWindow (x->menubar_widget))
 	    return f;
 #endif
+#endif
 	}
       else if (FRAME_X_WINDOW (f) == wdesc)
 	/* Tooltip frame.  */
@@ -501,7 +555,7 @@
     }
   return 0;
 }
-#endif /* USE_X_TOOLKIT */
+#endif /* USE_X_TOOLKIT || USE_GTK */
 
 
 
@@ -806,7 +860,7 @@
   {"right-fringe",		x_set_fringe_width},
   {"wait-for-wm",		x_set_wait_for_wm},
   {"fullscreen",                x_set_fullscreen},
-
+  
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -925,7 +979,7 @@
      cursor_color) are dependent upon them.  */
   /* Process default font as well, since fringe widths depends on it.  */
   /* Also, process fullscreen, width and height depend upon that */
-  for (p = 0; p < i; p++)
+  for (p = 0; p < i; p++) 
     {
       Lisp_Object prop, val;
 
@@ -940,7 +994,7 @@
 
 	  old_value = get_frame_param (f, prop);
  	  fullscreen_is_being_set |= EQ (prop, Qfullscreen);
-
+	  
 	  if (NILP (Fequal (val, old_value)))
 	    {
 	      store_frame_param (f, prop, val);
@@ -1040,11 +1094,11 @@
          position.  Resize of the frame is taken care of in the code after
          this if-statement. */
       int new_left, new_top;
-
+      
       x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
       x_fullscreen_move (f, new_top, new_left);
     }
-
+  
   /* Don't set these parameters unless they've been explicitly
      specified.  The window might be mapped or resized while we're in
      this function, and we don't want to override that unless the lisp
@@ -1188,12 +1242,12 @@
 
       win = wm_window;
     }
-
+    
   if (! had_errors)
     {
       int ign;
       Window child, rootw;
-
+          
       /* Get the real coordinates for the WM window upper left corner */
       XGetGeometry (FRAME_X_DISPLAY (f), win,
                     &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
@@ -1232,23 +1286,23 @@
                                  /* From-window, to-window.  */
                                  FRAME_X_DISPLAY_INFO (f)->root_window,
                                  FRAME_OUTER_WINDOW (f),
-
+                                     
                                  /* From-position, to-position.  */
                                  real_x, real_y, &outer_x, &outer_y,
-
+                         
                                  /* Child of win.  */
                                  &child);
     }
 
       had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
     }
-
+      
   x_uncatch_errors (FRAME_X_DISPLAY (f), count);
-
+      
   UNBLOCK_INPUT;
 
   if (had_errors) return;
-
+      
   f->output_data.x->x_pixels_diff = -win_x;
   f->output_data.x->y_pixels_diff = -win_y;
   f->output_data.x->x_pixels_outer_diff = -outer_x;
@@ -1508,7 +1562,7 @@
   if (FRAME_X_WINDOW (f) != 0)
     {
       Display *dpy = FRAME_X_DISPLAY (f);
-
+      
       BLOCK_INPUT;
       XSetForeground (dpy, x->normal_gc, fg);
       XSetBackground (dpy, x->reverse_gc, fg);
@@ -1519,15 +1573,15 @@
 	  x->cursor_pixel = x_copy_color (f, fg);
 	  XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
 	}
-
+      
       UNBLOCK_INPUT;
-
+      
       update_face_from_frame_parameter (f, Qforeground_color, arg);
-
+      
       if (FRAME_VISIBLE_P (f))
         redraw_frame (f);
     }
-
+      
   unload_color (f, old_fg);
 }
 
@@ -1546,13 +1600,17 @@
   if (FRAME_X_WINDOW (f) != 0)
     {
       Display *dpy = FRAME_X_DISPLAY (f);
-
+      
       BLOCK_INPUT;
       XSetBackground (dpy, x->normal_gc, bg);
       XSetForeground (dpy, x->reverse_gc, bg);
       XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
       XSetForeground (dpy, x->cursor_gc, bg);
 
+#ifdef USE_GTK
+      xg_set_background_color (f, bg);
+#endif
+
 #ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
 				   toolkit scroll bars.  */
       {
@@ -1631,7 +1689,7 @@
   else
     hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
   x_check_errors (dpy, "bad hourglass pointer cursor: %s");
-
+  
   x_check_errors (dpy, "bad nontext pointer cursor: %s");
   if (!NILP (Vx_mode_pointer_shape))
     {
@@ -1672,7 +1730,7 @@
     x_query_color (f, &fore_color);
     back_color.pixel = mask_color;
     x_query_color (f, &back_color);
-
+    
     XRecolorCursor (dpy, cursor, &fore_color, &back_color);
     XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
     XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
@@ -1703,7 +1761,7 @@
       && x->modeline_cursor != 0)
     XFreeCursor (dpy, f->output_data.x->modeline_cursor);
   x->modeline_cursor = mode_cursor;
-
+  
   if (cross_cursor != x->cross_cursor
       && x->cross_cursor != 0)
     XFreeCursor (dpy, x->cross_cursor);
@@ -1737,7 +1795,7 @@
     }
   else
     fore_pixel = x->background_pixel;
-
+  
   pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
   pixel_allocated_p = 1;
 
@@ -1749,7 +1807,7 @@
 	  x_free_colors (f, &pixel, 1);
 	  pixel_allocated_p = 0;
 	}
-
+      
       pixel = x->mouse_pixel;
       if (pixel == fore_pixel)
 	{
@@ -1957,7 +2015,7 @@
 	    ? x_new_fontset (f, SDATA (fontset_name))
 	    : x_new_font (f, SDATA (arg)));
   UNBLOCK_INPUT;
-
+  
   if (EQ (result, Qnil))
     error ("Font `%s' is not defined", SDATA (arg));
   else if (EQ (result, Qt))
@@ -1973,7 +2031,7 @@
 	}
       else if (!NILP (Fequal (result, oldval)))
 	return;
-
+      
       store_frame_param (f, Qfont, result);
       recompute_basic_faces (f);
     }
@@ -2119,7 +2177,7 @@
   /* Make sure we redisplay all windows in this frame.  */
   windows_or_buffers_changed++;
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   FRAME_MENU_BAR_LINES (f) = 0;
   if (nlines)
     {
@@ -2136,7 +2194,7 @@
       if (FRAME_X_P (f))
 	f->output_data.x->menubar_widget = 0;
     }
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
   FRAME_MENU_BAR_LINES (f) = nlines;
   x_change_window_heights (f->root_window, nlines - olines);
 #endif /* not USE_X_TOOLKIT */
@@ -2168,7 +2226,27 @@
   else
     nlines = 0;
 
-  /* Make sure we redisplay all windows in this frame.  */
+#ifdef USE_GTK
+  FRAME_TOOL_BAR_LINES (f) = 0;
+  if (nlines)
+    {
+      FRAME_EXTERNAL_TOOL_BAR (f) = 1;
+      if (FRAME_X_P (f) && f->output_data.x->toolbar_widget == 0)
+	/* Make sure next redisplay shows the tool bar.  */
+	XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = Qt;
+      update_frame_tool_bar (f);
+    }
+  else
+    {
+      if (FRAME_EXTERNAL_TOOL_BAR (f))
+        free_frame_tool_bar (f);
+      FRAME_EXTERNAL_TOOL_BAR (f) = 0;
+    }
+
+  return;
+#endif
+  
+     /* Make sure we redisplay all windows in this frame.  */
   ++windows_or_buffers_changed;
 
   delta = nlines - FRAME_TOOL_BAR_LINES (f);
@@ -2185,7 +2263,7 @@
   FRAME_TOOL_BAR_LINES (f) = nlines;
   x_change_window_heights (root_window, delta);
   adjust_glyphs (f);
-
+  
   /* We also have to make sure that the internal border at the top of
      the frame, below the menu bar or tool bar, is redrawn when the
      tool bar disappears.  This is so because the internal border is
@@ -2231,7 +2309,7 @@
      Lisp_Object value, oldval;
 {
   unsigned long pixel;
-
+  
   if (STRINGP (value))
     pixel = x_decode_color (f, value, BLACK_PIX_DEFAULT (f));
   else
@@ -2239,7 +2317,7 @@
 
   if (f->output_data.x->scroll_bar_foreground_pixel != -1)
     unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
-
+  
   f->output_data.x->scroll_bar_foreground_pixel = pixel;
   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
     {
@@ -2271,10 +2349,10 @@
     pixel = x_decode_color (f, value, WHITE_PIX_DEFAULT (f));
   else
     pixel = -1;
-
+  
   if (f->output_data.x->scroll_bar_background_pixel != -1)
     unload_color (f, f->output_data.x->scroll_bar_background_pixel);
-
+  
 #ifdef USE_TOOLKIT_SCROLL_BARS
   /* Scrollbar shadow colors.  */
   if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
@@ -2297,7 +2375,7 @@
 	(*condemn_scroll_bars_hook) (f);
       if (judge_scroll_bars_hook)
 	(*judge_scroll_bars_hook) (f);
-
+      
       update_face_from_frame_parameter (f, Qscroll_bar_background, value);
       redraw_frame (f);
     }
@@ -2392,7 +2470,7 @@
      Lisp_Object name;
      int explicit;
 {
-  /* Make sure that requests from lisp code override requests from
+  /* Make sure that requests from lisp code override requests from 
      Emacs redisplay code.  */
   if (explicit)
     {
@@ -2465,8 +2543,15 @@
 	XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
 			&icon);
 #else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+        gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                              SDATA (name));
+	XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                        &icon);
+#else /* not USE_GTK */
 	XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
 	XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
+#endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
 	if (!NILP (f->icon_name)
 	    && icon.value != (unsigned char *) SDATA (f->icon_name))
@@ -2570,8 +2655,15 @@
 	XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
 			&icon);
 #else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+        gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                              SDATA (name));
+	XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                        &icon);
+#else /* not USE_GTK */
 	XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
 	XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
+#endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
 	if (!NILP (f->icon_name)
 	    && icon.value != (unsigned char *) SDATA (f->icon_name))
@@ -2627,7 +2719,7 @@
 	= (NILP (arg)
 	   ? vertical_scroll_bar_none
 	   : EQ (Qright, arg)
-	   ? vertical_scroll_bar_right
+	   ? vertical_scroll_bar_right 
 	   : vertical_scroll_bar_left);
 
       /* We set this parameter before creating the X window for the
@@ -2658,7 +2750,7 @@
       /* Make the actual width at least 14 pixels and a multiple of a
 	 character width.  */
       FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
-
+      
       /* Use all of that space (aside from required margins) for the
 	 scroll bar.  */
       FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
@@ -2987,7 +3079,7 @@
 	      if (!strcmp (SDATA (tem), "on")
 		  || !strcmp (SDATA (tem), "true"))
 		return Qt;
-	      else
+	      else 
 		return Qnil;
 
 	    case RES_TYPE_STRING:
@@ -3106,11 +3198,11 @@
 	     specified.  */
 	  tem = Qnil;
 	}
-
+      
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-
+      
       tem = Qnil;
-
+      
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
     }
 
@@ -3308,7 +3400,7 @@
     {
       int left, top;
       int width, height;
-
+      
       /* It takes both for some WM:s to place it where we want */
       window_prompting = USPosition | PPosition;
       x_fullscreen_adjust (f, &width, &height, &top, &left);
@@ -3319,7 +3411,7 @@
       f->output_data.x->left_pos = left;
       f->output_data.x->top_pos = top;
     }
-
+  
   return window_prompting;
 }
 
@@ -3442,13 +3534,13 @@
   char **missing_list;
   int missing_count;
   char *def_string;
-
+  
   xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
 			base_fontname, &missing_list,
 			&missing_count, &def_string);
   if (missing_list)
     XFreeStringList (missing_list);
-
+  
   /* No need to free def_string. */
   return xfs;
 }
@@ -3488,7 +3580,7 @@
 
   if (FRAME_XIC (f))
     return;
-
+  
   xim = FRAME_X_XIM (f);
   if (xim)
     {
@@ -3586,7 +3678,7 @@
       XFree (preedit_attr);
       XFree (status_attr);
     }
-
+  
   FRAME_XIC (f) = xic;
   FRAME_XIC_STYLE (f) = xic_style;
   FRAME_XIC_FONTSET (f) = xfs;
@@ -3601,7 +3693,7 @@
 {
   if (FRAME_XIC (f) == NULL)
     return;
-
+  
   XDestroyIC (FRAME_XIC (f));
   if (FRAME_XIC_FONTSET (f))
     XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
@@ -3622,7 +3714,7 @@
   struct frame *f = XFRAME (w->frame);
   XVaNestedList attr;
   XPoint spot;
-
+      
   spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
   spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
   attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
@@ -3648,7 +3740,7 @@
   attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
   XSetICValues (xic, XNStatusAttributes, attr, NULL);
   XFree (attr);
-
+  
   attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
   XGetICValues (xic, XNStatusAttributes, attr, NULL);
   XFree (attr);
@@ -3664,7 +3756,9 @@
   area.height = needed->height;
   area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
   area.y = (PIXEL_HEIGHT (f) - area.height
-	    - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
+	    - FRAME_MENUBAR_HEIGHT (f)
+	    - FRAME_TOOLBAR_HEIGHT (f)
+            - FRAME_INTERNAL_BORDER_WIDTH (f));
   XFree (needed);
 
   attr = XVaCreateNestedList (0, XNArea, &area, NULL);
@@ -3692,7 +3786,7 @@
   if (FRAME_XIC_STYLE (f) & XIMStatusArea)
     XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
   XFree (attr);
-
+  
   if (FRAME_XIC_FONTSET (f))
     XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
   FRAME_XIC_FONTSET (f) = xfs;
@@ -3728,7 +3822,7 @@
      for the window manager, so GC relocation won't bother it.
 
      Elsewhere we specify the window name for the window manager.  */
-
+     
   {
     char *str = (char *) SDATA (Vx_resource_name);
     f->namebuf = (char *) xmalloc (strlen (str) + 1);
@@ -3765,7 +3859,7 @@
   XtSetValues (pane_widget, al, ac);
   f->output_data.x->column_widget = pane_widget;
 
-  /* mappedWhenManaged to false tells to the paned window to not map/unmap
+  /* mappedWhenManaged to false tells to the paned window to not map/unmap 
      the emacs screen when changing menubar.  This reduces flickering.  */
 
   ac = 0;
@@ -3779,10 +3873,10 @@
   XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
   frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
 				 al, ac);
-
+ 
   f->output_data.x->edit_widget = frame_widget;
-
-  XtManageChild (frame_widget);
+ 
+  XtManageChild (frame_widget); 
 
   /* Do some needed geometry management.  */
   {
@@ -3791,7 +3885,7 @@
     Arg al[2];
     int ac = 0;
     int extra_borders = 0;
-    int menubar_size
+    int menubar_size 
       = (f->output_data.x->menubar_widget
 	 ? (f->output_data.x->menubar_widget->core.height
 	    + f->output_data.x->menubar_widget->core.border_width)
@@ -3835,13 +3929,13 @@
 
       if (window_prompting & USPosition)
 	sprintf (shell_position, "=%dx%d%c%d%c%d",
-		 PIXEL_WIDTH (f) + extra_borders,
+		 PIXEL_WIDTH (f) + extra_borders, 
 		 PIXEL_HEIGHT (f) + menubar_size + extra_borders,
 		 (xneg ? '-' : '+'), left,
 		 (yneg ? '-' : '+'), top);
       else
 	sprintf (shell_position, "=%dx%d",
-		 PIXEL_WIDTH (f) + extra_borders,
+		 PIXEL_WIDTH (f) + extra_borders, 
 		 PIXEL_HEIGHT (f) + menubar_size + extra_borders);
     }
 
@@ -3859,7 +3953,7 @@
   XtManageChild (pane_widget);
   XtRealizeWidget (shell_widget);
 
-  FRAME_X_WINDOW (f) = XtWindow (frame_widget);
+  FRAME_X_WINDOW (f) = XtWindow (frame_widget); 
 
   validate_x_resource_name ();
 
@@ -3906,7 +4000,7 @@
       attributes.event_mask |= fevent;
     }
 #endif /* HAVE_X_I18N */
-
+  
   attribute_mask = CWEventMask;
   XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
 			   attribute_mask, &attributes);
@@ -3938,7 +4032,16 @@
 }
 
 #else /* not USE_X_TOOLKIT */
-
+#ifdef USE_GTK
+void
+x_window (f)
+     FRAME_PTR f;
+{
+  if (! xg_create_frame_widgets (f))
+    error ("Unable to create window");
+}
+
+#else /*! USE_GTK */
 /* Create and set up the X window for frame F.  */
 
 void
@@ -3988,7 +4091,7 @@
     }
 #endif
 #endif /* HAVE_X_I18N */
-
+  
   validate_x_resource_name ();
 
   class_hints.res_name = (char *) SDATA (Vx_resource_name);
@@ -4041,6 +4144,7 @@
     error ("Unable to create window");
 }
 
+#endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
 
 /* Handle the icon stuff for this window.  Perhaps later we might
@@ -4152,7 +4256,7 @@
      this must be done on a per-frame basis.  */
   f->output_data.x->border_tile
     = (XCreatePixmapFromBitmapData
-       (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
+       (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window, 
 	gray_bits, gray_width, gray_height,
 	f->output_data.x->foreground_pixel,
 	f->output_data.x->background_pixel,
@@ -4171,7 +4275,7 @@
   Display *dpy = FRAME_X_DISPLAY (f);
 
   BLOCK_INPUT;
-
+  
   if (f->output_data.x->normal_gc)
     {
       XFreeGC (dpy, f->output_data.x->normal_gc);
@@ -4183,7 +4287,7 @@
       XFreeGC (dpy, f->output_data.x->reverse_gc);
       f->output_data.x->reverse_gc = 0;
     }
-
+  
   if (f->output_data.x->cursor_gc)
     {
       XFreeGC (dpy, f->output_data.x->cursor_gc);
@@ -4216,7 +4320,7 @@
 #if GLYPH_DEBUG
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 #endif
-
+      
       x_free_frame_resources (f);
 
       /* Check that reference counts are indeed correct.  */
@@ -4224,7 +4328,7 @@
       xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
       return Qt;
     }
-
+  
   return Qnil;
 }
 
@@ -4355,7 +4459,7 @@
     f->output_data.x->cursor_foreground_pixel = -1;
     f->output_data.x->border_pixel = -1;
     f->output_data.x->mouse_pixel = -1;
-
+    
     black = build_string ("black");
     GCPRO1 (black);
     f->output_data.x->foreground_pixel
@@ -4418,7 +4522,7 @@
 	else
 	  font = x_new_font (f, SDATA (font));
       }
-
+    
     /* Try out a font which we hope has bold and italic variations.  */
     if (!STRINGP (font))
       font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
@@ -4449,7 +4553,7 @@
 
   x_default_parameter (f, parms, Qborder_width, make_number (2),
 		       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
-
+  
   /* This defaults to 1 in order to match xterm.  We recognize either
      internalBorderWidth or internalBorder (which is what xterm calls
      it).  */
@@ -4504,7 +4608,7 @@
      end up in init_iterator with a null face cache, which should not
      happen.  */
   init_frame_faces (f);
-
+  
   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
 		       "menuBar", "MenuBar", RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
@@ -4530,7 +4634,7 @@
   if (FRAME_TOOL_BAR_LINES (f))
     {
       int margin, relief, bar_height;
-
+      
       relief = (tool_bar_button_relief >= 0
 		? tool_bar_button_relief
 		: DEFAULT_TOOL_BAR_BUTTON_RELIEF);
@@ -4544,7 +4648,7 @@
 	margin = XFASTINT (XCDR (Vtool_bar_button_margin));
       else
 	margin = 0;
-
+	  
       bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
       f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
     }
@@ -4578,7 +4682,7 @@
 #else
   x_window (f);
 #endif
-
+  
   x_icon (f, parms);
   x_make_gc (f);
 
@@ -4606,7 +4710,7 @@
      f->height.  */
   width = f->width;
   height = f->height;
-
+  
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
   change_frame_size (f, height, width, 1, 0, 0);
@@ -4618,7 +4722,7 @@
      new frames.  */
   call1 (Qface_set_after_frame_default, frame);
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Create the menu bar.  */
   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
     {
@@ -4626,13 +4730,15 @@
 	 frame and we didn't make it visible.  */
       initialize_frame_menubar (f);
 
+#ifndef USE_GTK
       /* This is a no-op, except under Motif where it arranges the
 	 main window for the widgets on it.  */
       lw_set_main_areas (f->output_data.x->column_widget,
 			 f->output_data.x->menubar_widget,
 			 f->output_data.x->edit_widget);
-    }
-#endif /* USE_X_TOOLKIT */
+#endif /* not USE_GTK */
+    }
+#endif /* USE_X_TOOLKIT || USE_GTK */
 
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
@@ -4667,7 +4773,7 @@
   /* Make sure windows on this frame appear in calls to next-window
      and similar functions.  */
   Vwindow_list = Qnil;
-
+  
   return unbind_to (count, frame);
 }
 
@@ -4715,7 +4821,7 @@
 		  RevertToParent, CurrentTime);
   x_uncatch_errors (dpy, count);
   UNBLOCK_INPUT;
-
+  
   return Qnil;
 }
 
@@ -5032,7 +5138,7 @@
       error ("Display has an unknown visual class");
       result = Qnil;
     }
-
+  
   return result;
 }
 
@@ -5187,14 +5293,14 @@
 	  || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
 				dpyinfo->n_planes, class, &vinfo))
 	fatal ("Invalid visual specification `%s'", SDATA (value));
-
+      
       dpyinfo->visual = vinfo.visual;
     }
   else
     {
       int n_visuals;
       XVisualInfo *vinfo, vinfo_template;
-
+      
       dpyinfo->visual = DefaultVisualOfScreen (screen);
 
 #ifdef HAVE_X11R4
@@ -5488,7 +5594,7 @@
      Lisp_Object object;
 {
   int valid_p = 0;
-
+  
   if (CONSP (object) && EQ (XCAR (object), Qimage))
     {
       Lisp_Object tem;
@@ -5504,7 +5610,7 @@
 		if (type)
 		  valid_p = type->valid_p (object);
 	      }
-
+	    
 	    break;
 	  }
     }
@@ -5623,7 +5729,7 @@
 	 was found more than once, it's an error.  */
       keywords[i].value = value;
       ++keywords[i].count;
-
+      
       if (keywords[i].count > 1)
 	return 0;
 
@@ -5667,7 +5773,7 @@
 		   && XINT (value) <= 100)
 	    break;
 	  return 0;
-
+	      
 	case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
 	  if (!INTEGERP (value) || XINT (value) < 0)
 	    return 0;
@@ -5678,7 +5784,7 @@
 
 	case IMAGE_FUNCTION_VALUE:
 	  value = indirect_function (value);
-	  if (SUBRP (value)
+	  if (SUBRP (value) 
 	      || COMPILEDP (value)
 	      || (CONSP (value) && EQ (XCAR (value), Qlambda)))
 	    break;
@@ -5727,7 +5833,7 @@
      int *found;
 {
   Lisp_Object tail;
-
+  
   xassert (valid_image_p (spec));
 
   for (tail = XCDR (spec);
@@ -5741,12 +5847,12 @@
 	  return XCAR (XCDR (tail));
 	}
     }
-
+  
   if (found)
     *found = 0;
   return Qnil;
 }
-
+     
 
 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
        doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
@@ -5767,7 +5873,7 @@
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
-
+  
       if (NILP (pixels))
 	size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
 		      make_float ((double) height / CANON_Y_UNIT (f)));
@@ -5824,7 +5930,7 @@
      unsigned hash;
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
-
+  
   xassert (valid_image_p (spec));
   bzero (img, sizeof *img);
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
@@ -5885,7 +5991,7 @@
   if (img->pixmap == None && !img->load_failed_p)
     img->load_failed_p = img->type->load (f, img) == 0;
 }
-
+     
 
 /* Value is the number of pixels for the ascent of image IMG when
    drawn in face FACE.  */
@@ -5937,7 +6043,7 @@
   for (i = best_count = 0; i < 4; ++i)
     {
       int j, n;
-
+	  
       for (j = n = 0; j < 4; ++j)
 	if (corners[i] == corners[j])
 	  ++n;
@@ -6053,7 +6159,7 @@
       img->mask = None;
       img->background_transparent_valid = 0;
     }
-
+      
   if (colors_p && img->ncolors)
     {
       x_free_colors (f, img->colors, img->ncolors);
@@ -6128,7 +6234,7 @@
 {
   struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
   int size;
-
+  
   bzero (c, sizeof *c);
   c->size = 50;
   c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
@@ -6153,7 +6259,7 @@
 
       /* Cache should not be referenced by any frame when freed.  */
       xassert (c->refcount == 0);
-
+      
       for (i = 0; i < c->used; ++i)
 	free_image (f, c->images[i]);
       xfree (c->images);
@@ -6190,7 +6296,7 @@
       /* Block input so that we won't be interrupted by a SIGIO
 	 while being in an inconsistent state.  */
       BLOCK_INPUT;
-
+      
       for (i = nfreed = 0; i < c->used; ++i)
 	{
 	  struct image *img = c->images[i];
@@ -6209,7 +6315,7 @@
       if (nfreed)
 	{
 	  Lisp_Object tail, frame;
-
+	  
 	  FOR_EACH_FRAME (tail, frame)
 	    {
 	      struct frame *f = XFRAME (frame);
@@ -6237,7 +6343,7 @@
   if (EQ (frame, Qt))
     {
       Lisp_Object tail;
-
+      
       FOR_EACH_FRAME (tail, frame)
 	if (FRAME_X_P (XFRAME (frame)))
 	  clear_image_cache (XFRAME (frame), 1);
@@ -6264,7 +6370,7 @@
       Lisp_Object mask;
 
       spec = img->spec;
-
+      
       /* `:heuristic-mask t'
 	 `:mask heuristic'
 	 means build a mask heuristically.
@@ -6274,16 +6380,16 @@
 	 image.
 	 `:mask nil'
 	 means remove a mask, if any.  */
-
+	      
       mask = image_spec_value (spec, QCheuristic_mask, NULL);
       if (!NILP (mask))
 	x_build_heuristic_mask (f, img, mask);
       else
 	{
 	  int found_p;
-
+		    
 	  mask = image_spec_value (spec, QCmask, &found_p);
-
+		  
 	  if (EQ (mask, Qheuristic))
 	    x_build_heuristic_mask (f, img, Qt);
 	  else if (CONSP (mask)
@@ -6300,8 +6406,8 @@
 	      img->mask = None;
 	    }
 	}
-
-
+ 
+	  
       /* Should we apply an image transformation algorithm?  */
       conversion = image_spec_value (spec, QCconversion, NULL);
       if (EQ (conversion, Qdisabled))
@@ -6343,7 +6449,7 @@
      specification.  */
   xassert (FRAME_WINDOW_P (f));
   xassert (valid_image_p (spec));
-
+  
   GCPRO1 (spec);
 
   /* Look up SPEC in the hash table of the image cache.  */
@@ -6358,7 +6464,7 @@
   if (img == NULL)
     {
       extern Lisp_Object Qpostscript;
-
+      
       BLOCK_INPUT;
       img = make_image (spec, hash);
       cache_image (f, img);
@@ -6390,7 +6496,7 @@
 	    img->ascent = XFASTINT (ascent);
 	  else if (EQ (ascent, Qcenter))
 	    img->ascent = CENTERED_IMAGE_ASCENT;
-
+	  
 	  margin = image_spec_value (spec, QCmargin, NULL);
 	  if (INTEGERP (margin) && XINT (margin) >= 0)
 	    img->vmargin = img->hmargin = XFASTINT (margin);
@@ -6402,7 +6508,7 @@
 	      if (XINT (XCDR (margin)) > 0)
 		img->vmargin = XFASTINT (XCDR (margin));
 	    }
-
+	  
 	  relief = image_spec_value (spec, QCrelief, NULL);
 	  if (INTEGERP (relief))
 	    {
@@ -6436,9 +6542,9 @@
   /* We're using IMG, so set its timestamp to `now'.  */
   EMACS_GET_TIME (now);
   img->timestamp = EMACS_SECS (now);
-
+  
   UNGCPRO;
-
+  
   /* Value is the image id.  */
   return img->id;
 }
@@ -6590,7 +6696,7 @@
      int width, height;
 {
   GC gc;
-
+  
   xassert (interrupt_input_blocked);
   gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
   XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
@@ -6625,7 +6731,7 @@
 
   /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
   fd = openp (search_path, file, Qnil, &file_found, Qnil);
-
+  
   if (fd == -1)
     file_found = Qnil;
   else
@@ -6667,7 +6773,7 @@
 	  buf = NULL;
 	}
     }
-
+  
   return buf;
 }
 
@@ -6746,7 +6852,7 @@
   XBM_TK_NUMBER
 };
 
-
+  
 /* Return non-zero if OBJECT is a valid XBM-type image specification.
    A valid specification is a list starting with the symbol `image'
    The rest of the list is a property list which must contain an
@@ -6781,7 +6887,7 @@
      Lisp_Object object;
 {
   struct image_keyword kw[XBM_LAST];
-
+  
   bcopy (xbm_format, kw, sizeof kw);
   if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
     return 0;
@@ -6813,13 +6919,13 @@
       data = kw[XBM_DATA].value;
       width = XFASTINT (kw[XBM_WIDTH].value);
       height = XFASTINT (kw[XBM_HEIGHT].value);
-
+      
       /* Check type of data, and width and height against contents of
 	 data.  */
       if (VECTORP (data))
 	{
 	  int i;
-
+	  
 	  /* Number of elements of the vector must be >= height.  */
 	  if (XVECTOR (data)->size < height)
 	    return 0;
@@ -6879,7 +6985,7 @@
   int c;
 
  loop:
-
+  
   /* Skip white space.  */
   while (*s < end && (c = *(*s)++, isspace (c)))
     ;
@@ -6889,7 +6995,7 @@
   else if (isdigit (c))
     {
       int value = 0, digit;
-
+      
       if (c == '0' && *s < end)
 	{
 	  c = *(*s)++;
@@ -6987,7 +7093,7 @@
      if (LA1 != (TOKEN)) 	\
        goto failure;		\
      else			\
-       match ()
+       match ()	
 
 #define expect_ident(IDENT)					\
      if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0)	\
@@ -7030,7 +7136,7 @@
     {
       if (strcmp (buffer, "unsigned") == 0)
 	{
-	  match ();
+	  match (); 
 	  expect_ident ("char");
 	}
       else if (strcmp (buffer, "short") == 0)
@@ -7045,7 +7151,7 @@
       else
 	goto failure;
     }
-  else
+  else 
     goto failure;
 
   expect (XBM_TK_IDENT);
@@ -7068,7 +7174,7 @@
 	  *p++ = val;
 	  if (!padding_p || ((i + 2) % bytes_per_line))
 	    *p++ = value >> 8;
-
+	  
 	  if (LA1 == ',' || LA1 == '}')
 	    match ();
 	  else
@@ -7081,9 +7187,9 @@
 	{
 	  int val = value;
 	  expect (XBM_TK_NUMBER);
-
+	  
 	  *p++ = val;
-
+	  
 	  if (LA1 == ',' || LA1 == '}')
 	    match ();
 	  else
@@ -7095,7 +7201,7 @@
   return 1;
 
  failure:
-
+  
   if (data && *data)
     {
       xfree (*data);
@@ -7122,7 +7228,7 @@
   int rc;
   unsigned char *data;
   int success_p = 0;
-
+  
   rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
@@ -7130,7 +7236,7 @@
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       Lisp_Object value;
-
+      
       xassert (img->width > 0 && img->height > 0);
 
       /* Get foreground and background colors, maybe allocate colors.  */
@@ -7183,7 +7289,7 @@
 				   &w, &h, NULL));
 }
 
-
+    
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -7205,7 +7311,7 @@
       char *contents;
       int size;
       struct gcpro gcpro1;
-
+      
       file = x_find_image_file (file_name);
       GCPRO1 (file);
       if (!STRINGP (file))
@@ -7275,7 +7381,7 @@
 	      int i;
 	      char *p;
 	      int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
-
+	  
 	      p = bits = (char *) alloca (nbytes * img->height);
 	      for (i = 0; i < img->height; ++i, p += nbytes)
 		{
@@ -7313,14 +7419,14 @@
 
   return success_p;
 }
-
+  
 
 
 /***********************************************************************
 			      XPM images
  ***********************************************************************/
 
-#if HAVE_XPM
+#if HAVE_XPM 
 
 static int xpm_image_p P_ ((Lisp_Object object));
 static int xpm_load P_ ((struct frame *f, struct image *img));
@@ -7437,7 +7543,7 @@
     {
       int i;
       XColor color;
-
+      
       for (i = 0; i < attrs->numsymbols; ++i)
 	if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
 			 attrs->colorsymbols[i].value, &color))
@@ -7480,7 +7586,7 @@
 {
   unsigned h = 0;
   char *s;
-
+  
   for (s = color_name; *s; ++s)
     h = (h << 2) ^ *s;
   return h %= XPM_COLOR_CACHE_BUCKETS;
@@ -7500,10 +7606,10 @@
 {
   size_t nbytes;
   struct xpm_cached_color *p;
-
+  
   if (bucket < 0)
     bucket = xpm_color_bucket (color_name);
-
+      
   nbytes = sizeof *p + strlen (color_name);
   p = (struct xpm_cached_color *) xmalloc (nbytes);
   strcpy (p->name, color_name);
@@ -7541,7 +7647,7 @@
 				       color->blue);
       p = xpm_cache_color (f, color_name, color, h);
     }
-
+  
   return p != NULL;
 }
 
@@ -7668,7 +7774,7 @@
       Lisp_Object tail;
       XpmColorSymbol *xpm_syms;
       int i, size;
-
+      
       attrs.valuemask |= XpmColorSymbols;
 
       /* Count number of symbols.  */
@@ -7701,7 +7807,7 @@
 #ifdef ALLOC_XPM_COLORS
   xpm_init_color_cache (f, &attrs);
 #endif
-
+  
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (specified_file))
     {
@@ -7711,7 +7817,7 @@
 	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
 	  return 0;
 	}
-
+      
       rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
 				SDATA (file), &img->pixmap, &img->mask,
 				&attrs);
@@ -7758,19 +7864,19 @@
 	case XpmOpenFailed:
 	  image_error ("Error opening XPM file (%s)", img->spec, Qnil);
 	  break;
-
+	  
 	case XpmFileInvalid:
 	  image_error ("Invalid XPM file (%s)", img->spec, Qnil);
 	  break;
-
+	  
 	case XpmNoMemory:
 	  image_error ("Out of memory (%s)", img->spec, Qnil);
 	  break;
-
+	  
 	case XpmColorFailed:
 	  image_error ("Color allocation error (%s)", img->spec, Qnil);
 	  break;
-
+	  
 	default:
 	  image_error ("Unknown error (%s)", img->spec, Qnil);
 	  break;
@@ -7876,14 +7982,14 @@
       color.red = r;
       color.green = g;
       color.blue = b;
-
+      
       cmap = FRAME_X_COLORMAP (f);
       rc = x_alloc_nearest_color (f, cmap, &color);
 
       if (rc)
 	{
 	  ++ct_colors_allocated;
-
+      
 	  p = (struct ct_color *) xmalloc (sizeof *p);
 	  p->r = r;
 	  p->g = g;
@@ -7929,7 +8035,7 @@
       if (rc)
 	{
 	  ++ct_colors_allocated;
-
+      
 	  p = (struct ct_color *) xmalloc (sizeof *p);
 	  p->r = color.red;
 	  p->g = color.green;
@@ -7941,7 +8047,7 @@
       else
 	return FRAME_FOREGROUND_PIXEL (f);
     }
-
+  
   return p->pixel;
 }
 
@@ -7967,7 +8073,7 @@
       colors = (unsigned long *) xmalloc (ct_colors_allocated
 					  * sizeof *colors);
       *n = ct_colors_allocated;
-
+      
       for (i = j = 0; i < CT_SIZE; ++i)
 	for (p = ct_table[i]; p; p = p->next)
 	  colors[j++] = p->pixel;
@@ -8042,7 +8148,7 @@
   for (y = 0; y < img->height; ++y)
     {
       XColor *row = p;
-
+      
       for (x = 0; x < img->width; ++x, ++p)
 	p->pixel = XGetPixel (ximg, x, y);
 
@@ -8069,9 +8175,9 @@
   XImage *oimg;
   Pixmap pixmap;
   XColor *p;
-
+  
   init_color_table ();
-
+  
   x_create_x_image_and_pixmap (f, img->width, img->height, 0,
 			       &oimg, &pixmap);
   p = colors;
@@ -8098,7 +8204,7 @@
 
    MATRIX is a nine-element array specifying the transformation
    matrix.  See emboss_matrix for an example.
-
+   
    COLOR_ADJUST is a color adjustment added to each pixel of the
    outgoing image.  */
 
@@ -8126,7 +8232,7 @@
       p = COLOR (new, img->width - 1, y);
       p->red = p->green = p->blue = 0xffff/2;
     }
-
+  
   for (x = 1; x < img->width - 1; ++x)
     {
       p = COLOR (new, x, 0);
@@ -8138,7 +8244,7 @@
   for (y = 1; y < img->height - 1; ++y)
     {
       p = COLOR (new, 1, y);
-
+      
       for (x = 1; x < img->width - 1; ++x, ++p)
 	{
 	  int r, g, b, y1, x1;
@@ -8211,7 +8317,7 @@
 {
   int i = 0;
   int trans[9];
-
+  
   if (CONSP (matrix))
     {
       for (i = 0;
@@ -8331,7 +8437,7 @@
   /* Determine the background color of ximg.  If HOW is `(R G B)'
      take that as color.  Otherwise, use the image's background color. */
   use_img_background = 1;
-
+  
   if (CONSP (how))
     {
       int rgb[3], i;
@@ -8350,7 +8456,7 @@
 	  use_img_background = 0;
 	}
     }
-
+  
   if (use_img_background)
     bg = four_corners_best (ximg, img->width, img->height);
 
@@ -8367,7 +8473,7 @@
   x_put_x_image (f, mask_img, img->mask, img->width, img->height);
   x_destroy_x_image (mask_img);
   XDestroyImage (ximg);
-
+  
   return 1;
 }
 
@@ -8440,9 +8546,9 @@
      Lisp_Object object;
 {
   struct image_keyword fmt[PBM_LAST];
-
+  
   bcopy (pbm_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
 
@@ -8491,7 +8597,7 @@
 
 /* Load PBM image IMG for use on frame F.  */
 
-static int
+static int 
 pbm_load (f, img)
      struct frame *f;
      struct image *img;
@@ -8554,7 +8660,7 @@
     case '1':
       raw_p = 0, type = PBM_MONO;
       break;
-
+      
     case '2':
       raw_p = 0, type = PBM_GRAY;
       break;
@@ -8566,11 +8672,11 @@
     case '4':
       raw_p = 1, type = PBM_MONO;
       break;
-
+      
     case '5':
       raw_p = 1, type = PBM_GRAY;
       break;
-
+      
     case '6':
       raw_p = 1, type = PBM_COLOR;
       break;
@@ -8591,7 +8697,7 @@
       if (raw_p && max_color_idx > 255)
 	max_color_idx = 255;
     }
-
+  
   if (width < 0
       || height < 0
       || (type != PBM_MONO && max_color_idx < 0))
@@ -8600,7 +8706,7 @@
   if (!x_create_x_image_and_pixmap (f, width, height, 0,
 				    &ximg, &img->pixmap))
     goto error;
-
+  
   /* Initialize the color hash table.  */
   init_color_table ();
 
@@ -8614,7 +8720,7 @@
       /* Parse the image specification.  */
       bcopy (pbm_format, fmt, sizeof fmt);
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
-
+      
       /* Get foreground and background colors, maybe allocate colors.  */
       if (fmt[PBM_FOREGROUND].count
 	  && STRINGP (fmt[PBM_FOREGROUND].value))
@@ -8626,7 +8732,7 @@
 	  img->background = bg;
 	  img->background_valid = 1;
 	}
-
+      
       for (y = 0; y < height; ++y)
 	for (x = 0; x < width; ++x)
 	  {
@@ -8649,7 +8755,7 @@
 	for (x = 0; x < width; ++x)
 	  {
 	    int r, g, b;
-
+	    
 	    if (type == PBM_GRAY)
 	      r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
 	    else if (raw_p)
@@ -8664,7 +8770,7 @@
 		g = pbm_scan_number (&p, end);
 		b = pbm_scan_number (&p, end);
 	      }
-
+	    
 	    if (r < 0 || g < 0 || b < 0)
 	      {
 		xfree (ximg->data);
@@ -8674,7 +8780,7 @@
 			     img->spec, Qnil);
 		goto error;
 	      }
-
+	    
 	    /* RGB values are now in the range 0..max_color_idx.
 	       Scale this to the range 0..0xffff supported by X.  */
 	    r = (double) r * 65535 / max_color_idx;
@@ -8683,7 +8789,7 @@
 	    XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
 	  }
     }
-
+  
   /* Store in IMG->colors the colors allocated for the image, and
      free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
@@ -8692,11 +8798,11 @@
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     IMAGE_BACKGROUND (img, f, ximg);
-
+  
   /* Put the image into a pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-
+      
   img->width = width;
   img->height = height;
 
@@ -8778,7 +8884,7 @@
 {
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
@@ -8835,7 +8941,7 @@
 
   if (length > tbr->len - tbr->index)
     png_error (png_ptr, "Read error");
-
+  
   bcopy (tbr->bytes + tbr->index, data, length);
   tbr->index = tbr->index + length;
 }
@@ -8977,14 +9083,14 @@
   png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
 	        &interlace_type, NULL, NULL);
 
-  /* If image contains simply transparency data, we prefer to
+  /* If image contains simply transparency data, we prefer to 
      construct a clipping mask.  */
   if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
     transparent_p = 1;
   else
     transparent_p = 0;
 
-  /* This function is easier to write if we only have to handle
+  /* This function is easier to write if we only have to handle 
      one data format: RGB or RGBA with 8 bits per channel.  Let's
      transform other formats into that format.  */
 
@@ -8997,7 +9103,7 @@
   png_set_expand (png_ptr);
 
   /* Convert grayscale images to RGB.  */
-  if (color_type == PNG_COLOR_TYPE_GRAY
+  if (color_type == PNG_COLOR_TYPE_GRAY 
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     png_set_gray_to_rgb (png_ptr);
 
@@ -9046,14 +9152,14 @@
 	    }
 	}
       else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
-	/* Image contains a background color with which to
+	/* Image contains a background color with which to 
 	   combine the image.  */
 	png_set_background (png_ptr, image_bg,
 			    PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
 	{
 	  /* Image does not contain a background color with which
-	     to combine the image data via an alpha channel.  Use
+	     to combine the image data via an alpha channel.  Use 
 	     the frame's background instead.  */
 	  XColor color;
 	  Colormap cmap;
@@ -9101,12 +9207,12 @@
       fclose (fp);
       fp = NULL;
     }
-
+  
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
 				    &img->pixmap))
     goto error;
-
+  
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -9137,16 +9243,16 @@
 	  XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
 
 	  /* An alpha channel, aka mask channel, associates variable
-	     transparency with an image.  Where other image formats
-	     support binary transparency---fully transparent or fully
+	     transparency with an image.  Where other image formats 
+	     support binary transparency---fully transparent or fully 
 	     opaque---PNG allows up to 254 levels of partial transparency.
 	     The PNG library implements partial transparency by combining
 	     the image with a specified background color.
 
 	     I'm not sure how to handle this here nicely: because the
 	     background on which the image is displayed may change, for
-	     real alpha channel support, it would be necessary to create
-	     a new image for each possible background.
+	     real alpha channel support, it would be necessary to create 
+	     a new image for each possible background.  
 
 	     What I'm doing now is that a mask is created if we have
 	     boolean transparency information.  Otherwise I'm using
@@ -9292,9 +9398,9 @@
      Lisp_Object object;
 {
   struct image_keyword fmt[JPEG_LAST];
-
+  
   bcopy (jpeg_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
@@ -9365,7 +9471,7 @@
     {
       if (num_bytes > src->bytes_in_buffer)
 	ERREXIT (cinfo, JERR_INPUT_EOF);
-
+      
       src->bytes_in_buffer -= num_bytes;
       src->next_input_byte += num_bytes;
     }
@@ -9403,7 +9509,7 @@
       src = (struct jpeg_source_mgr *) cinfo->src;
       src->next_input_byte = data;
     }
-
+  
   src = (struct jpeg_source_mgr *) cinfo->src;
   src->init_source = our_init_source;
   src->fill_input_buffer = our_fill_input_buffer;
@@ -9418,7 +9524,7 @@
 /* Load image IMG for use on frame F.  Patterned after example.c
    from the JPEG lib.  */
 
-static int
+static int 
 jpeg_load (f, img)
      struct frame *f;
      struct image *img;
@@ -9451,7 +9557,7 @@
 	  UNGCPRO;
 	  return 0;
 	}
-
+  
       fp = fopen (SDATA (file), "r");
       if (fp == NULL)
 	{
@@ -9465,7 +9571,7 @@
      error is detected.  This function will perform a longjmp.  */
   cinfo.err = jpeg_std_error (&mgr.pub);
   mgr.pub.error_exit = my_error_exit;
-
+  
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
     {
       if (rc == 1)
@@ -9476,7 +9582,7 @@
 	  image_error ("Error reading JPEG image `%s': %s", img->spec,
 		       build_string (buffer));
 	}
-
+	  
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
 	fclose ((FILE *) fp);
@@ -9487,7 +9593,7 @@
 
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
-
+      
       UNGCPRO;
       return 0;
     }
@@ -9537,7 +9643,7 @@
     init_color_table ();
     colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
 				       * sizeof *colors);
-
+  
     for (i = 0; i < cinfo.actual_number_of_colors; ++i)
       {
 	/* Multiply RGB values with 255 because X expects RGB values
@@ -9573,7 +9679,7 @@
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     IMAGE_BACKGROUND (img, f, ximg);
-
+  
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
@@ -9654,10 +9760,10 @@
 {
   struct image_keyword fmt[TIFF_LAST];
   bcopy (tiff_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
-
+  
   /* Must specify either the :data or :file keyword.  */
   return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
 }
@@ -9721,22 +9827,22 @@
     case SEEK_SET:		/* Go from beginning of source.  */
       idx = off;
       break;
-
+      
     case SEEK_END:		/* Go from end of source.  */
       idx = src->len + off;
       break;
-
+      
     case SEEK_CUR:		/* Go from current position.  */
       idx = src->index + off;
       break;
-
+      
     default:			/* Invalid `whence'.   */
       return -1;
     }
-
+  
   if (idx > src->len || idx < 0)
     return -1;
-
+  
   src->index = idx;
   return src->index;
 }
@@ -9787,7 +9893,7 @@
 {
   char buf[512];
   int len;
-
+  
   len = sprintf (buf, "TIFF error: %s ", title);
   vsprintf (buf + len, format, ap);
   add_to_log (buf, Qnil, Qnil);
@@ -9801,7 +9907,7 @@
 {
   char buf[512];
   int len;
-
+  
   len = sprintf (buf, "TIFF warning: %s ", title);
   vsprintf (buf + len, format, ap);
   add_to_log (buf, Qnil, Qnil);
@@ -9844,7 +9950,7 @@
 	  UNGCPRO;
 	  return 0;
 	}
-
+	  
       /* Try to open the image file.  */
       tiff = TIFFOpen (SDATA (file), "r");
       if (tiff == NULL)
@@ -9883,7 +9989,7 @@
   TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
   TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
   buf = (uint32 *) xmalloc (width * height * sizeof *buf);
-
+  
   rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
   TIFFClose (tiff);
   if (!rc)
@@ -9909,21 +10015,21 @@
   for (y = 0; y < height; ++y)
     {
       uint32 *row = buf + y * width;
-
+      
       for (x = 0; x < width; ++x)
 	{
 	  uint32 abgr = row[x];
 	  int r = TIFFGetR (abgr) << 8;
 	  int g = TIFFGetG (abgr) << 8;
 	  int b = TIFFGetB (abgr) << 8;
-	  XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
+	  XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); 
 	}
     }
 
   /* Remember the colors allocated for the image.  Free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
-
+      
   img->width = width;
   img->height = height;
 
@@ -10015,10 +10121,10 @@
 {
   struct image_keyword fmt[GIF_LAST];
   bcopy (gif_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
-
+  
   /* Must specify either the :data or :file keyword.  */
   return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
 }
@@ -10093,7 +10199,7 @@
 	  UNGCPRO;
 	  return 0;
 	}
-
+  
       /* Open the GIF file.  */
       gif = DGifOpenFileName (SDATA (file));
       if (gif == NULL)
@@ -10151,14 +10257,14 @@
       UNGCPRO;
       return 0;
     }
-
+  
   /* Allocate colors.  */
   gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
   if (!gif_color_map)
     gif_color_map = gif->SColorMap;
   init_color_table ();
   bzero (pixel_colors, sizeof pixel_colors);
-
+  
   for (i = 0; i < gif_color_map->ColorCount; ++i)
     {
       int r = gif_color_map->Colors[i].Red << 8;
@@ -10171,7 +10277,7 @@
   free_color_table ();
 
   /* Clear the part of the screen image that are not covered by
-     the image from the GIF file.  Full animated GIF support
+     the image from the GIF file.  Full animated GIF support 
      requires more than can be done here (see the gif89 spec,
      disposal methods).  Let's simply assume that the part
      not covered by a sub-image is in the frame's background color.  */
@@ -10200,7 +10306,7 @@
      `raster' here because RasterBits below is a char *, and invites
      problems with bytes >= 0x80.  */
   raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
-
+  
   if (gif->SavedImages[ino].ImageDesc.Interlace)
     {
       static int interlace_start[] = {0, 4, 2, 1};
@@ -10218,14 +10324,14 @@
 	      while (row >= image_height)
 		row = interlace_start[++pass];
 	    }
-
+	  
 	  for (x = 0; x < image_width; x++)
 	    {
 	      int i = raster[(y * image_width) + x];
 	      XPutPixel (ximg, x + image_left, row + image_top,
 			 pixel_colors[i]);
 	    }
-
+	  
 	  row += interlace_increment[pass];
 	}
     }
@@ -10238,17 +10344,17 @@
 	    XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
 	  }
     }
-
+  
   DGifCloseFile (gif);
 
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     IMAGE_BACKGROUND (img, f, ximg);
-
+  
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-
+      
   UNGCPRO;
   return 1;
 }
@@ -10348,9 +10454,9 @@
   struct image_keyword fmt[GS_LAST];
   Lisp_Object tem;
   int i;
-
+  
   bcopy (gs_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
 
@@ -10416,7 +10522,7 @@
       image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
       return 0;
     }
-
+    
   /* Call the loader to fill the pixmap.  It returns a process object
      if successful.  We do not record_unwind_protect here because
      other places in redisplay like calling window scroll functions
@@ -10427,12 +10533,12 @@
 	   (unsigned long) FRAME_X_WINDOW (f),
 	   (unsigned long) img->pixmap);
   window_and_pixmap_id = build_string (buffer);
-
+  
   sprintf (buffer, "%lu %lu",
 	   FRAME_FOREGROUND_PIXEL (f),
 	   FRAME_BACKGROUND_PIXEL (f));
   pixel_colors = build_string (buffer);
-
+  
   XSETFRAME (frame, f);
   loader = image_spec_value (img->spec, QCloader, NULL);
   if (NILP (loader))
@@ -10470,7 +10576,7 @@
      instance, give up.  */
   if (i == c->used)
     return;
-
+  
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
   img = c->images[i];
@@ -10494,10 +10600,10 @@
       if (ximg)
 	{
 	  int x, y;
-
+	  
 	  /* Initialize the color table.  */
 	  init_color_table ();
-
+      
 	  /* For each pixel of the image, look its color up in the
 	     color table.  After having done so, the color table will
 	     contain an entry for each color used by the image.  */
@@ -10526,7 +10632,7 @@
       else
 	image_error ("Cannot get X image of `%s'; colors will not be freed",
 		     img->spec, Qnil);
-
+      
       UNBLOCK_INPUT;
     }
 
@@ -10629,8 +10735,8 @@
       rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
 			       prop_atom, 0, bytes_remaining,
 			       False, XA_STRING,
-			       &actual_type, &actual_format,
-			       &actual_size, &bytes_remaining,
+			       &actual_type, &actual_format, 
+			       &actual_size, &bytes_remaining, 
 			       (unsigned char **) &tmp_data);
       if (rc == Success && tmp_data)
 	prop_value = make_string (tmp_data, size);
@@ -10679,7 +10785,7 @@
 {
   EMACS_TIME delay;
   int secs, usecs = 0;
-
+  
   cancel_hourglass ();
 
   if (INTEGERP (Vhourglass_delay)
@@ -10695,7 +10801,7 @@
     }
   else
     secs = DEFAULT_HOURGLASS_DELAY;
-
+  
   EMACS_SET_SECS_USECS (delay, secs, usecs);
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
 				     show_hourglass, NULL);
@@ -10713,7 +10819,7 @@
       cancel_atimer (hourglass_atimer);
       hourglass_atimer = NULL;
     }
-
+  
   if (hourglass_shown_p)
     hide_hourglass ();
 }
@@ -10739,17 +10845,17 @@
   if (!hourglass_shown_p)
     {
       Lisp_Object rest, frame;
-
+  
       BLOCK_INPUT;
-
+  
       FOR_EACH_FRAME (rest, frame)
 	{
 	  struct frame *f = XFRAME (frame);
-
+	  
 	  if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
 	    {
 	      Display *dpy = FRAME_X_DISPLAY (f);
-
+	      
 #ifdef USE_X_TOOLKIT
 	      if (f->output_data.x->widget)
 #else
@@ -10757,14 +10863,14 @@
 #endif
 		{
 		  f->output_data.x->hourglass_p = 1;
-
+	
 		  if (!f->output_data.x->hourglass_window)
 		    {
 		      unsigned long mask = CWCursor;
 		      XSetWindowAttributes attrs;
-
+	    
 		      attrs.cursor = f->output_data.x->hourglass_cursor;
-
+	    
 		      f->output_data.x->hourglass_window
 			= XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
 					 0, 0, 32000, 32000, 0, 0,
@@ -10772,7 +10878,7 @@
 					 CopyFromParent,
 					 mask, &attrs);
 		    }
-
+	
 		  XMapRaised (dpy, f->output_data.x->hourglass_window);
 		  XFlush (dpy);
 		}
@@ -10799,7 +10905,7 @@
       FOR_EACH_FRAME (rest, frame)
 	{
 	  struct frame *f = XFRAME (frame);
-
+      
 	  if (FRAME_X_P (f)
 	      /* Watch out for newly created frames.  */
 	      && f->output_data.x->hourglass_window)
@@ -10828,7 +10934,7 @@
 					   Lisp_Object, Lisp_Object));
 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
 				Lisp_Object, int, int, int *, int *));
-
+     
 /* The frame of a currently visible tooltip.  */
 
 Lisp_Object tip_frame;
@@ -10861,7 +10967,7 @@
       tip_window = None;
       tip_frame = Qnil;
     }
-
+  
   return deleted;
 }
 
@@ -10925,7 +11031,7 @@
   Ferase_buffer ();
   Finsert (1, &text);
   set_buffer_internal_1 (old_buffer);
-
+  
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
@@ -10961,7 +11067,7 @@
   {
     Lisp_Object black;
     struct gcpro gcpro1;
-
+    
     black = build_string ("black");
     GCPRO1 (black);
     f->output_data.x->foreground_pixel
@@ -11011,7 +11117,7 @@
 	else
 	  font = x_new_font (f, SDATA (font));
       }
-
+    
     /* Try out a font which we hope has bold and italic variations.  */
     if (!STRINGP (font))
       font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
@@ -11036,7 +11142,7 @@
 
   x_default_parameter (f, parms, Qborder_width, make_number (2),
 		       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
-
+  
   /* This defaults to 2 in order to match xterm.  We recognize either
      internalBorderWidth or internalBorder (which is what xterm calls
      it).  */
@@ -11074,7 +11180,7 @@
      end up in init_iterator with a null face cache, which should not
      happen.  */
   init_frame_faces (f);
-
+  
   f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
   window_prompting = x_figure_window_size (f, parms);
 
@@ -11097,12 +11203,12 @@
   {
     XSetWindowAttributes attrs;
     unsigned long mask;
-
+    
     BLOCK_INPUT;
     mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
     if (DoesSaveUnders (dpyinfo->screen))
       mask |= CWSaveUnder;
-
+    
     /* Window managers look at the override-redirect flag to determine
        whether or net to give windows a decoration (Xlib spec, chapter
        3.2.8).  */
@@ -11141,12 +11247,12 @@
   f->height = 0;
   SET_FRAME_WIDTH (f, 0);
   change_frame_size (f, height, width, 1, 0, 0);
-
+  
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
     Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
 					    Qnil));
-
+  
   /* Set up faces after all frame parameters are known.  This call
      also merges in face attributes specified for new frames.
 
@@ -11161,12 +11267,12 @@
     /* Set tip_frame here, so that */
     tip_frame = frame;
     call1 (Qface_set_after_frame_default, frame);
-
+    
     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
       Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
 					      Qnil));
   }
-
+  
   f->no_split = 1;
 
   UNGCPRO;
@@ -11209,11 +11315,11 @@
   int win_x, win_y;
   Window root, child;
   unsigned pmask;
-
+  
   /* User-specified position?  */
   left = Fcdr (Fassq (Qleft, parms));
   top  = Fcdr (Fassq (Qtop, parms));
-
+  
   /* Move the tooltip window where the mouse pointer is.  Resize and
      show it.  */
   if (!INTEGERP (left) || !INTEGERP (top))
@@ -11282,7 +11388,7 @@
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   int count = SPECPDL_INDEX ();
-
+  
   specbind (Qinhibit_redisplay, Qt);
 
   GCPRO4 (string, parms, frame, timeout);
@@ -11293,12 +11399,12 @@
     timeout = make_number (5);
   else
     CHECK_NATNUM (timeout);
-
+  
   if (NILP (dx))
     dx = make_number (5);
   else
     CHECK_NUMBER (dx);
-
+  
   if (NILP (dy))
     dy = make_number (-10);
   else
@@ -11318,7 +11424,7 @@
 	  && !NILP (Fequal (last_parms, parms)))
 	{
 	  struct frame *f = XFRAME (tip_frame);
-
+	  
 	  /* Only DX and DY have changed.  */
 	  if (!NILP (tip_timer))
 	    {
@@ -11365,7 +11471,7 @@
   /* Set up the frame's root window.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left = w->top = make_number (0);
-
+  
   if (CONSP (Vx_max_tooltip_size)
       && INTEGERP (XCAR (Vx_max_tooltip_size))
       && XINT (XCAR (Vx_max_tooltip_size)) > 0
@@ -11380,7 +11486,7 @@
       w->width = make_number (80);
       w->height = make_number (40);
     }
-
+  
   f->window_width = XINT (w->width);
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
@@ -11418,7 +11524,7 @@
 	}
       else
 	row_width = row->pixel_width;
-
+      
       height += row->height;
       width = max (width, row_width);
     }
@@ -11437,7 +11543,7 @@
 		     root_x, root_y, width, height);
   XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
   UNBLOCK_INPUT;
-
+  
   /* Draw into the window.  */
   w->must_be_updated_p = 1;
   update_single_window (w, 1);
@@ -11468,16 +11574,16 @@
   /* Return quickly if nothing to do.  */
   if (NILP (tip_timer) && NILP (tip_frame))
     return Qnil;
-
+  
   frame = tip_frame;
   timer = tip_timer;
   GCPRO2 (frame, timer);
   tip_frame = tip_timer = deleted = Qnil;
-
+  
   count = SPECPDL_INDEX ();
   specbind (Qinhibit_redisplay, Qt);
   specbind (Qinhibit_quit, Qt);
-
+  
   if (!NILP (timer))
     call1 (Qcancel_timer, timer);
 
@@ -11580,7 +11686,7 @@
   dir = Fexpand_file_name (dir, Qnil);
   dir_xmstring = XmStringCreateLocalized (SDATA (dir));
   pattern_xmstring = XmStringCreateLocalized ("*");
-
+    
   XtSetArg (al[ac], XmNtitle, SDATA (prompt)); ++ac;
   XtSetArg (al[ac], XmNdirectory, dir_xmstring); ++ac;
   XtSetArg (al[ac], XmNpattern, pattern_xmstring); ++ac;
@@ -11603,7 +11709,7 @@
   help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
   XtSetSensitive (help, False);
 
-  /* Mark OK button as default.  */
+  /* Mark OK button as default.  */ 
   XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
 		 XmNshowAsDefault, True, NULL);
 
@@ -11663,7 +11769,7 @@
     {
       XmString text;
       String data;
-
+      
       XtVaGetValues (dialog, XmNtextString, &text, NULL);
       XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
       XmStringFree (text);
@@ -11682,12 +11788,64 @@
   /* Make "Cancel" equivalent to C-g.  */
   if (NILP (file))
     Fsignal (Qquit, Qnil);
-
+  
   return unbind_to (count, file);
 }
 
 #endif /* USE_MOTIF */
 
+#ifdef USE_GTK
+
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+  "Read file name, prompting with PROMPT in directory DIR.\n\
+Use a file selection dialog.\n\
+Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
+specified.  Don't let the user enter a file name in the file\n\
+selection dialog's entry field, if MUSTMATCH is non-nil.")
+  (prompt, dir, default_filename, mustmatch)
+     Lisp_Object prompt, dir, default_filename, mustmatch;
+{
+  FRAME_PTR f = SELECTED_FRAME ();
+  char *fn;
+  Lisp_Object file = Qnil;
+  int count = specpdl_ptr - specpdl;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  char *cdef_file;
+  char *cprompt;
+  
+  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  CHECK_STRING (prompt);
+  CHECK_STRING (dir);
+
+  /* Prevent redisplay.  */
+  specbind (Qinhibit_redisplay, Qt);
+
+  BLOCK_INPUT;
+
+  if (STRINGP (default_filename))
+    cdef_file = SDATA (default_filename);
+  else
+    cdef_file = SDATA (dir);
+
+  fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
+  
+  if (fn)
+    {
+      file = build_string (fn);
+      xfree (fn);
+    }
+
+  UNBLOCK_INPUT;
+  UNGCPRO;
+
+  /* Make "Cancel" equivalent to C-g.  */
+  if (NILP (file))
+    Fsignal (Qquit, Qnil);
+  
+  return unbind_to (count, file);
+}
+
+#endif /* USE_GTK */
 
 
 /***********************************************************************
@@ -11734,7 +11892,7 @@
       UNBLOCK_INPUT;
       return Qnil;
     }
-
+  
   have_keys = Qnil;
   kb = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
   if (kb)
@@ -11761,7 +11919,7 @@
 	}
 
       XkbFreeClientMap (kb, 0, True);
-
+  
       if (delete_keycode
 	  && backspace_keycode
 	  && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
@@ -11891,7 +12049,7 @@
   staticpro (&QCcolor_adjustment);
   QCmask = intern (":mask");
   staticpro (&QCmask);
-
+ 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
@@ -11959,7 +12117,7 @@
   DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
     doc: /* Non-zero means Emacs displays an hourglass pointer on window systems.  */);
   display_hourglass_p = 1;
-
+  
   DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
     doc: /* *Seconds to wait before displaying an hourglass pointer.
 Value must be an integer or float.  */);
@@ -11995,7 +12153,7 @@
     doc: /* Maximum size for tooltips.  Value is a pair (COLUMNS . ROWS).
 Text larger than this is clipped.  */);
   Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
-
+  
   DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
     doc: /* Non-nil if no X window manager is in use.
 Emacs doesn't try to figure this out; this is always nil
@@ -12064,7 +12222,7 @@
   defsubr (&Sx_synchronize);
   defsubr (&Sx_focus_frame);
   defsubr (&Sx_backspace_delete_keys_p);
-
+  
   /* Setting callback functions for fontset handler.  */
   get_font_info_func = x_get_font_info;
 
@@ -12072,7 +12230,7 @@
 	 And the pointer assigned has the wrong type, anyway.  */
   list_fonts_func = x_list_fonts;
 #endif
-
+  
   load_font_func = x_load_font;
   find_ccl_program_func = x_find_ccl_program;
   query_font_func = x_query_font;
@@ -12113,16 +12271,16 @@
   Qxpm = intern ("xpm");
   staticpro (&Qxpm);
 #endif
-
+  
 #if HAVE_JPEG
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
-#endif
+#endif 
 
 #if HAVE_TIFF
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
-#endif
+#endif 
 
 #if HAVE_GIF
   Qgif = intern ("gif");
@@ -12162,27 +12320,27 @@
 {
   image_types = NULL;
   Vimage_types = Qnil;
-
+  
   define_image_type (&xbm_type);
   define_image_type (&gs_type);
   define_image_type (&pbm_type);
-
+  
 #if HAVE_XPM
   define_image_type (&xpm_type);
 #endif
-
+  
 #if HAVE_JPEG
   define_image_type (&jpeg_type);
 #endif
-
+  
 #if HAVE_TIFF
   define_image_type (&tiff_type);
 #endif
-
+  
 #if HAVE_GIF
   define_image_type (&gif_type);
 #endif
-
+  
 #if HAVE_PNG
   define_image_type (&png_type);
 #endif
--- a/src/xmenu.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/xmenu.c	Sun Jan 19 21:50:03 2003 +0000
@@ -81,7 +81,9 @@
 #endif /* USE_LUCID */
 #include "../lwlib/lwlib.h"
 #else /* not USE_X_TOOLKIT */
+#ifndef USE_GTK
 #include "../oldXMenu/XMenu.h"
+#endif
 #endif /* not USE_X_TOOLKIT */
 #endif /* HAVE_X_WINDOWS */
 
@@ -116,6 +118,13 @@
 /* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
 
 #define HAVE_BOXES 1
+#endif /* USE_X_TOOLKIT */
+
+#ifdef USE_GTK
+#include "gtkutil.h"
+#define HAVE_BOXES 1
+extern void set_frame_menubar ();
+static Lisp_Object xdialog_show ();
 #endif
 
 static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
@@ -194,7 +203,7 @@
 
 /* Flag which when set indicates a dialog or menu has been posted by
    Xt on behalf of one of the widget sets.  */
-int popup_activated_flag;
+static int popup_activated_flag;
 
 static int next_menubar_widget_id;
 
@@ -593,7 +602,7 @@
   }
 #endif /* not HAVE_BOXES */
  
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   if (!NILP(map))
     /* Indicate visually that this is a submenu.  */
     item_string = concat2 (item_string, build_string (" >"));
@@ -606,7 +615,7 @@
 		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
 		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Display a submenu using the toolkit.  */
   if (! (NILP (map) || NILP (enabled)))
     {
@@ -771,6 +780,7 @@
 #ifdef HAVE_MENUS
   if (! NILP (position))
     {
+      int get_current_pos_p = 0;
       check_x ();
 
       /* Decode the first argument: find the window and the coordinates.  */
@@ -778,6 +788,38 @@
 	  || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
 				   || EQ (XCAR (position), Qtool_bar))))
 	{
+          get_current_pos_p = 1;
+        }
+      else
+	{
+	  tem = Fcar (position);
+	  if (CONSP (tem))
+	    {
+	      window = Fcar (Fcdr (position));
+	      x = Fcar (tem);
+	      y = Fcar (Fcdr (tem));
+	    }
+	  else
+	    {
+	      for_click = 1;
+	      tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
+	      window = Fcar (tem);	     /* POSN_WINDOW (tem) */
+	      tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
+	      x = Fcar (tem);
+	      y = Fcdr (tem);
+	    }
+
+          /* If a click happens in an external tool bar or a detached
+             tool bar, x and y is NIL.  In that case, use the current
+             mouse position.  This happens for the help button in the
+             tool bar.  Ideally popup-menu should pass NIL to
+             this function, but it doesn't.  */
+          if (NILP (x) && NILP (y))
+            get_current_pos_p = 1;
+	}
+
+      if (get_current_pos_p)
+        {
 	  /* Use the mouse's current position.  */
 	  FRAME_PTR new_f = SELECTED_FRAME ();
 #ifdef HAVE_X_WINDOWS
@@ -813,25 +855,6 @@
 	      XSETFASTINT (y, 0);
 	    }
 	}
-      else
-	{
-	  tem = Fcar (position);
-	  if (CONSP (tem))
-	    {
-	      window = Fcar (Fcdr (position));
-	      x = Fcar (tem);
-	      y = Fcar (Fcdr (tem));
-	    }
-	  else
-	    {
-	      for_click = 1;
-	      tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
-	      window = Fcar (tem);	     /* POSN_WINDOW (tem) */
-	      tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
-	      x = Fcar (tem);
-	      y = Fcdr (tem);
-	    }
-	}
 
       CHECK_NUMBER (x);
       CHECK_NUMBER (y);
@@ -1040,7 +1063,7 @@
        but I don't want to make one now.  */
     CHECK_WINDOW (window);
 
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Display a menu with these alternatives
      in the middle of frame F.  */
   {
@@ -1081,7 +1104,7 @@
 #endif
 }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 
 /* Loop in Xt until the menu pulldown or dialog popup has been
    popped down (deactivated).  This is used for x-popup-menu
@@ -1092,6 +1115,7 @@
    NOTE: All calls to popup_get_selection should be protected
    with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
 
+#ifdef USE_X_TOOLKIT
 static void
 popup_get_selection (initial_event, dpyinfo, id, do_timers)
      XEvent *initial_event;
@@ -1148,6 +1172,24 @@
     }
 }
 
+#endif /* USE_X_TOOLKIT */
+
+#ifdef USE_GTK
+/* Loop util popup_activated_flag is set to zero in a callback.
+   Used for popup menus and dialogs. */
+static void
+popup_widget_loop ()
+{
+  ++popup_activated_flag;
+
+  /* Process events in the Gtk event loop until done.  */
+  while (popup_activated_flag)
+    {
+      gtk_main_iteration ();
+    }
+}
+#endif
+
 /* Activate the menu bar of frame F.
    This is called from keyboard.c when it gets the
    MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
@@ -1169,9 +1211,20 @@
   if (!f->output_data.x->saved_menu_event->type)
     return;
 
+#ifdef USE_GTK  
+  if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window))
+    return;
+#endif
+  
   set_frame_menubar (f, 0, 1);
   BLOCK_INPUT;
+#ifdef USE_GTK
+  XPutBackEvent (f->output_data.x->display_info->display,
+                 f->output_data.x->saved_menu_event);
+  popup_activated_flag = 1;
+#else
   XtDispatchEvent (f->output_data.x->saved_menu_event);
+#endif
   UNBLOCK_INPUT;
 #ifdef USE_MOTIF
   if (f->output_data.x->saved_menu_event->type == ButtonRelease)
@@ -1193,6 +1246,7 @@
 /* This callback is invoked when the user selects a menubar cascade
    pushbutton, but before the pulldown menu is posted.  */
 
+#ifndef USE_GTK
 static void
 popup_activate_callback (widget, id, client_data)
      Widget widget;
@@ -1201,10 +1255,20 @@
 {
   popup_activated_flag = 1;
 }
+#endif
 
 /* This callback is invoked when a dialog or menu is finished being
    used and has been unposted.  */
 
+#ifdef USE_GTK
+static void
+popup_deactivate_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+{
+  popup_activated_flag = 0;
+}
+#else
 static void
 popup_deactivate_callback (widget, id, client_data)
      Widget widget;
@@ -1213,27 +1277,20 @@
 {
   popup_activated_flag = 0;
 }
-
-/* Lwlib callback called when menu items are highlighted/unhighlighted
-   while moving the mouse over them.  WIDGET is the menu bar or menu
-   popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
-   the widget_value structure for the menu item, or null in case of
-   unhighlighting.  */
-
-void
-menu_highlight_callback (widget, id, call_data)
-     Widget widget;
-     LWLIB_ID id;
-     void *call_data;
+#endif
+
+
+/* Function that finds the frame for WIDGET and shows the HELP text
+   for that widget.
+   F is the frame if known, or NULL if not known.  */
+static void
+show_help_event (f, widget, help)
+     FRAME_PTR f;
+     xt_or_gtk_widget widget;
+     Lisp_Object help;
 {
-  widget_value *wv = (widget_value *) call_data;
-  struct frame *f;
-  Lisp_Object frame, help;
-
-  help = wv ? wv->help : Qnil;
-  
-  /* Determine the frame for the help event.  */
-  f = menubar_id_to_frame (id);
+  Lisp_Object frame;
+
   if (f)
     {
       XSETFRAME (frame, f);
@@ -1243,7 +1300,7 @@
     {
       /* WIDGET is the popup menu.  It's parent is the frame's 
 	 widget.  See which frame that is.  */
-      Widget frame_widget = XtParent (widget);
+      xt_or_gtk_widget frame_widget = XtParent (widget);
       Lisp_Object tail;
 
       for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
@@ -1259,32 +1316,77 @@
     }
 }
 
-/* This callback is called from the menu bar pulldown menu
-   when the user makes a selection.
-   Figure out what the user chose
-   and put the appropriate events into the keyboard buffer.  */
-
-static void
-menubar_selection_callback (widget, id, client_data)
+/* Callback called when menu items are highlighted/unhighlighted
+   while moving the mouse over them.  WIDGET is the menu bar or menu
+   popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
+   the data structure for the menu item, or null in case of
+   unhighlighting.  */
+
+#ifdef USE_GTK
+void
+menu_highlight_callback (widget, call_data)
+     GtkWidget *widget;
+     gpointer call_data;
+{
+  xg_menu_item_cb_data *cb_data;
+  Lisp_Object help;
+  
+  cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
+                                                       XG_ITEM_DATA);
+  if (! cb_data) return;
+
+  help = call_data ? cb_data->help : Qnil;
+
+  /* If popup_activated_flag is greater than 1 we are in a popup menu.
+     Don't show help for them, they won't appear before the
+     popup is popped down.  */
+  if (popup_activated_flag <= 1)
+    show_help_event (cb_data->cl_data->f, widget, help);
+}
+#else
+void
+menu_highlight_callback (widget, id, call_data)
      Widget widget;
      LWLIB_ID id;
-     XtPointer client_data;
+     void *call_data;
+{
+  struct frame *f;
+  Lisp_Object help;
+
+  widget_value *wv = (widget_value *) call_data;
+
+  help = wv ? wv->help : Qnil;
+  
+  /* Determine the frame for the help event.  */
+  f = menubar_id_to_frame (id);
+
+  show_help_event (f, widget, help);
+}
+#endif
+
+/* Find the menu selection and store it in the keyboard buffer.
+   F is the frame the menu is on.
+   MENU_BAR_ITEMS_USED is the length of VECTOR.
+   VECTOR is an array of menu events for the whole menu.
+ */
+void
+find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
+     FRAME_PTR f;
+     int menu_bar_items_used;
+     Lisp_Object vector;
+     void *client_data;
 {
   Lisp_Object prefix, entry;
-  FRAME_PTR f = menubar_id_to_frame (id);
-  Lisp_Object vector;
   Lisp_Object *subprefix_stack;
   int submenu_depth = 0;
   int i;
 
-  if (!f)
-    return;
   entry = Qnil;
-  subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
-  vector = f->menu_bar_vector;
+  subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof (Lisp_Object));
   prefix = Qnil;
   i = 0;
-  while (i < f->menu_bar_items_used)
+
+  while (i < menu_bar_items_used)
     {
       if (EQ (XVECTOR (vector)->contents[i], Qnil))
 	{
@@ -1348,6 +1450,59 @@
     }
 }
 
+
+#ifdef USE_GTK
+/* Gtk calls callbacks just because we tell it what item should be
+   selected in a radio group.  If this variable is set to a non-zero
+   value, we are creating menus and don't want callbacks right now.
+*/
+static int xg_crazy_callback_abort;
+
+/* This callback is called from the menu bar pulldown menu
+   when the user makes a selection.
+   Figure out what the user chose
+   and put the appropriate events into the keyboard buffer.  */
+static void
+menubar_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+{
+  xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
+
+  if (xg_crazy_callback_abort)
+    return;
+
+  if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
+    return;
+
+  find_and_call_menu_selection (cb_data->cl_data->f,
+                                cb_data->cl_data->menu_bar_items_used,
+                                cb_data->cl_data->menu_bar_vector,
+                                cb_data->call_data);
+}
+
+#else /* not USE_GTK */
+
+/* This callback is called from the menu bar pulldown menu
+   when the user makes a selection.
+   Figure out what the user chose
+   and put the appropriate events into the keyboard buffer.  */
+static void
+menubar_selection_callback (widget, id, client_data)
+     Widget widget;
+     LWLIB_ID id;
+     XtPointer client_data;
+{
+  FRAME_PTR f;
+
+  f = menubar_id_to_frame (id);
+  if (!f)
+    return;
+  find_and_call_menu_selection (f, f->menu_bar_items_used,
+                                f->menu_bar_vector, client_data);
+}
+#endif /* not USE_GTK */
+
 /* Allocate a widget_value, blocking input.  */
 
 widget_value *
@@ -1623,9 +1778,12 @@
 update_frame_menubar (f)
      FRAME_PTR f;
 {
+#ifdef USE_GTK
+  return xg_update_frame_menubar (f);
+#else
   struct x_output *x = f->output_data.x;
   int columns, rows;
-
+  
   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
     return 0;
 
@@ -1657,6 +1815,7 @@
   /* Force the pane widget to resize itself with the right values.  */
   EmacsFrameSetCharSize (x->edit_widget, columns, rows);
   UNBLOCK_INPUT;
+#endif
   return 1;
 }
 
@@ -1670,21 +1829,25 @@
      int first_time;
      int deep_p;
 {
-  Widget menubar_widget = f->output_data.x->menubar_widget;
+  xt_or_gtk_widget menubar_widget = f->output_data.x->menubar_widget;
+#ifdef USE_X_TOOLKIT
+  LWLIB_ID id;
+#endif
   Lisp_Object items;
   widget_value *wv, *first_wv, *prev_wv = 0;
   int i, last_i;
   int *submenu_start, *submenu_end;
   int *submenu_top_level_items, *submenu_n_panes;
 
-  LWLIB_ID id;
 
   XSETFRAME (Vmenu_updating_frame, f);
 
+#ifdef USE_X_TOOLKIT
   if (f->output_data.x->id == 0)
     f->output_data.x->id = next_menubar_widget_id++;
   id = f->output_data.x->id;
-
+#endif
+  
   if (! menubar_widget)
     deep_p = 1;
   else if (pending_menu_activation && !deep_p)
@@ -1893,6 +2056,35 @@
 
   BLOCK_INPUT;
 
+#ifdef USE_GTK
+  xg_crazy_callback_abort = 1;
+  if (menubar_widget)
+    {
+      /* The third arg is DEEP_P, which says to consider the entire
+	 menu trees we supply, rather than just the menu bar item names.  */
+      xg_modify_menubar_widgets (menubar_widget,
+                                 f,
+                                 first_wv,
+                                 deep_p,
+                                 G_CALLBACK (menubar_selection_callback),
+                                 G_CALLBACK (popup_deactivate_callback),
+                                 G_CALLBACK (menu_highlight_callback));
+    }
+  else
+    {
+      GtkWidget *wvbox = f->output_data.x->vbox_widget;
+      
+      menubar_widget
+        = xg_create_widget ("menubar", "menubar", f, first_wv, 
+                            G_CALLBACK (menubar_selection_callback),
+                            G_CALLBACK (popup_deactivate_callback),
+                            G_CALLBACK (menu_highlight_callback));
+
+      f->output_data.x->menubar_widget = menubar_widget;
+    }
+
+  
+#else /* not USE_GTK */
   if (menubar_widget)
     {
       /* Disable resizing (done for Motif!) */
@@ -1939,10 +2131,15 @@
 
     f->output_data.x->menubar_height = menubar_size;
   }
+#endif /* not USE_GTK */
   
   free_menubar_widget_value_tree (first_wv);
   update_frame_menubar (f);
 
+#ifdef USE_GTK
+  xg_crazy_callback_abort = 0;
+#endif
+
   UNBLOCK_INPUT;
 }
 
@@ -1963,8 +2160,10 @@
 
 
 /* Get rid of the menu bar of frame F, and free its storage.
-   This is used when deleting a frame, and when turning off the menu bar.  */
-
+   This is used when deleting a frame, and when turning off the menu bar.
+   For GTK this function is in gtkutil.c.  */
+
+#ifndef USE_GTK
 void
 free_frame_menubar (f)
      FRAME_PTR f;
@@ -2011,8 +2210,9 @@
       UNBLOCK_INPUT;
     }
 }
-
-#endif /* USE_X_TOOLKIT */
+#endif /* not USE_GTK */
+
+#endif /* USE_X_TOOLKIT || USE_GTK */
 
 /* xmenu_show actually displays a menu using the panes and items in menu_items
    and returns the value selected from it.
@@ -2030,7 +2230,116 @@
    ERROR is a place to store an error message string in case of failure.
    (We return nil on failure, but the value doesn't actually matter.)  */
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+
+/* The item selected in the popup menu.  */
+static Lisp_Object *volatile menu_item_selection;
+
+#ifdef USE_GTK
+
+/* Used when position a popup menu.  See menu_position_func and
+   create_and_show_popup_menu below.  */
+struct next_popup_x_y
+{
+  int x;
+  int y;
+};
+
+/* The menu position function to use if we are not putting a popup
+   menu where the pointer is.
+   MENU is the menu to pop up.
+   X and Y shall on exit contain x/y where the menu shall pop up.
+   PUSH_IN is not documented in the GTK manual.
+   USER_DATA is any data passed in when calling gtk_menu_popup.
+   Here it points to a struct next_popup_x_y where the coordinates
+   to store in *X and *Y are.
+
+   Here only X and Y are used.  */
+static void
+menu_position_func (menu, x, y, push_in, user_data)
+     GtkMenu *menu;
+     gint *x;
+     gint *y;
+     gboolean *push_in;
+     gpointer user_data;
+{
+  *x = ((struct next_popup_x_y*)user_data)->x;
+  *y = ((struct next_popup_x_y*)user_data)->y;
+}
+
+static void
+popup_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+{
+  xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
+
+  if (xg_crazy_callback_abort) return;
+  if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
+}
+
+/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
+   menu pops down.
+   menu_item_selection will be set to the selection.  */
+static void
+create_and_show_popup_menu (f, first_wv, x, y, for_click)
+     FRAME_PTR f;
+     widget_value *first_wv;
+     int x;
+     int y;
+     int for_click;
+{
+  int i;
+  GtkWidget *menu;
+  GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
+  struct next_popup_x_y popup_x_y;
+
+  xg_crazy_callback_abort = 1;
+  menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
+                           G_CALLBACK (popup_selection_callback),
+                           G_CALLBACK (popup_deactivate_callback),
+                           G_CALLBACK (menu_highlight_callback));
+  xg_crazy_callback_abort = 0;
+  
+  for (i = 0; i < 5; i++)
+    if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+      break;
+
+  if (! for_click)
+    {
+      /* Not invoked by a click.  pop up at x/y.  */
+      pos_func = menu_position_func;
+
+      /* Adjust coordinates to be root-window-relative.  */
+      x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+      y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+
+      popup_x_y.x = x;
+      popup_x_y.y = y;
+    }
+
+  /* Display the menu.  */
+  gtk_widget_show_all (menu);
+  gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
+  
+  xg_did_tearoff = 0;
+  /* Set this to one.  popup_widget_loop increases it by one, so it becomes
+     two.  show_help_echo uses this to detect popup menus.  */
+  popup_activated_flag = 1;
+  /* Process events that apply to the menu.  */
+  popup_widget_loop ();
+
+  if (xg_did_tearoff)
+    xg_keep_popup (menu, xg_did_tearoff);
+  else
+    gtk_widget_destroy (menu);
+    
+  /* Must reset this manually because the button release event is not passed
+     to Emacs event loop. */
+  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+}
+
+#else /* not USE_GTK */
 
 /* We need a unique id for each widget handled by the Lucid Widget
    library.
@@ -2042,8 +2351,6 @@
    next_menubar_widget_id.  */
 LWLIB_ID widget_id_tick;
 
-static Lisp_Object *volatile menu_item_selection;
-
 static void
 popup_selection_callback (widget, id, client_data)
      Widget widget;
@@ -2053,6 +2360,76 @@
   menu_item_selection = (Lisp_Object *) client_data;
 }
 
+/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
+   menu pops down.
+   menu_item_selection will be set to the selection.  */
+static void
+create_and_show_popup_menu (f, first_wv, x, y, for_click)
+     FRAME_PTR f;
+     widget_value *first_wv;
+     int x;
+     int y;
+     int for_click;
+{
+  int i;
+  Arg av[2];
+  int ac = 0;
+  XButtonPressedEvent dummy;
+  LWLIB_ID menu_id;
+  Widget menu;
+  Window child;
+
+  menu_id = widget_id_tick++;
+  menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
+                           f->output_data.x->widget, 1, 0,
+                           popup_selection_callback,
+                           popup_deactivate_callback,
+                           menu_highlight_callback);
+
+  dummy.type = ButtonPress;
+  dummy.serial = 0;
+  dummy.send_event = 0;
+  dummy.display = FRAME_X_DISPLAY (f);
+  dummy.time = CurrentTime;
+  dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
+  dummy.window = dummy.root;
+  dummy.subwindow = dummy.root;
+  dummy.x = x;
+  dummy.y = y;
+
+  /* Adjust coordinates to be root-window-relative.  */
+  x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+  y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+
+  dummy.x_root = x;
+  dummy.y_root = y;
+
+  dummy.state = 0;
+  dummy.button = 0;
+  for (i = 0; i < 5; i++)
+    if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+      dummy.button = i;
+
+  /* Don't allow any geometry request from the user.  */
+  XtSetArg (av[ac], XtNgeometry, 0); ac++;
+  XtSetValues (menu, av, ac);
+
+  /* Display the menu.  */
+  lw_popup_menu (menu, (XEvent *) &dummy);
+  popup_activated_flag = 1;
+
+  /* Process events that apply to the menu.  */
+  popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0);
+
+  /* fp turned off the following statement and wrote a comment
+     that it is unnecessary--that the menu has already disappeared.
+     Nowadays the menu disappears ok, all right, but
+     we need to delete the widgets or multiple ones will pile up.  */
+  lw_destroy_all_widgets (menu_id); 
+}
+
+#endif /* not USE_GTK */
+
 static Lisp_Object
 xmenu_show (f, x, y, for_click, keymaps, title, error)
      FRAME_PTR f;
@@ -2064,17 +2441,12 @@
      char **error;
 {
   int i;
-  LWLIB_ID menu_id;
-  Widget menu;
-  Arg av[2];
-  int ac = 0;
   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
   widget_value **submenu_stack
     = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
   Lisp_Object *subprefix_stack
     = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
   int submenu_depth = 0;
-  XButtonPressedEvent dummy;
 
   int first_pane;
 
@@ -2266,71 +2638,15 @@
       first_wv->contents = wv_title;
     }
 
-  /* Actually create the menu.  */
-  menu_id = widget_id_tick++;
-  menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
-			   f->output_data.x->widget, 1, 0,
-			   popup_selection_callback,
-			   popup_deactivate_callback,
-			   menu_highlight_callback);
-  
-  /* See if whe positions are up to date.  Temporary code to be removed
-     when we are sure positions are always up to date.  */
-  {
-    int real_x, real_y;
-    x_real_positions (f, &real_x, &real_y);
-
-    if (real_x != f->output_data.x->left_pos ||
-        real_y != f->output_data.x->top_pos)
-      abort ();
-  }
-
-  dummy.type = ButtonPress;
-  dummy.serial = 0;
-  dummy.send_event = 0;
-  dummy.display = FRAME_X_DISPLAY (f);
-  dummy.time = CurrentTime;
-  dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
-  dummy.window = dummy.root;
-  dummy.subwindow = dummy.root;
-  dummy.x = x;
-  dummy.y = y;
-
-  /* Adjust coordinates to be root-window-relative.  */
-  x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
-  y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-  
-  dummy.x_root = x;
-  dummy.y_root = y;
-  dummy.state = 0;
-  dummy.button = 0;
-  for (i = 0; i < 5; i++)
-    if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
-      dummy.button = i;
-
-  /* Don't allow any geometry request from the user.  */
-  XtSetArg (av[ac], XtNgeometry, 0); ac++;
-  XtSetValues (menu, av, ac);
+  /* No selection has been chosen yet.  */
+  menu_item_selection = 0;
+
+  /* Actually create and show the menu until popped down.  */
+  create_and_show_popup_menu (f, first_wv, x, y, for_click);
 
   /* Free the widget_value objects we used to specify the contents.  */
   free_menubar_widget_value_tree (first_wv);
 
-  /* No selection has been chosen yet.  */
-  menu_item_selection = 0;
-
-  /* Display the menu.  */
-  lw_popup_menu (menu, (XEvent *) &dummy);
-  popup_activated_flag = 1;
-
-  /* Process events that apply to the menu.  */
-  popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0);
-
-  /* fp turned off the following statement and wrote a comment
-     that it is unnecessary--that the menu has already disappeared.
-     Nowadays the menu disappears ok, all right, but
-     we need to delete the widgets or multiple ones will pile up.  */
-  lw_destroy_all_widgets (menu_id); 
-
   /* Find the selected item, and its pane, to return
      the proper value.  */
   if (menu_item_selection != 0)
@@ -2389,6 +2705,48 @@
   return Qnil;
 }
 
+#ifdef USE_GTK
+static void
+dialog_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+{
+  /* The EMACS_INT cast avoids a warning.  There's no problem
+     as long as pointers have enough bits to hold small integers.  */
+  if ((int) (EMACS_INT) client_data != -1)
+    menu_item_selection = (Lisp_Object *) client_data;
+
+  popup_activated_flag = 0;
+}
+
+/* Pop up the dialog for frame F defined by FIRST_WV and loop until the
+   dialog pops down.
+   menu_item_selection will be set to the selection.  */
+static void
+create_and_show_dialog (f, first_wv)
+     FRAME_PTR f;
+     widget_value *first_wv;
+{
+  GtkWidget *menu;
+
+  menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
+                           G_CALLBACK (dialog_selection_callback),
+                           G_CALLBACK (popup_deactivate_callback),
+                           0);
+
+  if (menu)
+    {
+      /* Display the menu.  */
+      gtk_widget_show_all (menu);
+
+      /* Process events that apply to the menu.  */
+      popup_widget_loop ();
+  
+      gtk_widget_destroy (menu);
+    }
+}
+
+#else /* not USE_GTK */
 static void
 dialog_selection_callback (widget, id, client_data)
      Widget widget;
@@ -2399,12 +2757,14 @@
      as long as pointers have enough bits to hold small integers.  */
   if ((int) (EMACS_INT) client_data != -1)
     menu_item_selection = (Lisp_Object *) client_data;
+
   BLOCK_INPUT;
   lw_destroy_all_widgets (id);
   UNBLOCK_INPUT;
   popup_activated_flag = 0;
 }
 
+
 /* ARG is the LWLIB ID of the dialog box, represented
    as a Lisp object as (HIGHPART . LOWPART).  */
 
@@ -2421,6 +2781,46 @@
   return Qnil;
 }
 
+
+/* Pop up the dialog for frame F defined by FIRST_WV and loop until the
+   dialog pops down.
+   menu_item_selection will be set to the selection.  */
+static void
+create_and_show_dialog (f, first_wv)
+     FRAME_PTR f;
+     widget_value *first_wv;
+{
+  LWLIB_ID dialog_id;
+
+  dialog_id = widget_id_tick++;
+  lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
+                    f->output_data.x->widget, 1, 0,
+                    dialog_selection_callback, 0, 0);
+  lw_modify_all_widgets (dialog_id, first_wv->contents, True);
+
+  /* Display the dialog box.  */
+  lw_pop_up_all_widgets (dialog_id);
+  popup_activated_flag = 1;
+
+  /* Process events that apply to the dialog box.
+     Also handle timers.  */
+  {
+    int count = SPECPDL_INDEX ();
+    int fact = 4 * sizeof (LWLIB_ID);
+    
+    /* xdialog_show_unwind is responsible for popping the dialog box down.  */
+    record_unwind_protect (xdialog_show_unwind,
+                           Fcons (make_number (dialog_id >> (fact)),
+                                  make_number (dialog_id & ~(-1 << (fact)))));
+
+    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
+
+    unbind_to (count, Qnil);
+  }
+}
+
+#endif /* not USE_GTK */
+
 static char * button_names [] = {
   "button1", "button2", "button3", "button4", "button5",
   "button6", "button7", "button8", "button9", "button10" };
@@ -2433,7 +2833,6 @@
      char **error;
 {
   int i, nb_buttons=0;
-  LWLIB_ID dialog_id;
   char dialog_name[6];
 
   widget_value *wv, *first_wv = 0, *prev_wv = 0;
@@ -2543,38 +2942,17 @@
     first_wv = wv;
   }
 
-  /* Actually create the dialog.  */
-  dialog_id = widget_id_tick++;
-  lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
-		    f->output_data.x->widget, 1, 0,
-		    dialog_selection_callback, 0, 0);
-  lw_modify_all_widgets (dialog_id, first_wv->contents, True);
-  /* Free the widget_value objects we used to specify the contents.  */
-  free_menubar_widget_value_tree (first_wv);
-
   /* No selection has been chosen yet.  */
   menu_item_selection = 0;
 
-  /* Display the dialog box.  */
-  lw_pop_up_all_widgets (dialog_id);
-  popup_activated_flag = 1;
-
-  /* Process events that apply to the dialog box.
-     Also handle timers.  */
-  {
-    int count = SPECPDL_INDEX ();
-
-    /* xdialog_show_unwind is responsible for popping the dialog box down.  */
-    record_unwind_protect (xdialog_show_unwind,
-			   Fcons (make_number (dialog_id >> (4 * sizeof (LWLIB_ID))),
-				  make_number (dialog_id & ~(-1 << (4 * sizeof (LWLIB_ID))))));
-
-    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
-
-    unbind_to (count, Qnil);
-  }
-
-  /* Find the selected item and pane, and return the corresponding value.  */
+  /* Actually create and show the dialog.  */
+  create_and_show_dialog (f, first_wv);
+
+  /* Free the widget_value objects we used to specify the contents.  */
+  free_menubar_widget_value_tree (first_wv);
+  
+  /* Find the selected item, and its pane, to return
+     the proper value.  */
   if (menu_item_selection != 0)
     {
       Lisp_Object prefix;
@@ -2619,7 +2997,7 @@
   return Qnil;
 }
 
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
 
 /* The frame of the last activated non-toolkit menu bar.
    Used to generate menu help events.  */
--- a/src/xterm.c	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/xterm.c	Sun Jan 19 21:50:03 2003 +0000
@@ -97,17 +97,23 @@
 #include <unistd.h>
 #endif
 
+#ifdef USE_GTK
+#include "gtkutil.h"
+#endif
+
 #ifdef USE_LUCID
 extern int xlwmenu_window_p P_ ((Widget w, Window window));
 extern void xlwmenu_redisplay P_ ((Widget));
 #endif
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 
 extern void free_frame_menubar P_ ((struct frame *));
 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
 						    int));
-
+#endif
+
+#ifdef USE_X_TOOLKIT
 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
 #define HACK_EDITRES
 extern void _XEditResCheckMessages ();
@@ -138,7 +144,7 @@
 
 #endif /* USE_X_TOOLKIT */
 
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 #define x_any_window_to_frame x_window_to_frame
 #define x_top_window_to_frame x_window_to_frame
 #endif
@@ -520,6 +526,12 @@
 					    unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_fullscreen_move P_ ((struct frame *));
+static int handle_one_xevent P_ ((struct x_display_info *,
+                                  XEvent *,
+                                  struct input_event **,
+                                  int *,
+                                  int *));
+
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -4330,6 +4342,7 @@
 
   height = s->height - 2 * box_line_vwidth;
 
+
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
@@ -7074,7 +7087,7 @@
   struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (popup_activated ())
     return;
 #endif
@@ -8399,7 +8412,7 @@
 x_process_timeouts (timer)
      struct atimer *timer;
 {
-  if (toolkit_scroll_bar_interaction || popup_activated_flag)
+  if (toolkit_scroll_bar_interaction || popup_activated ())
     {
       BLOCK_INPUT;
       while (XtAppPending (Xt_app_con) & XtIMTimer)
@@ -8494,10 +8507,6 @@
 						int, int, int));
 
 
-/* Id of action hook installed for scroll bars.  */
-
-static XtActionHookId action_hook_id;
-
 /* Lisp window being scrolled.  Set when starting to interact with
    a toolkit scroll bar, reset to nil when ending the interaction.  */
 
@@ -8510,6 +8519,11 @@
 /* Whether this is an Xaw with arrow-scrollbars.  This should imply
    that movements of 1/20 of the screen size are mapped to up/down.  */
 
+#ifndef USE_GTK
+/* Id of action hook installed for scroll bars.  */
+
+static XtActionHookId action_hook_id;
+
 static Boolean xaw3d_arrow_scroll;
 
 /* Whether the drag scrolling maintains the mouse at the top of the
@@ -8562,6 +8576,7 @@
       toolkit_scroll_bar_interaction = 0;
     }
 }
+#endif /* not USE_GTK */
 
 /* A vector of windows used for communication between
    x_send_scroll_bar_event and x_scroll_bar_to_input_event.  */
@@ -8655,7 +8670,11 @@
   ievent->kind = SCROLL_BAR_CLICK_EVENT;
   ievent->frame_or_window = window;
   ievent->arg = Qnil;
+#ifdef USE_GTK
+  ievent->timestamp = CurrentTime;
+#else
   ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
+#endif
   ievent->part = ev->data.l[1];
   ievent->code = ev->data.l[2];
   ievent->x = make_number ((int) ev->data.l[3]);
@@ -8749,8 +8768,80 @@
 }
 
 
-#else /* !USE_MOTIF, i.e. Xaw.  */
-
+#else /* !USE_MOTIF, i.e. Xaw or GTK */
+#ifdef USE_GTK
+/* Scroll bar callback for Gtk scroll bars.  WIDGET is the scroll
+   bar adjustment widget.  DATA is a pointer to the scroll_bar structure. */
+
+static void
+xg_scroll_callback (widget, data)
+     GtkWidget *widget;
+     gpointer data;
+{
+  struct scroll_bar *bar = (struct scroll_bar *) data;
+  gdouble previous;
+  gdouble position;
+  gdouble *p;
+  int diff;
+  
+  int part = -1, whole = 0, portion = 0;
+  GtkAdjustment *adj = GTK_ADJUSTMENT (widget);
+  
+  if (xg_ignore_gtk_scrollbar) return;
+  
+  position = gtk_adjustment_get_value (adj);
+
+  p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
+  if (! p)
+    {
+      p = (gdouble*) xmalloc (sizeof (gdouble));
+      *p = XG_SB_MIN;
+      g_object_set_data (G_OBJECT (widget), XG_LAST_SB_DATA, p);
+    }
+
+  previous = *p;
+  *p = position;
+
+  diff = (int) (position - previous);
+  
+  if (diff == (int) adj->step_increment)
+    {
+      part = scroll_bar_down_arrow;
+      bar->dragging = Qnil;
+    }
+  else if (-diff == (int) adj->step_increment)
+    {
+      part = scroll_bar_up_arrow;
+      bar->dragging = Qnil;
+    }
+  else if (diff == (int) adj->page_increment)
+    {
+      part = scroll_bar_below_handle;
+      bar->dragging = Qnil;
+    }
+  else if (-diff == (int) adj->page_increment)
+    {
+      part = scroll_bar_above_handle;
+      bar->dragging = Qnil;
+    }
+  else
+    {
+      part = scroll_bar_handle;
+      whole = adj->upper - adj->page_size;
+      portion = min (position, whole);
+      bar->dragging = make_number (portion);
+    }
+  
+  if (part >= 0)
+    {
+      xg_ignore_next_thumb = 1;
+      window_being_scrolled = bar->window;
+      last_scroll_bar_part = part;
+      x_send_scroll_bar_event (bar->window, part, portion, whole);
+    }
+}
+
+#else /* not USE_GTK */
 
 /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
    WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
@@ -8833,13 +8924,30 @@
   x_send_scroll_bar_event (bar->window, part, position, height);
 }
 
-
+#endif /* not USE_GTK */
 #endif /* not USE_MOTIF */
 
+#define SCROLL_BAR_NAME "verticalScrollBar"
 
 /* Create the widget for scroll bar BAR on frame F.  Record the widget
    and X window of the scroll bar in BAR.  */
 
+#ifdef USE_GTK
+static void
+x_create_toolkit_scroll_bar (f, bar)
+     struct frame *f;
+     struct scroll_bar *bar;
+{
+  char *scroll_bar_name = SCROLL_BAR_NAME;
+
+  BLOCK_INPUT;
+  xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+                        scroll_bar_name);
+  UNBLOCK_INPUT;
+}
+
+#else /* not USE_GTK */
+
 static void
 x_create_toolkit_scroll_bar (f, bar)
      struct frame *f;
@@ -8849,7 +8957,7 @@
   Widget widget;
   Arg av[20];
   int ac = 0;
-  char *scroll_bar_name = "verticalScrollBar";
+  char *scroll_bar_name = SCROLL_BAR_NAME;
   unsigned long pixel;
 
   BLOCK_INPUT;
@@ -9022,11 +9130,22 @@
 
   UNBLOCK_INPUT;
 }
+#endif /* not USE_GTK */
 
 
 /* Set the thumb size and position of scroll bar BAR.  We are currently
    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
 
+#ifdef USE_GTK
+static void
+x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
+     struct scroll_bar *bar;
+     int portion, position, whole;
+{
+  xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+}
+
+#else /* not USE_GTK */
 static void
 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      struct scroll_bar *bar;
@@ -9149,6 +9268,7 @@
 
   UNBLOCK_INPUT;
 }
+#endif /* not USE_GTK */
 
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
@@ -9237,6 +9357,15 @@
   /* Map the window/widget.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
   {
+#ifdef USE_GTK
+    xg_update_scrollbar_pos (f,
+                             SCROLL_BAR_X_WINDOW (bar),
+                             top,
+                             left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                             width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                             max (height, 1));
+    xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
+#else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
     XtConfigureWidget (scroll_bar,
 		       left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
@@ -9244,6 +9373,7 @@
 		       width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
 		       max (height, 1), 0);
     XtMapWidget (scroll_bar);
+#endif /* not USE_GTK */
     }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
@@ -9378,7 +9508,11 @@
   BLOCK_INPUT;
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_GTK
+  xg_remove_scroll_bar (f, SCROLL_BAR_X_WINDOW (bar));
+#else /* not USE_GTK */
   XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
+#endif /* not USE_GTK */
 #else
   XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
 #endif
@@ -9472,20 +9606,30 @@
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
+#ifdef USE_GTK
+      if (mask)
+        xg_update_scrollbar_pos (f,
+                                 SCROLL_BAR_X_WINDOW (bar),
+                                 top,
+                                 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                                 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                                 max (height, 1));
+#else /* not USE_GTK */
+
       /* Since toolkit scroll bars are smaller than the space reserved
-	 for them on the frame, we have to clear "under" them.  */
+         for them on the frame, we have to clear "under" them.  */
       if (width > 0 && height > 0)
-	x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-		      left, top, width, height, False);
-
+        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          left, top, width, height, False);
       /* Move/size the scroll bar widget.  */
       if (mask)
-	XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
-			   sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-			   top,
-			   sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-			   max (height, 1), 0);
-
+          XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
+                             sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                             top,
+                             sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                             max (height, 1), 0);
+
+#endif /* not USE_GTK */
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
@@ -10070,6 +10214,41 @@
   X_EVENT_DROP
 };
 
+#ifdef USE_GTK
+static struct x_display_info *current_dpyinfo;
+static struct input_event **current_bufp;
+static int *current_numcharsp;
+static int current_count;
+static int current_finish;
+
+/* This is the filter function invoked by the GTK event loop.
+   It is invoked before the XEvent is translated to a GdkEvent,
+   so we have a chanse to act on the event before GTK. */
+static GdkFilterReturn
+event_handler_gdk (gxev, ev, data)
+     GdkXEvent *gxev;
+     GdkEvent *ev;
+     gpointer data;
+{
+  XEvent *xev = (XEvent*)gxev;
+
+  if (current_numcharsp)
+    current_count += handle_one_xevent (current_dpyinfo,
+                                        xev,
+                                        current_bufp,
+                                        current_numcharsp,
+                                        &current_finish);
+  else
+    x_dispatch_event (xev, GDK_DISPLAY ());
+
+  if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
+    return GDK_FILTER_REMOVE;
+
+  return GDK_FILTER_CONTINUE;
+}
+#endif /* USE_GTK */
+
+
 /* Handles the XEvent EVENT on display DPYINFO.
    
    *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@@ -10079,7 +10258,7 @@
    Events representing keys are stored in buffer *BUFP_R,
    which can hold up to *NUMCHARSP characters.
    We return the number of characters stored into the buffer. */
-
+   
 static int
 handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
      struct x_display_info *dpyinfo;
@@ -10097,7 +10276,7 @@
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
-
+  
   switch (event.type)
     {
     case ClientMessage:
@@ -10514,8 +10693,9 @@
     case KeyPress:
 
       /* Dispatch KeyPress events when in menu.  */
-      if (popup_activated_flag)
+      if (popup_activated ())
         goto OTHER;
+
       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
@@ -11080,6 +11260,10 @@
       if (f)
         {
 #ifndef USE_X_TOOLKIT
+#ifdef USE_GTK
+          xg_resize_widgets (f, event.xconfigure.width,
+                             event.xconfigure.height);
+#else /* not USE_GTK */
           /* If there is a pending resize for fullscreen, don't
              do this one, the right one will come later.
              The toolkit version doesn't seem to need this, but we
@@ -11108,20 +11292,31 @@
               SET_FRAME_GARBAGED (f);
               cancel_mouse_face (f);
             }
+#endif /* not USE_GTK */
 #endif
 
           f->output_data.x->pixel_width = event.xconfigure.width;
           f->output_data.x->pixel_height = event.xconfigure.height;
 
+#ifdef USE_GTK
+          /* GTK creates windows but doesn't map them.
+             Only get real positions and check fullscreen when mapped. */
+          if (FRAME_GTK_OUTER_WIDGET (f)
+              && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
+            {
+#endif
           /* What we have now is the position of Emacs's own window.
              Convert that to the position of the window manager window.  */
           x_real_positions (f, &f->output_data.x->left_pos,
                             &f->output_data.x->top_pos);
 
-          x_check_fullscreen_move(f);
+          x_check_fullscreen_move (f);
           if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
             f->output_data.x->want_fullscreen &=
               ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+#ifdef USE_GTK
+            }
+#endif
 #ifdef HAVE_X_I18N
           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
             xic_set_statusarea (f);
@@ -11137,8 +11332,8 @@
         }
       goto OTHER;
 
+    case ButtonRelease:
     case ButtonPress:
-    case ButtonRelease:
       {
         /* If we decide we want to generate an event to be seen
            by the rest of Emacs, we put it here.  */
@@ -11179,7 +11374,10 @@
             if (!tool_bar_p)
               if (!dpyinfo->x_focus_frame
                   || f == dpyinfo->x_focus_frame)
-                construct_mouse_click (&emacs_event, &event, f);
+                {
+                  if (! popup_activated ())
+                    construct_mouse_click (&emacs_event, &event, f);
+                }
           }
         else
           {
@@ -11207,9 +11405,7 @@
               last_tool_bar_item = -1;
           }
         else
-          {
-            dpyinfo->grabbed &= ~(1 << event.xbutton.button);
-          }
+          dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
         if (numchars >= 1 && emacs_event.kind != NO_EVENT)
           {
@@ -11219,14 +11415,19 @@
             numchars--;
           }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
         /* For a down-event in the menu bar,
            don't pass it to Xt right now.
            Instead, save it away
            and we will pass it to Xt from kbd_buffer_get_event.
            That way, we can run some Lisp code first.  */
-        if (f && event.type == ButtonPress
+        if (
+#ifdef USE_GTK
+            ! popup_activated ()
+            &&
+#endif
+            f && event.type == ButtonPress
             /* Verify the event is really within the menu bar
                and not just sent to it due to grabbing.  */
             && event.xbutton.x >= 0
@@ -11237,6 +11438,9 @@
           {
             SET_SAVED_BUTTON_EVENT;
             XSETFRAME (last_mouse_press_frame, f);
+#ifdef USE_GTK
+            *finish = X_EVENT_DROP;
+#endif
           }
         else if (event.type == ButtonPress)
           {
@@ -11260,7 +11464,7 @@
 #endif /* USE_MOTIF */
         else
           goto OTHER;
-#endif /* USE_X_TOOLKIT */
+#endif /* USE_X_TOOLKIT || USE_GTK */
       }
       break;
 
@@ -11297,7 +11501,7 @@
     }
 
   goto ret;
-
+  
  out:
   *finish = X_EVENT_GOTO_OUT;
 
@@ -11427,6 +11631,31 @@
       UNBLOCK_INPUT;
 #endif
 
+#ifdef USE_GTK
+      /* For GTK we must use the GTK event loop.  But XEvents gets passed
+         to our filter function above, and then to the big event switch.
+         We use a bunch of globals to communicate with our filter function,
+         that is kind of ugly, but it works. */
+      current_dpyinfo = dpyinfo;
+      
+      while (gtk_events_pending ())
+        {
+          static int nr = 0;
+          current_count = count;
+          current_numcharsp = &numchars;
+          current_bufp = &bufp;
+
+          gtk_main_iteration ();
+
+          count = current_count;
+          current_bufp = 0;
+          current_numcharsp = 0;
+
+          if (current_finish == X_EVENT_GOTO_OUT)
+            goto out;
+        }
+
+#else /* not USE_GTK */
       while (XPending (dpyinfo->display))
 	{
           int finish;
@@ -11457,6 +11686,7 @@
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
         }
+#endif /* USE_GTK */
     }
 
  out:;
@@ -12922,11 +13152,7 @@
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
-#ifdef USE_X_TOOLKIT
-  this_window = XtWindow (f->output_data.x->widget);
-#else
-  this_window = FRAME_X_WINDOW (f);
-#endif
+  this_window = FRAME_OUTER_WINDOW (f);
 
   /* Find the position of the outside upper-left corner of
      the inner window, with respect to the outer window.
@@ -13057,13 +13283,8 @@
     }
 #endif
 
-#ifdef USE_X_TOOLKIT
-  XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
-	       modified_left, modified_top);
-#else /* not USE_X_TOOLKIT */
-  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-	       modified_left, modified_top);
-#endif /* not USE_X_TOOLKIT */
+  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+               modified_left, modified_top);
   UNBLOCK_INPUT;
 }
 
@@ -13249,7 +13470,12 @@
 {
   BLOCK_INPUT;
 
-#ifdef USE_X_TOOLKIT
+#ifdef USE_GTK
+  if (FRAME_GTK_WIDGET (f))
+    xg_frame_set_char_size (f, cols, rows);
+  else
+    x_set_window_size_1 (f, change_gravity, cols, rows);
+#elif USE_X_TOOLKIT
 
   if (f->output_data.x->widget != NULL)
     {
@@ -13445,7 +13671,11 @@
       /* This was XtPopup, but that did nothing for an iconified frame.  */
       XtMapWidget (f->output_data.x->widget);
 #else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+      gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+#else
       XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
 #if 0 /* This seems to bring back scroll bars in the wrong places
 	 if the window configuration has changed.  They seem
@@ -13596,6 +13826,14 @@
      by hand again (they have already done that once for this window.)  */
   x_wm_set_size_hint (f, (long) 0, 1);
 
+#ifdef USE_GTK
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    {
+      gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
+      goto out;
+    }
+#endif
+
 #ifdef HAVE_X11R4
 
   if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
@@ -13630,6 +13868,7 @@
   XUnmapWindow (FRAME_X_DISPLAY (f), window);
 #endif /* ! defined (HAVE_X11R4) */
 
+ out:
   /* We can't distinguish this from iconification
      just by the event that we get from the server.
      So we can't win using the usual strategy of letting
@@ -13669,6 +13908,22 @@
   if (!NILP (type))
     x_bitmap_icon (f, type);
 
+#ifdef USE_GTK
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    {
+      if (! FRAME_VISIBLE_P (f))
+        gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+
+      gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+      f->iconified = 1;
+      f->visible = 1;
+      f->async_iconified = 1;
+      f->async_visible = 0;
+      UNBLOCK_INPUT;
+      return;
+    }
+#endif
+
 #ifdef USE_X_TOOLKIT
 
   if (! FRAME_VISIBLE_P (f))
@@ -13803,6 +14058,18 @@
 
       free_frame_menubar (f);
 #else  /* !USE_X_TOOLKIT */
+
+#ifdef USE_GTK
+      /* In the GTK version, tooltips are normal X
+         frames.  We must check and free both types. */
+      if (FRAME_GTK_OUTER_WIDGET (f))
+        {
+          gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+          FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
+          FRAME_GTK_OUTER_WIDGET (f) = 0;
+        }
+#endif /* USE_GTK */
+          
       if (FRAME_X_WINDOW (f))
 	XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* !USE_X_TOOLKIT */
@@ -13888,8 +14155,10 @@
    FLAGS is the flags word to use--or 0 meaning preserve the flags
    that the window now has.
    If USER_POSITION is nonzero, we set the USPosition
-   flag (this is useful when FLAGS is 0).  */
-
+   flag (this is useful when FLAGS is 0).
+   The GTK version is in gtkutils.c  */
+
+#ifndef USE_GTK
 void
 x_wm_set_size_hint (f, flags, user_position)
      struct frame *f;
@@ -13902,10 +14171,9 @@
   Arg al[2];
   int ac = 0;
   Dimension widget_width, widget_height;
-  Window window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
-  Window window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
+#endif
+  
+  Window window = FRAME_OUTER_WINDOW (f);
 
   /* Setting PMaxSize caused various problems.  */
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
@@ -14032,6 +14300,7 @@
   XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
 #endif
 }
+#endif /* not USE_GTK */
 
 /* Used for IconicState or NormalState */
 
@@ -14063,7 +14332,7 @@
   Pixmap icon_pixmap;
 
 #ifndef USE_X_TOOLKIT
-  Window window = FRAME_X_WINDOW (f);
+  Window window = FRAME_OUTER_WINDOW (f);
 #endif
 
   if (pixmap_id > 0)
@@ -14864,6 +15133,67 @@
       x_initialized = 1;
     }
 
+#ifdef USE_GTK
+  {
+#define NUM_ARGV 10
+    int argc;
+    char *argv[NUM_ARGV];
+    char **argv2 = argv;
+    GdkAtom atom;
+
+    /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
+       than one, but this remains to be implemented.  */
+    if (x_initialized > 1)
+      return 0;
+
+    x_initialized++;
+
+    for (argc = 0; argc < NUM_ARGV; ++argc)
+      argv[argc] = 0;
+
+    argc = 0;
+    argv[argc++] = initial_argv[0];
+
+    if (! NILP (display_name))
+      {
+        argv[argc++] = "--display";
+        argv[argc++] = SDATA (display_name);
+      }
+
+    argv[argc++] = "--name";
+    argv[argc++] = resource_name;
+    
+    gtk_init (&argc, &argv2);
+
+    /* gtk_init does set_locale.  We must fix locale after calling it.  */
+    fixup_locale ();
+    xg_initialize ();
+
+    dpy = GDK_DISPLAY ();
+    
+    /* NULL window -> events for all windows go to our function */
+    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+
+    /* Load our own gtkrc if it exists.  */
+    {
+      struct gcpro gcpro1, gcpro2;
+      char *file = "~/.emacs.d/gtkrc";
+      Lisp_Object s, abs_file;
+
+      GCPRO2 (str, abs_file);
+      s = make_string (file, strlen (file));
+      abs_file = Fexpand_file_name(s, Qnil);
+
+      if (! NILP (abs_file) && Ffile_readable_p (abs_file))
+        gtk_rc_parse (SDATA (abs_file));
+      
+      UNGCPRO;
+    }
+    
+    XSetErrorHandler (x_error_handler);
+    XSetIOErrorHandler (x_io_error_quitter);
+  }
+#else /* not USE_GTK */
 #ifdef USE_X_TOOLKIT
   /* weiner@footloose.sps.mot.com reports that this causes
      errors with X11R5:
@@ -14904,6 +15234,7 @@
 #endif
   dpy = XOpenDisplay (SDATA (display_name));
 #endif /* not USE_X_TOOLKIT */
+#endif /* not USE_GTK*/
 
   /* Detect failure.  */
   if (dpy == 0)
@@ -15363,9 +15694,11 @@
 #endif
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+#ifndef USE_GTK
   xaw3d_arrow_scroll = False;
   xaw3d_pick_top = True;
 #endif
+#endif
 
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
@@ -15445,6 +15778,8 @@
   Vx_toolkit_scroll_bars = intern ("motif");
 #elif defined HAVE_XAW3D
   Vx_toolkit_scroll_bars = intern ("xaw3d");
+#elif USE_GTK
+  Vx_toolkit_scroll_bars = intern ("gtk");
 #else
   Vx_toolkit_scroll_bars = intern ("xaw");
 #endif
--- a/src/xterm.h	Sun Jan 19 20:03:42 2003 +0000
+++ b/src/xterm.h	Sun Jan 19 21:50:03 2003 +0000
@@ -33,6 +33,18 @@
 				   window inside a widget instead of one 
 				   that Xt creates... */
 #include <X11/StringDefs.h>
+
+typedef Widget xt_or_gtk_widget;
+#endif
+
+#ifdef USE_GTK
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+/* Some definitions to reduce conditionals.  */
+typedef GtkWidget *xt_or_gtk_widget;
+#define XtParent(x) (gtk_widget_get_parent (x))
+
 #endif
 
 /* The class of this X application.  */
@@ -348,7 +360,7 @@
 
 extern struct frame *x_window_to_frame P_ ((struct x_display_info *, int));
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 extern struct frame *x_any_window_to_frame P_ ((struct x_display_info *, int));
 extern struct frame *x_non_menubar_window_to_frame P_ ((struct x_display_info *, int));
 extern struct frame *x_top_window_to_frame P_ ((struct x_display_info *, int));
@@ -403,6 +415,10 @@
      if the menubar is turned off.  */
   int menubar_height;
 
+  /* Height of tool bar widget, in pixels.
+     Zero if not using an external tool bar.  */
+  int toolbar_height;
+
   /* Height of a line, in pixels.  */
   int line_height;
 
@@ -446,6 +462,26 @@
   Widget menubar_widget;
 #endif
 
+#ifdef USE_GTK
+  /* The widget of this screen.  This is the window of a top widget.  */
+  GtkWidget *widget;
+  /* The widget of the edit portion of this screen; the window in
+     "window_desc" is inside of this.  */
+  GtkWidget *edit_widget;
+  /* The widget used for laying out widgets vertically.  */
+  GtkWidget *vbox_widget;
+  /* The menubar in this frame.  */
+  GtkWidget *menubar_widget;
+  /* The tool bar in this frame  */
+  GtkWidget *toolbar_widget;
+  /* The handle box that makes the tool bar detachable.  */
+  GtkWidget *handlebox_widget;
+  
+  /* The last size hints set.  */
+  GdkGeometry size_hints;
+  long hint_flags;
+#endif
+
   /* If >=0, a bitmap index.  The indicated bitmap is used for the
      icon. */
   int icon_bitmap;
@@ -638,13 +674,28 @@
                                XtWindow ((f)->output_data.x->widget) :  \
                                FRAME_X_WINDOW (f))
 #else
+#ifdef USE_GTK
+#define GTK_WIDGET_TO_X_WIN(w) \
+  ((w) && (w)->window ? GDK_WINDOW_XWINDOW ((w)->window) : 0)
+
+#define FRAME_GTK_OUTER_WIDGET(f) ((f)->output_data.x->widget)
+#define FRAME_GTK_WIDGET(f) ((f)->output_data.x->edit_widget)
+#define FRAME_OUTER_WINDOW(f)                                   \
+       (FRAME_GTK_OUTER_WIDGET (f) ?                            \
+        GTK_WIDGET_TO_X_WIN (FRAME_GTK_OUTER_WIDGET (f)) :      \
+         FRAME_X_WINDOW (f))
+
+#else /* !USE_GTK */
 #define FRAME_OUTER_WINDOW(f) (FRAME_X_WINDOW (f))
+#endif /* !USE_GTK */
 #endif
 
+
 #define FRAME_FONT(f) ((f)->output_data.x->font)
 #define FRAME_FONTSET(f) ((f)->output_data.x->fontset)
 #define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->output_data.x->internal_border_width)
 #define FRAME_MENUBAR_HEIGHT(f) ((f)->output_data.x->menubar_height)
+#define FRAME_TOOLBAR_HEIGHT(f) ((f)->output_data.x->toolbar_height)
 #define FRAME_LINE_HEIGHT(f) ((f)->output_data.x->line_height)
 
 /* Width of the default font of frame F.  Must be defined by each
@@ -681,7 +732,7 @@
      ((f)->output_data.x->x_pixels_outer_diff)
 #define FRAME_OUTER_TO_INNER_DIFF_Y(f)          \
      ((f)->output_data.x->y_pixels_outer_diff   \
-      + (f)->output_data.x->menubar_height)
+      + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
 
 
 #define FRAME_XIC(f) ((f)->output_data.x->xic)