all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* GTK patches part 1
@ 2002-12-08 19:19 Jan D.
  2002-12-09  5:14 ` Miles Bader
  0 siblings, 1 reply; 11+ messages in thread
From: Jan D. @ 2002-12-08 19:19 UTC (permalink / raw)


Hello

Attached is the part of the GTK port that modifies files.  I will
send two new files (gtkutil.c and .h) in a separate mail.

There are still minor bugs, for example geometry handling, removing and
showing scrollbar/menubar isn't correct, some scrolling issues remain,
argv isn't parsed for GTK options, help in menus, e.t.c.
Also, there is no GTK toolbar yet.

But I hope to resolve most of that before doing a checkin.  I think these
are minor changes only and it is valuable to get comments on the code
even before all issues are solved.

	Jan D.

diff -cwr -x '*.elc' emacs/configure.in emacs-gtk/configure.in
*** emacs/configure.in	2002-12-05 15:00:51.000000000 +0100
--- emacs-gtk/configure.in	2002-12-07 15:05:44.000000000 +0100
***************
*** 107,112 ****
--- 107,116 ----
  [  --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])
+ 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])
***************
*** 1781,1786 ****
--- 1785,1870 ----
    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"; then
+   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)
+   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,1909 ****
    fi
  fi
    
! dnl Use toolkit scroll bars if configured for X toolkit and either
  dnl using Motif or Xaw3d is available, and unless
  dnl --with-toolkit-scroll-bars=no was specified.
  
--- 1987,1993 ----
    fi
  fi
    
! 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,1925 ****
--- 2004,2012 ----
        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
  
***************
*** 2723,2728 ****
--- 2810,2822 ----
  ])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}'.
  
diff -cwr -x '*.elc' emacs/src/Makefile.in emacs-gtk/src/Makefile.in
*** emacs/src/Makefile.in	2002-12-05 15:01:02.000000000 +0100
--- emacs-gtk/src/Makefile.in	2002-12-08 19:53:48.000000000 +0100
***************
*** 252,263 ****
--- 252,270 ----
  #define C_SWITCH_ASM
  #endif
  
+ #ifdef 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,306 ****
--- 307,318 ----
  #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,381 ****
  #endif /* not LIBXT_STATIC */
  
  #else /* not USE_X_TOOLKIT */
  #ifdef HAVE_X_SM
! LIBXT=-lSM -lICE
  #else
! LIBXT=
  #endif
  #endif /* not USE_X_TOOLKIT */
  
--- 384,400 ----
  #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=$(LIBW) -lSM -lICE
  #else
! LIBXT=$(LIBW)
  #endif
  #endif /* not USE_X_TOOLKIT */
  
***************
*** 1143,1160 ****
     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)
  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)
  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)
  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
  hftctl.o: hftctl.c $(config_h)
  sound.o: sound.c dispextern.h $(config_h)
  atimer.o: atimer.c atimer.h systime.h $(config_h)
--- 1162,1182 ----
     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 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 \
!    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 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
+ 
  hftctl.o: hftctl.c $(config_h)
  sound.o: sound.c dispextern.h $(config_h)
  atimer.o: atimer.c atimer.h systime.h $(config_h)
diff -cwr -x '*.elc' emacs/src/alloc.c emacs-gtk/src/alloc.c
*** emacs/src/alloc.c	2002-12-05 15:01:02.000000000 +0100
--- emacs-gtk/src/alloc.c	2002-12-08 17:24:09.000000000 +0100
***************
*** 4245,4250 ****
--- 4245,4257 ----
    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.  */
diff -cwr -x '*.elc' emacs/src/config.in emacs-gtk/src/config.in
*** emacs/src/config.in	2002-12-05 15:01:02.000000000 +0100
--- emacs-gtk/src/config.in	2002-12-05 15:21:54.000000000 +0100
***************
*** 721,726 ****
--- 721,730 ----
  /* Define to 1 if using an X toolkit. */
  #undef USE_X_TOOLKIT
  
+ /* Define if using GTK. */
+ #undef HAVE_GTK
+ 
+ 
  /* Define to 1 if on AIX 3.
     System headers sometimes define this.
     We just want to avoid a redefinition error message.  */
diff -cwr -x '*.elc' emacs/src/fileio.c emacs-gtk/src/fileio.c
*** emacs/src/fileio.c	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/fileio.c	2002-12-05 15:22:31.000000000 +0100
***************
*** 6102,6108 ****
  
    GCPRO2 (insdef, default_filename);
    
! #if defined (USE_MOTIF) || defined (HAVE_NTGUI)
    if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
        && use_dialog_box
        && have_menus_p ())
--- 6102,6108 ----
  
    GCPRO2 (insdef, default_filename);
    
! #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 ())
diff -cwr -x '*.elc' emacs/src/frame.h emacs-gtk/src/frame.h
*** emacs/src/frame.h	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/frame.h	2002-12-05 15:30:27.000000000 +0100
***************
*** 270,276 ****
    /* Number of lines of menu bar.  */
    int menu_bar_lines;
  
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
    /* Nonzero means using a menu bar that comes from the X toolkit.  */
    int external_menu_bar;
  #endif
--- 270,277 ----
    /* Number of lines of menu bar.  */
    int menu_bar_lines;
  
! #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
***************
*** 468,474 ****
  
  /* 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)
  #define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
  #else
  #define FRAME_EXTERNAL_MENU_BAR(f) 0
--- 469,476 ----
  
  /* 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) \
!     || defined (USE_GTK)
  #define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
  #else
  #define FRAME_EXTERNAL_MENU_BAR(f) 0
Endast i emacs-gtk/src: gtkutil.c
Endast i emacs-gtk/src: gtkutil.h
diff -cwr -x '*.elc' emacs/src/keyboard.c emacs-gtk/src/keyboard.c
*** emacs/src/keyboard.c	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/keyboard.c	2002-12-08 15:45:02.000000000 +0100
***************
*** 3857,3863 ****
  	  XSETBUFFER (obj, current_buffer);
  	  kbd_fetch_ptr = event + 1;
  	}
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
        else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
  	{
  	  kbd_fetch_ptr = event + 1;
--- 3857,3864 ----
  	  XSETBUFFER (obj, current_buffer);
  	  kbd_fetch_ptr = event + 1;
  	}
! #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;
***************
*** 3964,3970 ****
  	    {
  	      obj = make_lispy_event (event);
  	      
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS)
  	      /* 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
--- 3965,3972 ----
  	    {
  	      obj = make_lispy_event (event);
  	      
! #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
***************
*** 5027,5033 ****
   	    pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
  	 			   &column, &row, NULL, 1);
  
! #ifndef USE_X_TOOLKIT
  	    /* In the non-toolkit version, clicks on the menu bar
  	       are ordinary button events in the event buffer.
  	       Distinguish them, and invoke the menu.
--- 5029,5035 ----
   	    pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
  	 			   &column, &row, NULL, 1);
  
! #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.
***************
*** 5079,5085 ****
  
  		return Fcons (item, Fcons (position, Qnil));
  	      }
! #endif /* not USE_X_TOOLKIT */
  
  	    /* Set `window' to the window under frame pixel coordinates
  	       event->x/event->y.  */
--- 5081,5087 ----
  
  		return Fcons (item, Fcons (position, Qnil));
  	      }
! #endif /* not USE_X_TOOLKIT && not USE_GTK */
  
  	    /* Set `window' to the window under frame pixel coordinates
  	       event->x/event->y.  */
***************
*** 5317,5323 ****
  	}
        }
  
! #ifdef USE_TOOLKIT_SCROLL_BARS
  
        /* We don't have down and up events if using toolkit scroll bars,
  	 so make this always a click event.  Store in the `part' of
--- 5319,5325 ----
  	}
        }
  
! #if USE_TOOLKIT_SCROLL_BARS
  
        /* We don't have down and up events if using toolkit scroll bars,
  	 so make this always a click event.  Store in the `part' of
***************
*** 5568,5574 ****
        }
  #endif /* HAVE_MOUSE */
  
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
      case MENU_BAR_EVENT:
        if (EQ (event->arg, event->frame_or_window))
  	/* This is the prefix key.  We translate this to
--- 5570,5577 ----
        }
  #endif /* HAVE_MOUSE */
  
! #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
diff -cwr -x '*.elc' emacs/src/lisp.h emacs-gtk/src/lisp.h
*** emacs/src/lisp.h	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/lisp.h	2002-12-07 15:27:17.000000000 +0100
***************
*** 3122,3127 ****
--- 3122,3128 ----
  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 */
Endast i emacs-gtk/src: x
diff -cwr -x '*.elc' emacs/src/xdisp.c emacs-gtk/src/xdisp.c
*** emacs/src/xdisp.c	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/xdisp.c	2002-12-05 15:29:02.000000000 +0100
***************
*** 200,206 ****
  
  #define INFINITY 10000000
  
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
  extern void set_frame_menubar P_ ((struct frame *f, int, int));
  extern int pending_menu_activation;
  #endif
--- 200,207 ----
  
  #define INFINITY 10000000
  
! #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
***************
*** 7512,7518 ****
  
    if (FRAME_WINDOW_P (f)
        ?
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
        FRAME_EXTERNAL_MENU_BAR (f)
  #else
        FRAME_MENU_BAR_LINES (f) > 0
--- 7513,7520 ----
  
    if (FRAME_WINDOW_P (f)
        ?
! #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
***************
*** 7563,7569 ****
  	  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 (FRAME_WINDOW_P (f)
  #if defined (MAC_OS)
                /* All frames on Mac OS share the same menubar.  So only the
--- 7565,7572 ----
  	  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) \
!     || defined (USE_GTK)
  	  if (FRAME_WINDOW_P (f)
  #if defined (MAC_OS)
                /* All frames on Mac OS share the same menubar.  So only the
***************
*** 7576,7586 ****
  	    /* 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) */
  	  /* 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) */
  
  	  unbind_to (count, Qnil);
  	  set_buffer_internal_1 (prev);
--- 7579,7589 ----
  	    /* 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 || 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 || MAC_OS || USE_GTK) */
  
  	  unbind_to (count, Qnil);
  	  set_buffer_internal_1 (prev);
***************
*** 8544,8550 ****
  	return;
      }
  
! #ifdef USE_X_TOOLKIT
    if (popup_activated ())
      return;
  #endif
--- 8547,8553 ----
  	return;
      }
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    if (popup_activated ())
      return;
  #endif
***************
*** 10761,10767 ****
  
        if (FRAME_WINDOW_P (f))
  	{
! #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
  	  redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
  #else
  	  redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
--- 10764,10771 ----
  
        if (FRAME_WINDOW_P (f))
  	{
! #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;
diff -cwr -x '*.elc' emacs/src/xfns.c emacs-gtk/src/xfns.c
*** emacs/src/xfns.c	2002-12-06 23:24:12.000000000 +0100
--- emacs-gtk/src/xfns.c	2002-12-07 17:58:23.000000000 +0100
***************
*** 65,70 ****
--- 65,74 ----
  #include "[.bitmaps]gray.xbm"
  #endif
  
+ #ifdef USE_GTK
+ #include "gtkutil.h"
+ #endif
+ 
  #ifdef USE_X_TOOLKIT
  #include <X11/Shell.h>
  
***************
*** 340,345 ****
--- 344,358 ----
            || 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,354 ****
    return 0;
  }
  
! #ifdef USE_X_TOOLKIT
  /* Like x_window_to_frame but also compares the window with the widget's
     windows.  */
  
--- 361,367 ----
    return 0;
  }
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
  /* Like x_window_to_frame but also compares the window with the widget's
     windows.  */
  
***************
*** 377,382 ****
--- 390,404 ----
  	    found = f;
  	  else if (x->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))
***************
*** 384,389 ****
--- 406,412 ----
  	      /* 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.  */
***************
*** 419,428 ****
--- 442,460 ----
  	return f;
        else if (x->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,460 ****
--- 484,508 ----
  	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,489 ****
--- 532,542 ----
        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,
***************
*** 494,499 ****
--- 547,553 ----
  	      && wdesc == XtWindow (x->menubar_widget))
  	    return f;
  #endif
+ #endif
  	}
        else if (FRAME_X_WINDOW (f) == wdesc)
  	/* Tooltip frame.  */
***************
*** 501,507 ****
      }
    return 0;
  }
! #endif /* USE_X_TOOLKIT */
  
  \f
  
--- 555,561 ----
      }
    return 0;
  }
! #endif /* USE_X_TOOLKIT || USE_GTK */
  
  \f
  
***************
*** 2119,2125 ****
    /* Make sure we redisplay all windows in this frame.  */
    windows_or_buffers_changed++;
  
! #ifdef USE_X_TOOLKIT
    FRAME_MENU_BAR_LINES (f) = 0;
    if (nlines)
      {
--- 2173,2179 ----
    /* Make sure we redisplay all windows in this frame.  */
    windows_or_buffers_changed++;
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    FRAME_MENU_BAR_LINES (f) = 0;
    if (nlines)
      {
***************
*** 2136,2142 ****
        if (FRAME_X_P (f))
  	f->output_data.x->menubar_widget = 0;
      }
! #else /* not USE_X_TOOLKIT */
    FRAME_MENU_BAR_LINES (f) = nlines;
    x_change_window_heights (f->root_window, nlines - olines);
  #endif /* not USE_X_TOOLKIT */
--- 2190,2196 ----
        if (FRAME_X_P (f))
  	f->output_data.x->menubar_widget = 0;
      }
! #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 */
***************
*** 2465,2472 ****
--- 2519,2531 ----
  	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));
+ #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))
***************
*** 3938,3944 ****
--- 3997,4012 ----
  }
  
  #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
***************
*** 4041,4046 ****
--- 4109,4115 ----
      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
***************
*** 4618,4624 ****
       new frames.  */
    call1 (Qface_set_after_frame_default, frame);
  
! #ifdef USE_X_TOOLKIT
    /* Create the menu bar.  */
    if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
      {
--- 4687,4693 ----
       new frames.  */
    call1 (Qface_set_after_frame_default, frame);
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    /* Create the menu bar.  */
    if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
      {
***************
*** 4626,4638 ****
  	 frame and we didn't make it visible.  */
        initialize_frame_menubar (f);
  
        /* 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 */
  
    /* 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
--- 4695,4709 ----
  	 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 /* 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
***************
*** 11692,11697 ****
--- 11763,11939 ----
  
  #endif /* USE_MOTIF */
  
+ #ifdef USE_GTK
+ 
+ enum
+ {
+   GTK_FILE_NOT_DONE,
+   GTK_FILE_OK,
+   GTK_FILE_CANCEL,
+   GTK_FILE_DESTROY,
+   GTK_FILE_ACTIVATE
+ };
+ 
+ static void
+ FileSelOk (w, arg)
+      GtkWidget *w;
+      gpointer arg;
+ {
+   *(int*)arg = GTK_FILE_OK;
+ }
+ 
+ static void
+ FileSelCancel (w, arg)
+      GtkWidget *w;
+      gpointer arg;
+ {
+   *(int*)arg = GTK_FILE_CANCEL;
+ }
+ 
+ static void
+ FileSelDestroy (w, arg)
+      GtkWidget *w;
+      gpointer arg;
+ {
+   *(int*)arg = GTK_FILE_DESTROY;
+ }
+ 
+ static void
+ FileSelActivated (w, arg)
+      GtkWidget *w;
+      gpointer arg;
+ {
+   *(int*)arg = GTK_FILE_ACTIVATE;
+ }
+ 
+ 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;
+ {
+   GtkWidget* filewin;
+   GtkFileSelection* filesel;
+   char *fn;
+   int gtk_file_done = GTK_FILE_NOT_DONE;
+   Lisp_Object file = Qnil;
+   Lisp_Object def_nodir = Qnil;
+   int count = specpdl_ptr - specpdl;
+   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
+ 
+   GCPRO6 (prompt, dir, default_filename, mustmatch, def_nodir, file);
+   CHECK_STRING (prompt);
+   CHECK_STRING (dir);
+ 
+   /* Prevent redisplay.  */
+   specbind (Qinhibit_redisplay, Qt);
+ 
+   BLOCK_INPUT;
+ 
+   filewin = gtk_file_selection_new (SDATA (prompt));
+   filesel = GTK_FILE_SELECTION (filewin);
+       
+   g_signal_connect (filesel->ok_button,
+                     "clicked",
+                     G_CALLBACK (FileSelOk),
+                     &gtk_file_done);
+   g_signal_connect (filesel->cancel_button,
+                     "clicked",
+                     G_CALLBACK (FileSelCancel),
+                     &gtk_file_done);
+   g_signal_connect (filesel,
+                     "destroy",
+                     G_CALLBACK (FileSelDestroy),
+                     &gtk_file_done);
+ 
+   /* KOKO: GTK fileselection dialog does not have separate directory and
+      default filename options. */
+   /* dir = Fexpand_file_name (dir, Qnil);*/
+   if (STRINGP (default_filename))
+     {
+       gtk_file_selection_set_filename (filesel, SDATA (default_filename));
+     }
+ 
+   if (! NILP (mustmatch))
+     {
+       GtkTreeSelection *sel;
+       sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (filesel->file_list));
+       g_signal_connect (sel,
+                         "changed",
+                         G_CALLBACK (FileSelActivated),
+                         &gtk_file_done);
+       gtk_widget_set_sensitive (filesel->ok_button, FALSE);
+       gtk_widget_set_sensitive (filesel->file_list, FALSE);
+       gtk_file_selection_hide_fileop_buttons (filesel);
+       if (STRINGP (default_filename))
+         {
+           def_nodir = Ffile_name_nondirectory (default_filename);
+           /* The row below doesn't seem to work the way it does in Motif,
+              i.e. only show files with this name.  Must do this some
+              other way.
+           gtk_file_selection_complete(filesel, SDATA (def_nodir));
+           */
+         }
+     }
+ 
+   
+   gtk_widget_show (filewin);
+   while (gtk_file_done == GTK_FILE_NOT_DONE)
+     {
+       gtk_main_iteration ();
+       if (NILP (mustmatch)
+           || NILP (def_nodir)
+           || gtk_file_done == GTK_FILE_CANCEL
+           || gtk_file_done == GTK_FILE_DESTROY
+           || gtk_file_done == GTK_FILE_OK)
+         continue;
+       
+       fn = (char*)gtk_file_selection_get_filename (filesel);
+       file = build_string (fn);
+ 
+       gtk_widget_set_sensitive (filesel->ok_button,
+                                 ! NILP (Ffile_exists_p (file)));
+ 
+       file = Ffile_name_nondirectory (file);
+ 
+       /* This is not so nice, but there is no official way to do this
+          i.e. without using undocumented things in filesel. */
+       if (strcmp (SDATA (def_nodir), SDATA (file)) != 0)
+         {
+           gtk_file_selection_set_filename (filesel, SDATA (def_nodir));
+           gtk_widget_set_sensitive (filesel->ok_button, FALSE);
+         }
+ 
+       gtk_file_done = GTK_FILE_NOT_DONE;
+     }
+       
+ 
+   if (gtk_file_done == GTK_FILE_OK)
+     {
+       fn = (char*)gtk_file_selection_get_filename (filesel);
+       file = build_string (fn);
+     }
+   else if (gtk_file_done == GTK_FILE_DESTROY)
+     {
+       filesel = 0;
+     }
+   
+   if (filesel) gtk_widget_destroy (filewin);
+ 
+   UNBLOCK_INPUT;
+   UNGCPRO;
+ 
+   /* Make "Cancel" equivalent to C-g.  */
+   if (NILP (file))
+     Fsignal (Qquit, Qnil);
+   
+   return unbind_to (count, file);
+ }
+ 
+ #endif /* USE_GTK */
  
  \f
  /***********************************************************************
diff -cwr -x '*.elc' emacs/src/xmenu.c emacs-gtk/src/xmenu.c
*** emacs/src/xmenu.c	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/xmenu.c	2002-12-08 19:54:32.000000000 +0100
***************
*** 81,87 ****
--- 81,89 ----
  #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 */
  
***************
*** 117,122 ****
--- 119,131 ----
  /* 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,
***************
*** 592,598 ****
    }
  #endif /* not HAVE_BOXES */
   
! #ifndef USE_X_TOOLKIT
    if (!NILP(map))
      /* Indicate visually that this is a submenu.  */
      item_string = concat2 (item_string, build_string (" >"));
--- 601,607 ----
    }
  #endif /* not HAVE_BOXES */
   
! #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 (" >"));
***************
*** 605,611 ****
  		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
  		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
  
! #ifdef USE_X_TOOLKIT
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
      {
--- 614,620 ----
  		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
  		  XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    /* Display a submenu using the toolkit.  */
    if (! (NILP (map) || NILP (enabled)))
      {
***************
*** 972,978 ****
         but I don't want to make one now.  */
      CHECK_WINDOW (window);
  
! #ifndef USE_X_TOOLKIT
    /* Display a menu with these alternatives
       in the middle of frame F.  */
    {
--- 981,987 ----
         but I don't want to make one now.  */
      CHECK_WINDOW (window);
  
! #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
    /* Display a menu with these alternatives
       in the middle of frame F.  */
    {
***************
*** 1013,1019 ****
  #endif
  }
  \f
! #ifdef USE_X_TOOLKIT
  
  /* Loop in Xt until the menu pulldown or dialog popup has been
     popped down (deactivated).  This is used for x-popup-menu
--- 1022,1028 ----
  #endif
  }
  \f
! #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
***************
*** 1022,1027 ****
--- 1031,1037 ----
     NOTE: All calls to popup_get_selection should be protected
     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
  
+ #ifdef USE_X_TOOLKIT
  void
  popup_get_selection (initial_event, dpyinfo, id)
       XEvent *initial_event;
***************
*** 1122,1127 ****
--- 1132,1156 ----
        interrupt_input_pending = 1;
      }
  }
+ #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 = 1;
+ 
+   /* Process events in the Gtk event loop until done.  */
+   xg_pass_through_events = TRUE;
+   while (popup_activated_flag)
+     {
+       gtk_main_iteration ();
+     }
+   xg_pass_through_events = FALSE;
+ }
+ #endif
  
  /* Activate the menu bar of frame F.
     This is called from keyboard.c when it gets the
***************
*** 1144,1152 ****
--- 1173,1192 ----
    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)
***************
*** 1168,1178 ****
--- 1208,1225 ----
  /* This callback is invoked when the user selects a menubar cascade
     pushbutton, but before the pulldown menu is posted.  */
  
+ #ifdef USE_GTK
+ static void
+ popup_activate_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ #else
  static void
  popup_activate_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
+ #endif
  {
    popup_activated_flag = 1;
  }
***************
*** 1180,1214 ****
  /* This callback is invoked when a dialog or menu is finished being
     used and has been unposted.  */
  
  static void
  popup_deactivate_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
  {
    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;
  {
-   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);
    if (f)
      {
        XSETFRAME (frame, f);
--- 1227,1290 ----
  /* 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;
+ #else
  static void
  popup_deactivate_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
+ #endif
  {
    popup_activated_flag = 0;
  }
  
! /* 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.  */
  
+ #ifdef USE_GTK
+ void
+ menu_highlight_callback (widget, call_data)
+      GtkWidget *widget;
+      gpointer call_data;
+ #else
  void
  menu_highlight_callback (widget, id, call_data)
       Widget widget;
       LWLIB_ID id;
       void *call_data;
+ #endif
  {
    struct frame *f;
    Lisp_Object frame, help;
  
+ #ifdef USE_GTK
+   struct menu_gtk_data *cl_data;
+   cl_data = (struct menu_gtk_data*) g_object_get_data (G_OBJECT (widget),
+                                                        G_FRAME_DATA);
+   if (! cl_data) return;
+   
+   f = cl_data->f;
+ 
+   /* NYI */
+   return;
+   
+ #else
+   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);
+ #endif
+ 
    if (f)
      {
        XSETFRAME (frame, f);
***************
*** 1218,1224 ****
--- 1294,1304 ----
      {
        /* WIDGET is the popup menu.  It's parent is the frame's 
  	 widget.  See which frame that is.  */
+ #ifdef USE_GTK
+       GtkWidget *frame_widget = gtk_widget_get_parent (widget);
+ #else
        Widget frame_widget = XtParent (widget);
+ #endif
        Lisp_Object tail;
  
        for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
***************
*** 1234,1265 ****
      }
  }
  
  /* 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;
  {
    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;
    prefix = Qnil;
    i = 0;
!   while (i < f->menu_bar_items_used)
      {
        if (EQ (XVECTOR (vector)->contents[i], Qnil))
  	{
--- 1314,1379 ----
      }
  }
  
+ /* Gtk calls callbacks just because we tell it what item should be
+    selected in a radio group.  If this variable is set to z non-zero
+    value, we are creating menus and don't want callbacks right now.
+ */
+ #ifdef USE_GTK
+ static int xg_crazy_callback_abort = 0;
+ #endif
+ 
  /* 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.  */
! #ifdef USE_GTK
! static void
! menubar_selection_callback (widget, client_data)
!      GtkWidget *widget;
!      gpointer client_data;
! #else
  static void
  menubar_selection_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
+ #endif
  {
    Lisp_Object prefix, entry;
    Lisp_Object vector;
    Lisp_Object *subprefix_stack;
    int submenu_depth = 0;
    int i;
+   int menu_bar_items_used;
    
+ #ifdef USE_GTK
+   FRAME_PTR f;
+   struct menu_gtk_data *cl_data;
+ 
+   if (xg_crazy_callback_abort)
+     return;
+   
+   cl_data = (struct menu_gtk_data*) g_object_get_data (G_OBJECT (widget),
+                                                        G_FRAME_DATA);
+   if (! cl_data || ! cl_data->f)
+     return;
+ 
+   menu_bar_items_used = cl_data->menu_bar_items_used;
+   f = cl_data->f;
+   vector = cl_data->menu_bar_vector;
+ #else
+   FRAME_PTR f = menubar_id_to_frame (id);
+   menu_bar_items_used = f->menu_bar_items_used;
    if (!f)
      return;
    vector = f->menu_bar_vector;
+ #endif
+ 
+   entry = Qnil;
+   subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof (Lisp_Object));
    prefix = Qnil;
    i = 0;
!   while (i < menu_bar_items_used)
      {
        if (EQ (XVECTOR (vector)->contents[i], Qnil))
  	{
***************
*** 1592,1597 ****
--- 1706,1714 ----
  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;
    
***************
*** 1626,1631 ****
--- 1743,1749 ----
    /* Force the pane widget to resize itself with the right values.  */
    EmacsFrameSetCharSize (x->edit_widget, columns, rows);
    UNBLOCK_INPUT;
+ #endif
    return 1;
  }
  
***************
*** 1639,1658 ****
       int first_time;
       int deep_p;
  {
    Widget menubar_widget = f->output_data.x->menubar_widget;
    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;
  
-   LWLIB_ID id;
  
    XSETFRAME (Vmenu_updating_frame, f);
  
    if (f->output_data.x->id == 0)
      f->output_data.x->id = next_menubar_widget_id++;
    id = f->output_data.x->id;
  
    if (! menubar_widget)
      deep_p = 1;
--- 1757,1782 ----
       int first_time;
       int deep_p;
  {
+ #ifdef USE_GTK
+   GtkWidget *menubar_widget = f->output_data.x->menubar_widget;
+ #else
    Widget menubar_widget = f->output_data.x->menubar_widget;
+   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;
  
  
    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;
***************
*** 1859,1864 ****
--- 1983,2020 ----
  
    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 (popup_activate_callback),
+                                  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, 
+                             0,
+                             G_CALLBACK (popup_activate_callback),
+                             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!) */
***************
*** 1902,1914 ****
        }
  #endif /* USE_LUCID */
  #endif /* 0 */
- 
      f->output_data.x->menubar_height = menubar_size;
    }
    
    free_menubar_widget_value_tree (first_wv);
    update_frame_menubar (f);
  
    UNBLOCK_INPUT;
  }
  
--- 2058,2074 ----
        }
  #endif /* USE_LUCID */
  #endif /* 0 */
      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;
  }
  
***************
*** 1935,1940 ****
--- 2095,2103 ----
  free_frame_menubar (f)
       FRAME_PTR f;
  {
+ #ifdef USE_GTK
+   xg_free_frame_menubar (f);
+ #else /* not USE_GTK */
    Widget menubar_widget;
  
    menubar_widget = f->output_data.x->menubar_widget;
***************
*** 1976,1984 ****
        
        UNBLOCK_INPUT;
      }
  }
  
! #endif /* USE_X_TOOLKIT */
  \f
  /* xmenu_show actually displays a menu using the panes and items in menu_items
     and returns the value selected from it.
--- 2139,2148 ----
        
        UNBLOCK_INPUT;
      }
+ #endif /* not USE_GTK */
  }
  
! #endif /* USE_X_TOOLKIT || USE_GTK */
  \f
  /* xmenu_show actually displays a menu using the panes and items in menu_items
     and returns the value selected from it.
***************
*** 1996,2002 ****
     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
  
  /* We need a unique id for each widget handled by the Lucid Widget
     library.
--- 2160,2166 ----
     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.)  */
  
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
  
  /* We need a unique id for each widget handled by the Lucid Widget
     library.
***************
*** 2006,2020 ****
--- 2170,2193 ----
  
     For menu bars, we use numbers starting at 0, counted in
     next_menubar_widget_id.  */
+ #ifdef USE_X_TOOLKIT
  LWLIB_ID widget_id_tick;
+ #endif
  
  static Lisp_Object *volatile menu_item_selection;
  
+ #ifdef USE_GTK
+ static void
+ popup_selection_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ #else
  static void
  popup_selection_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
+ #endif
  {
    menu_item_selection = (Lisp_Object *) client_data;
  }
***************
*** 2030,2046 ****
       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;
  
--- 2203,2223 ----
       char **error;
  {
    int i;
+ #ifdef USE_GTK
+   GtkWidget *menu;
+ #else
    LWLIB_ID menu_id;
    Widget menu;
    Arg av[2];
    int ac = 0;
+   XButtonPressedEvent dummy;
+ #endif
    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;
  
    int first_pane;
  
***************
*** 2233,2238 ****
--- 2410,2423 ----
      }
  
    /* Actually create the menu.  */
+ #ifdef USE_GTK
+   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
+                            1,
+                            0,
+                            G_CALLBACK (popup_selection_callback),
+                            G_CALLBACK (popup_deactivate_callback),
+                            G_CALLBACK (menu_highlight_callback));
+ #else
    menu_id = widget_id_tick++;
    menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
  			   f->output_data.x->widget, 1, 0,
***************
*** 2240,2245 ****
--- 2425,2431 ----
  			   popup_deactivate_callback,
  			   menu_highlight_callback);
  
+ #endif
    /* Adjust coordinates to relative to the outer (window manager) window.  */
    {
      Window child;
***************
*** 2271,2276 ****
--- 2457,2486 ----
    x += f->output_data.x->left_pos;
    y += f->output_data.x->top_pos;
  
+ #ifdef USE_GTK
+   for (i = 0; i < 5; i++)
+     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+       break;
+ 
+   /* 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.  */
+   gtk_menu_popup (GTK_MENU (menu), 0, 0, 0, 0, i, 0);
+   
+   /* Process events that apply to the menu.  */
+   popup_widget_loop ();
+ 
+   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 */
    dummy.type = ButtonPress;
    dummy.serial = 0;
    dummy.send_event = 0;
***************
*** 2311,2316 ****
--- 2521,2527 ----
       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 */
  
    /* Find the selected item, and its pane, to return
       the proper value.  */
***************
*** 2370,2388 ****
--- 2581,2608 ----
    return Qnil;
  }
  \f
+ #ifdef USE_GTK
+ static void
+ dialog_selection_callback (widget, client_data)
+      GtkWidget *widget;
+      gpointer client_data;
+ #else
  static void
  dialog_selection_callback (widget, id, client_data)
       Widget widget;
       LWLIB_ID id;
       XtPointer client_data;
+ #endif
  {
    /* 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;
+ #ifdef USE_X_TOOLKIT
    BLOCK_INPUT;
    lw_destroy_all_widgets (id);
    UNBLOCK_INPUT;
+ #endif
    popup_activated_flag = 0;
  }
  
***************
*** 2398,2405 ****
--- 2618,2629 ----
       char **error;
  {
    int i, nb_buttons=0;
+ #ifdef USE_GTK
+   GtkWidget *menu;
+ #else
    LWLIB_ID dialog_id;
    Widget menu;
+ #endif
    char dialog_name[6];
  
    widget_value *wv, *first_wv = 0, *prev_wv = 0;
***************
*** 2510,2520 ****
--- 2734,2752 ----
    }
  
    /* Actually create the dialog.  */
+ #ifdef USE_GTK
+   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
+                            0, 0,
+                            G_CALLBACK (dialog_selection_callback),
+                            G_CALLBACK (popup_deactivate_callback),
+                            0);
+ #else
    dialog_id = widget_id_tick++;
    menu = 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);
+ #endif
    /* Free the widget_value objects we used to specify the contents.  */
    free_menubar_widget_value_tree (first_wv);
  
***************
*** 2522,2527 ****
--- 2754,2771 ----
    menu_item_selection = 0;
  
    /* Display the menu.  */
+ #ifdef USE_GTK
+   if (menu)
+     {
+       /* Display the menu.  */
+       gtk_widget_show_all (menu);
+ 
+       /* Process events that apply to the menu.  */
+       popup_widget_loop ();
+   
+       if (menu_item_selection != 0) gtk_widget_destroy (menu);
+     }
+ #else
    lw_pop_up_all_widgets (dialog_id);
    popup_activated_flag = 1;
  
***************
*** 2529,2535 ****
    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
  
    lw_destroy_all_widgets (dialog_id); 
! 
    /* Find the selected item, and its pane, to return
       the proper value.  */
    if (menu_item_selection != 0)
--- 2773,2779 ----
    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
  
    lw_destroy_all_widgets (dialog_id); 
! #endif
    /* Find the selected item, and its pane, to return
       the proper value.  */
    if (menu_item_selection != 0)
***************
*** 2576,2582 ****
    return Qnil;
  }
  
! #else /* not USE_X_TOOLKIT */
  
  /* The frame of the last activated non-toolkit menu bar.
     Used to generate menu help events.  */
--- 2820,2826 ----
    return Qnil;
  }
  
! #else /* not USE_X_TOOLKIT && not USE_GTK */
  
  /* The frame of the last activated non-toolkit menu bar.
     Used to generate menu help events.  */
diff -cwr -x '*.elc' emacs/src/xterm.c emacs-gtk/src/xterm.c
*** emacs/src/xterm.c	2002-12-05 15:01:03.000000000 +0100
--- emacs-gtk/src/xterm.c	2002-12-08 19:46:57.000000000 +0100
***************
*** 97,113 ****
  #include <unistd.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
  
  extern void free_frame_menubar P_ ((struct frame *));
  extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
  						    int));
  
  #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
  #define HACK_EDITRES
  extern void _XEditResCheckMessages ();
--- 97,119 ----
  #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
  
! #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,144 ****
  
  #endif /* USE_X_TOOLKIT */
  
! #ifndef USE_X_TOOLKIT
  #define x_any_window_to_frame x_window_to_frame
  #define x_top_window_to_frame x_window_to_frame
  #endif
--- 144,150 ----
  
  #endif /* 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
***************
*** 7074,7080 ****
    struct buffer *b;
  
    /* When a menu is active, don't highlight because this looks odd.  */
! #ifdef USE_X_TOOLKIT
    if (popup_activated ())
      return;
  #endif
--- 7080,7086 ----
    struct buffer *b;
  
    /* When a menu is active, don't highlight because this looks odd.  */
! #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
    if (popup_activated ())
      return;
  #endif
***************
*** 8494,8503 ****
  						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.  */
  
--- 8500,8505 ----
***************
*** 8510,8515 ****
--- 8512,8522 ----
  /* 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,8567 ****
--- 8569,8575 ----
        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,8661 ****
--- 8663,8673 ----
    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]);
***************
*** 8663,8669 ****
    ievent->modifiers = 0;
  }
  
- 
  #ifdef USE_MOTIF
  
  /* Minimum and maximum values used for Motif scroll bars.  */
--- 8675,8680 ----
***************
*** 8749,8756 ****
  }
  
  
! #else /* !USE_MOTIF, i.e. Xaw.  */
  
  
  /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
     WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
--- 8760,8841 ----
  }
  
  
! #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 slider_size;
!   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);
+   slider_size = (adj->upper - adj->lower)/adj->page_size;
+ 
+   p = g_object_get_data (G_OBJECT (widget), G_LAST_SB_DATA);
+   if (! p)
+     {
+       p = (gdouble*) xmalloc (sizeof (gdouble));
+       *p = GTK_SB_MIN;
+       g_object_set_data (G_OBJECT (widget), G_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 = GTK_SB_RANGE;
+       portion = position;
+       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,8839 ****
    x_send_scroll_bar_event (bar->window, part, position, height);
  }
  
! 
  #endif /* not USE_MOTIF */
  
  
--- 8918,8924 ----
    x_send_scroll_bar_event (bar->window, part, position, height);
  }
  
! #endif /* not USE_GTK */
  #endif /* not USE_MOTIF */
  
  
***************
*** 8845,8859 ****
--- 8930,8950 ----
       struct frame *f;
       struct scroll_bar *bar;
  {
+ #ifndef USE_GTK
    Window xwindow;
    Widget widget;
    Arg av[20];
    int ac = 0;
+ #endif
    char *scroll_bar_name = "verticalScrollBar";
    unsigned long pixel;
  
    BLOCK_INPUT;
  
+ #ifdef USE_GTK
+   xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+                         scroll_bar_name);
+ #else /* not USE_GTK */
  #ifdef USE_MOTIF
    /* Set resources.  Create the widget.  */
    XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
***************
*** 9020,9025 ****
--- 9111,9117 ----
    xwindow = XtWindow (widget);
    SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
  
+ #endif /* not USE_GTK */
    UNBLOCK_INPUT;
  }
  
***************
*** 9032,9043 ****
--- 9124,9140 ----
       struct scroll_bar *bar;
       int portion, position, whole;
  {
+ #ifndef USE_GTK
    struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
    Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
    float top, shown;
+ #endif
  
    BLOCK_INPUT;
  
+ #ifdef USE_GTK
+   xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+ #else
  #ifdef USE_MOTIF
  
    /* We use an estimate of 30 chars per line rather than the real
***************
*** 9146,9151 ****
--- 9243,9249 ----
        }
    }
  #endif /* !USE_MOTIF */
+ #endif /* not USE_GTK */
  
    UNBLOCK_INPUT;
  }
***************
*** 9237,9242 ****
--- 9335,9349 ----
    /* 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,9249 ****
--- 9351,9357 ----
  		       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,9384 ****
--- 9486,9496 ----
    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
***************
*** 9471,9476 ****
--- 9583,9599 ----
  	mask |= CWHeight;
  
  #ifdef USE_TOOLKIT_SCROLL_BARS
+ #ifdef USE_GTK
+       if (mask)
+         {
+           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));
+         }
+ #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.  */
***************
*** 9486,9491 ****
--- 9609,9615 ----
  			   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
***************
*** 10107,10217 ****
  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
  
! /* Read events coming from the X server.
!    This routine is called by the SIGIO handler.
!    We return as soon as there are no more events to be read.
! 
!    Events representing keys are stored in buffer BUFP,
!    which can hold up to NUMCHARS characters.
!    We return the number of characters stored into the buffer,
!    thus pretending to be `read'.
! 
!    EXPECTED is nonzero if the caller knows input is available.  */
! 
! static int
! XTread_socket (sd, bufp, numchars, expected)
!      register int sd;
!      /* register */ struct input_event *bufp;
!      /* register */ int numchars;
!      int expected;
  {
!   int count = 0;
!   int nbytes = 0;
!   XEvent event;
!   struct frame *f;
!   int event_found = 0;
!   struct x_display_info *dpyinfo;
!   struct coding_system coding;
  
!   if (interrupt_input_blocked)
!     {
!       interrupt_input_pending = 1;
!       return -1;
      }
  
!   interrupt_input_pending = 0;
!   BLOCK_INPUT;
! 
!   /* So people can tell when we have read the available input.  */
!   input_signal_count++;
  
!   if (numchars <= 0)
!     abort ();			/* Don't think this happens.  */
  
!   ++handling_signal;
  
!   /* Find the display we are supposed to read input for.
!      It's the one communicating on descriptor SD.  */
!   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
!     {
! #if 0 /* This ought to be unnecessary; let's verify it.  */
! #ifdef FIOSNBIO
!       /* If available, Xlib uses FIOSNBIO to make the socket
! 	 non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
! 	 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
! 	 a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
!       fcntl (dpyinfo->connection, F_SETFL, 0);
! #endif /* ! defined (FIOSNBIO) */
! #endif
  
! #if 0 /* This code can't be made to work, with multiple displays,
! 	 and appears not to be used on any system any more.
! 	 Also keyboard.c doesn't turn O_NDELAY on and off
! 	 for X connections.  */
! #ifndef SIGIO
! #ifndef HAVE_SELECT
!       if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
! 	{
! 	  extern int read_alarm_should_throw;
! 	  read_alarm_should_throw = 1;
! 	  XPeekEvent (dpyinfo->display, &event);
! 	  read_alarm_should_throw = 0;
  	}
! #endif /* HAVE_SELECT */
! #endif /* SIGIO */
! #endif
  
!       /* For debugging, this gives a way to fake an I/O error.  */
!       if (dpyinfo == XTread_socket_fake_io_error)
! 	{
! 	  XTread_socket_fake_io_error = 0;
! 	  x_io_error_quitter (dpyinfo->display);
! 	}
  
! #ifdef HAVE_X_SM
!       BLOCK_INPUT;
!       count += x_session_check_input (bufp, &numchars);
!       UNBLOCK_INPUT;
! #endif
  
!       while (XPending (dpyinfo->display))
! 	{
! 	  XNextEvent (dpyinfo->display, &event);
  
! #ifdef HAVE_X_I18N
  	  {
! 	    /* Filter events for the current X input method.
! 	       XFilterEvent returns non-zero if the input method has
! 	       consumed the event.  We pass the frame's X window to
! 	       XFilterEvent because that's the one for which the IC
! 	       was created.  */
! 	    struct frame *f1 = x_any_window_to_frame (dpyinfo,
! 						      event.xclient.window);
! 	    if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
! 	      break;
! 	  }
! #endif
! 	  event_found = 1;
  
  	  switch (event.type)
  	    {
--- 10231,10336 ----
  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
  
! enum
  {
!   X_EVENT_NORMAL,
!   X_EVENT_GOTO_OUT,
!   X_EVENT_GOTO_OTHER
! };
  
! #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;
! static int xg_drop_event;
! 
! static int handle_one_xevent P_ ((struct x_display_info *dpyinfo,
!                                   XEvent *eventp,
!                                   struct input_event **bufp_r,
!                                   int *numcharsp,
!                                   int *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 gtk_pass_through_events is TRUE we want events to go to GTK only.
!      But Expose is passed to the Emacs loop so redraw is done correctly.
!      gtk_pass_through_events is set to TRUE by menu popups and dialogs. */
!   if (xg_pass_through_events && xev->type != Expose)
!     return GDK_FILTER_CONTINUE;
!   
!   xg_drop_event = 0;
!   if (current_numcharsp)
!     {
!       current_count += handle_one_xevent (current_dpyinfo,
!                                           xev,
!                                           current_bufp,
!                                           current_numcharsp,
!                                           &current_finish);
      }
+   else
+     {
+       struct x_display_info *dpyinfo;
+       struct input_event bufp[10];
+       struct input_event *bufpp = bufp;
+       int numchars = 10;
        
!       for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
!           if (dpyinfo->display == GDK_DISPLAY ())
!             break;
            
!       if (dpyinfo)
!         handle_one_xevent (dpyinfo,
!                            xev,
!                            &bufpp,
!                            &numchars,
!                            &current_finish);
  
!       /* KOKO: Store emacs events? */
!     }
  
!   if (current_finish == X_EVENT_GOTO_OUT || xg_drop_event)
!     return GDK_FILTER_REMOVE;
  
!   return GDK_FILTER_CONTINUE;
  }
! #endif /* USE_GTK */
  
! /* Handles the XEvent EVENT on display DPYINFO.
     
!    *FINISH is non-zero if caller should stop processing events,
!    *FINISH is zero if caller should continue reading events.
  
!    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;
!      XEvent *eventp;
!      /* register */ struct input_event **bufp_r;
!      /* register */ int *numcharsp;
!      int *finish;
  {
!   int count = 0;
!   int nbytes = 0;
!   struct frame *f;
!   struct coding_system coding;
!   struct input_event *bufp = *bufp_r;
!   int numchars = *numcharsp;
!   XEvent event = *eventp;
  
    switch (event.type)
      {
***************
*** 10318,10323 ****
--- 10437,10447 ----
  
                      count += 1;
                      numchars -= 1;
+ #ifdef USE_GTK
+                     /* Can't pass this to GTK, it will delete
+                        widgets beyond our control.  Go figure. */
+                     xg_drop_event = 1;
+ #endif
                    }
                }
            }
***************
*** 10529,10534 ****
--- 10653,10661 ----
        f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
        if (f)
          {
+ #ifdef USE_GTK
+           xg_drop_event = 1;
+ #endif
            expose_frame (f,
                          event.xgraphicsexpose.x, event.xgraphicsexpose.y,
                          event.xgraphicsexpose.width,
***************
*** 11189,11194 ****
--- 11316,11325 ----
        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
***************
*** 11217,11227 ****
--- 11348,11366 ----
                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,
***************
*** 11231,11236 ****
--- 11370,11378 ----
            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);
***************
*** 11328,11341 ****
  		    numchars--;
  		  }
  
! #ifdef USE_X_TOOLKIT
  		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
  		    /* Verify the event is really within the menu bar
  		       and not just sent to it due to grabbing.  */
  		    && event.xbutton.x >= 0
--- 11470,11488 ----
              numchars--;
            }
  
! #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 (
! #ifdef USE_GTK
!             ! popup_activated_flag
!             &&
! #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
***************
*** 11346,11351 ****
--- 11493,11501 ----
            {
              SET_SAVED_BUTTON_EVENT;
              XSETFRAME (last_mouse_press_frame, f);
+ #ifdef USE_GTK
+             xg_drop_event = 1;
+ #endif
            }
          else if (event.type == ButtonPress)
            {
***************
*** 11369,11375 ****
  #endif /* USE_MOTIF */
  		else
  		  goto OTHER;
! #endif /* USE_X_TOOLKIT */
  	      }
  	      break;
  
--- 11519,11525 ----
  #endif /* USE_MOTIF */
          else
            goto OTHER;
! #endif /* USE_X_TOOLKIT || USE_GTK */
        }
        break;
  
***************
*** 11402,11410 ****
--- 11552,11716 ----
      XtDispatchEvent (&event);
      UNBLOCK_INPUT;
  #endif /* USE_X_TOOLKIT */
+     *finish = X_EVENT_GOTO_OTHER;
      break;
+     goto ret;
      }
+ 
+   *finish = X_EVENT_NORMAL;
+   goto ret;
+   
+  out:
+   *finish = X_EVENT_GOTO_OUT;
+ 
+  ret:
+   *bufp_r = bufp;
+   *numcharsp = numchars;
+   *eventp = event;
+   
+   return count;
  }
+ 
+ /* Read events coming from the X server.
+    This routine is called by the SIGIO handler.
+    We return as soon as there are no more events to be read.
+ 
+    Events representing keys are stored in buffer BUFP,
+    which can hold up to NUMCHARS characters.
+    We return the number of characters stored into the buffer,
+    thus pretending to be `read'.
+ 
+    EXPECTED is nonzero if the caller knows input is available.  */
+ 
+ static int
+ XTread_socket (sd, bufp, numchars, expected)
+      register int sd;
+      /* register */ struct input_event *bufp;
+      /* register */ int numchars;
+      int expected;
+ {
+   int count = 0;
+   int nbytes = 0;
+   XEvent event;
+   int event_found = 0;
+   struct x_display_info *dpyinfo;
+ 
+   if (interrupt_input_blocked)
+     {
+       interrupt_input_pending = 1;
+       return -1;
+     }
+ 
+   interrupt_input_pending = 0;
+   BLOCK_INPUT;
+ 
+   /* So people can tell when we have read the available input.  */
+   input_signal_count++;
+ 
+   if (numchars <= 0)
+     abort ();			/* Don't think this happens.  */
+ 
+   ++handling_signal;
+ 
+   /* Find the display we are supposed to read input for.
+      It's the one communicating on descriptor SD.  */
+   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+     {
+ #if 0 /* This ought to be unnecessary; let's verify it.  */
+ #ifdef FIOSNBIO
+       /* If available, Xlib uses FIOSNBIO to make the socket
+ 	 non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
+ 	 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
+ 	 a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
+       fcntl (dpyinfo->connection, F_SETFL, 0);
+ #endif /* ! defined (FIOSNBIO) */
+ #endif
+ 
+ #if 0 /* This code can't be made to work, with multiple displays,
+ 	 and appears not to be used on any system any more.
+ 	 Also keyboard.c doesn't turn O_NDELAY on and off
+ 	 for X connections.  */
+ #ifndef SIGIO
+ #ifndef HAVE_SELECT
+       if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
+ 	{
+ 	  extern int read_alarm_should_throw;
+ 	  read_alarm_should_throw = 1;
+ 	  XPeekEvent (dpyinfo->display, &event);
+ 	  read_alarm_should_throw = 0;
+ 	}
+ #endif /* HAVE_SELECT */
+ #endif /* SIGIO */
+ #endif
+ 
+       /* For debugging, this gives a way to fake an I/O error.  */
+       if (dpyinfo == XTread_socket_fake_io_error)
+ 	{
+ 	  XTread_socket_fake_io_error = 0;
+ 	  x_io_error_quitter (dpyinfo->display);
+ 	}
+ 
+ #ifdef HAVE_X_SM
+       BLOCK_INPUT;
+       count += x_session_check_input (bufp, &numchars);
+       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 ())
+         {
+           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;
+           
+ 	  XNextEvent (dpyinfo->display, &event);
+ 
+ #ifdef HAVE_X_I18N
+ 	  {
+ 	    /* Filter events for the current X input method.
+ 	       XFilterEvent returns non-zero if the input method has
+ 	       consumed the event.  We pass the frame's X window to
+ 	       XFilterEvent because that's the one for which the IC
+ 	       was created.  */
+ 	    struct frame *f1 = x_any_window_to_frame (dpyinfo,
+ 						      event.xclient.window);
+ 	    if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
+ 	      break;
+ 	  }
+ #endif
+ 	  event_found = 1;
+ 
+           count += handle_one_xevent (dpyinfo,
+                                       &event,
+                                       &bufp,
+                                       &numchars,
+                                       &finish);
+ 
+           if (finish == X_EVENT_GOTO_OUT)
+             goto out;
+         }
+ #endif /* USE_GTK */
      }
  
   out:;
***************
*** 12862,12872 ****
    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
  
    /* Find the position of the outside upper-left corner of
       the inner window, with respect to the outer window.
--- 13168,13174 ----
    if (! ((flags & XNegative) || (flags & YNegative)))
      return;
  
!   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.
***************
*** 12997,13009 ****
      }
  #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 */
    UNBLOCK_INPUT;
  }
  
--- 13299,13306 ----
      }
  #endif
  
!   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                 modified_left, modified_top);
    UNBLOCK_INPUT;
  }
  
***************
*** 13189,13195 ****
  {
    BLOCK_INPUT;
  
! #ifdef USE_X_TOOLKIT
  
    if (f->output_data.x->widget != NULL)
      {
--- 13486,13497 ----
  {
    BLOCK_INPUT;
  
! #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)
      {
***************
*** 13385,13391 ****
--- 13687,13697 ----
        /* 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
***************
*** 13536,13541 ****
--- 13842,13855 ----
       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,
***************
*** 13570,13575 ****
--- 13884,13890 ----
    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
***************
*** 13609,13614 ****
--- 13924,13945 ----
    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))
***************
*** 13743,13748 ****
--- 14074,14091 ----
  
        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 */
***************
*** 13836,13851 ****
       long flags;
       int user_position;
  {
    XSizeHints size_hints;
  
  #ifdef USE_X_TOOLKIT
    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 */
  
    /* Setting PMaxSize caused various problems.  */
    size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
--- 14179,14198 ----
       long flags;
       int user_position;
  {
+ #ifdef USE_GTK
+   /* Must use GTK routines here, otherwise Gtk resets the size hints
+      to its own defaults. */
+   xg_set_wm_size_hints (f, flags, user_position);
+ #else /* not USE_GTK */
    XSizeHints size_hints;
  
  #ifdef USE_X_TOOLKIT
    Arg al[2];
    int ac = 0;
    Dimension widget_width, widget_height;
! #endif
!   
!   Window window = FRAME_OUTER_WINDOW (f);
  
    /* Setting PMaxSize caused various problems.  */
    size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
***************
*** 13971,13976 ****
--- 14318,14324 ----
  #else
    XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
  #endif
+ #endif /* not USE_GTK */
  }
  
  /* Used for IconicState or NormalState */
***************
*** 14804,14809 ****
--- 15152,15179 ----
        x_initialized = 1;
      }
  
+ #ifdef USE_GTK
+   {
+     int argc = 0;
+     char *argv[3];
+     char **argv2 = argv;
+     GdkAtom atom;
+ 
+     /* KOKO, must pass -display and such */
+     argv[0] = initial_argv[0];
+     argv[1] = argv[2] = 0;
+     argc = 1;
+ 
+     gtk_init (&argc, &argv2);
+ 
+     dpy = GDK_DISPLAY ();
+     /* NULL window -> events for all windows go to our function */
+     gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+ 
+     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:
***************
*** 14844,14849 ****
--- 15214,15220 ----
  #endif
    dpy = XOpenDisplay (SDATA (display_name));
  #endif /* not USE_X_TOOLKIT */
+ #endif /* not USE_GTK*/
  
    /* Detect failure.  */
    if (dpy == 0)
***************
*** 15303,15311 ****
--- 15674,15684 ----
  #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.  */
***************
*** 15385,15390 ****
--- 15758,15765 ----
    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
diff -cwr -x '*.elc' emacs/src/xterm.h emacs-gtk/src/xterm.h
*** emacs/src/xterm.h	2002-10-03 19:25:46.000000000 +0200
--- emacs-gtk/src/xterm.h	2002-12-05 16:02:26.000000000 +0100
***************
*** 35,40 ****
--- 35,45 ----
  #include <X11/StringDefs.h>
  #endif
  
+ #ifdef USE_GTK
+ #include <gtk/gtk.h>
+ #include <gdk/gdkx.h>
+ #endif
+ 
  /* The class of this X application.  */
  #define EMACS_CLASS "Emacs"
  \f
***************
*** 348,354 ****
  
  extern struct frame *x_window_to_frame P_ ((struct x_display_info *, int));
  
! #ifdef USE_X_TOOLKIT
  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));
--- 353,359 ----
  
  extern struct frame *x_window_to_frame P_ ((struct x_display_info *, int));
  
! #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));
***************
*** 446,451 ****
--- 451,471 ----
    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 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;
***************
*** 619,625 ****
  enum
  {
    /* Values for focus_state, used as bit mask.
!      EXPLICIT means if we received a FocusIn for the frame and know it has
       the focus.  IMPLICIT means we recevied an EnterNotify and the frame
       may have the focus if no window manager is running.
       FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
--- 639,645 ----
  enum
  {
    /* Values for focus_state, used as bit mask.
!      EXPLICIT means we received a FocusIn for the frame and know it has
       the focus.  IMPLICIT means we recevied an EnterNotify and the frame
       may have the focus if no window manager is running.
       FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
***************
*** 638,646 ****
--- 658,680 ----
                                 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)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-08 19:19 GTK patches part 1 Jan D.
@ 2002-12-09  5:14 ` Miles Bader
  2002-12-09 12:44   ` Jan D.
  0 siblings, 1 reply; 11+ messages in thread
From: Miles Bader @ 2002-12-09  5:14 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1220 bytes --]

Cool!  I tried it and after a bit of futzing, it (mostly) works!

Some minor issues (besides those you mentioned):

 (1) Some hunks didn't apply for some reason, though the failed hunks
     _did_ apply when I tried in diff-mode, so perhaps there's a
     character encoding issue.  I've appended a patch generated with
     `cvs diff' that the patch program seems to be happy with.

 (2) HAVE_GTK isn't defined in src/config.in, and I had problems getting
     autoheader to do so (the autoheader invocation in the top-level
     Makefile seems to not be correct, though maybe I screwed something
     up).  I've also included this change in the patch at the end of
     this message.

 (3) The `xg_win_to_widget' function in gtkutil.c contained intermixed
     declarations and statements, which is not legal C (I _think_ it's
     legal in C99, but most people are using older compilers).

 (4) It looks like the user has to give the `--with-gtk' option to
     configure to enable GTK.  I think using `--with-x-toolkit=gtk'
     would be more correct, at least from a user's perspective.

I'll withhold comments on scrollbars &c. until you think you've got
those working properly.


Here's my change to gtkutil.c:



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Fix to src/gtkutil.c --]
[-- Type: text/x-patch, Size: 455 bytes --]

diff -up src/gtkutil.c.\~1\~ src/gtkutil.c
--- src/gtkutil.c.~1~	2002-12-09 10:58:30.000000000 +0900
+++ src/gtkutil.c	2002-12-09 13:41:36.000000000 +0900
@@ -754,9 +754,12 @@ GtkWidget*
 xg_win_to_widget (wdesc)
      Window wdesc;
 {
-  BLOCK_INPUT;
-  gpointer gdkwin = gdk_xid_table_lookup (wdesc);
+  gpointer gdkwin;
   GtkWidget *gwdesc = 0;
+
+  BLOCK_INPUT;
+
+  gdkwin= gdk_xid_table_lookup (wdesc);
   if (gdkwin)
     {
       GdkEvent event;

[-- Attachment #3: Type: text/plain, Size: 92 bytes --]



Here's my re-diffed version of your patch, plus an entry for HAVE_GTK in
src/config.in:



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: GTK patch --]
[-- Type: text/x-patch, Size: 77904 bytes --]

Index: configure.in
===================================================================
RCS file: /cvsroot/emacs/emacs/configure.in,v
retrieving revision 1.315
diff -u -I*~ -r1.315 configure.in
--- configure.in	27 Nov 2002 22:53:51 -0000	1.315
+++ configure.in	9 Dec 2002 04:45:16 -0000
@@ -107,6 +107,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])
+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])
@@ -1781,6 +1785,86 @@
   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"; then
+  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)
+  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 +1987,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 +2004,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
 
@@ -2723,6 +2810,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}'.
 
Index: src/Makefile.in
===================================================================
RCS file: /cvsroot/emacs/emacs/src/Makefile.in,v
retrieving revision 1.262
diff -u -I*~ -r1.262 Makefile.in
--- src/Makefile.in	25 Nov 2002 19:08:14 -0000	1.262
+++ src/Makefile.in	9 Dec 2002 04:45:20 -0000
@@ -252,12 +252,19 @@
 #define C_SWITCH_ASM
 #endif
 
+#ifdef 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 */
 
@@ -1143,18 +1162,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
+
 hftctl.o: hftctl.c $(config_h)
 sound.o: sound.c dispextern.h $(config_h)
 atimer.o: atimer.c atimer.h systime.h $(config_h)
Index: src/alloc.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/alloc.c,v
retrieving revision 1.282
diff -u -I*~ -r1.282 alloc.c
--- src/alloc.c	14 Nov 2002 14:12:12 -0000	1.282
+++ src/alloc.c	9 Dec 2002 04:45:23 -0000
@@ -4245,6 +4245,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.  */
Index: src/config.in
===================================================================
RCS file: /cvsroot/emacs/emacs/src/config.in,v
retrieving revision 1.178
diff -u -I*~ -r1.178 config.in
--- src/config.in	29 Nov 2002 06:25:05 -0000	1.178
+++ src/config.in	9 Dec 2002 04:45:23 -0000
@@ -721,6 +721,10 @@
 /* Define to 1 if using an X toolkit. */
 #undef USE_X_TOOLKIT
 
+/* Define if using GTK. */
+#undef HAVE_GTK
+
+
 /* Define to 1 if on AIX 3.
    System headers sometimes define this.
    We just want to avoid a redefinition error message.  */
Index: src/fileio.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/fileio.c,v
retrieving revision 1.467
diff -u -I*~ -r1.467 fileio.c
--- src/fileio.c	7 Dec 2002 21:39:50 -0000	1.467
+++ src/fileio.c	9 Dec 2002 04:45:27 -0000
@@ -6105,7 +6105,7 @@
 
   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 ())
Index: src/frame.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/frame.h,v
retrieving revision 1.98
diff -u -I*~ -r1.98 frame.h
--- src/frame.h	14 Nov 2002 14:15:48 -0000	1.98
+++ src/frame.h	9 Dec 2002 04:45:28 -0000
@@ -270,7 +270,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
@@ -468,7 +469,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
Index: src/keyboard.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/keyboard.c,v
retrieving revision 1.716
diff -u -I*~ -r1.716 keyboard.c
--- src/keyboard.c	22 Nov 2002 12:23:13 -0000	1.716
+++ src/keyboard.c	9 Dec 2002 04:45:33 -0000
@@ -3857,7 +3862,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;
@@ -3964,7 +3970,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
@@ -5027,7 +5034,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.
@@ -5079,7 +5086,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.  */
@@ -5317,7 +5324,7 @@
 	}
       }
 
-#ifdef USE_TOOLKIT_SCROLL_BARS
+#if USE_TOOLKIT_SCROLL_BARS
 
       /* We don't have down and up events if using toolkit scroll bars,
 	 so make this always a click event.  Store in the `part' of
@@ -5568,7 +5575,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
Index: src/lisp.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lisp.h,v
retrieving revision 1.443
diff -u -I*~ -r1.443 lisp.h
--- src/lisp.h	25 Nov 2002 19:06:07 -0000	1.443
+++ src/lisp.h	9 Dec 2002 04:45:35 -0000
@@ -3122,6 +3122,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 */
Index: src/xdisp.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xdisp.c,v
retrieving revision 1.793
diff -u -I*~ -r1.793 xdisp.c
--- src/xdisp.c	29 Nov 2002 16:19:26 -0000	1.793
+++ src/xdisp.c	9 Dec 2002 04:45:44 -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
@@ -7512,7 +7513,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
@@ -7563,7 +7565,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
@@ -7576,11 +7579,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);
@@ -8544,7 +8547,7 @@
 	return;
     }
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (popup_activated ())
     return;
 #endif
@@ -10761,7 +10764,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)
 	  redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
 	  redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
Index: src/xfns.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xfns.c,v
retrieving revision 1.567
diff -u -I*~ -r1.567 xfns.c
--- src/xfns.c	6 Dec 2002 17:05:15 -0000	1.567
+++ src/xfns.c	9 Dec 2002 04:45:50 -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>
 
@@ -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.  */
 
@@ -377,13 +390,23 @@
 	    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.  */
@@ -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,6 +532,11 @@
       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,
@@ -494,6 +547,7 @@
 	      && 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 */
 
 \f
 
@@ -2119,7 +2173,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 +2190,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 */
@@ -2465,8 +2519,13 @@
 	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));
+#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))
@@ -3938,7 +3997,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
@@ -4041,6 +4109,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
@@ -4618,7 +4687,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 +4695,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 /* not USE_GTK */
     }
-#endif /* USE_X_TOOLKIT */
+#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
@@ -11692,6 +11763,177 @@
 
 #endif /* USE_MOTIF */
 
+#ifdef USE_GTK
+
+enum
+{
+  GTK_FILE_NOT_DONE,
+  GTK_FILE_OK,
+  GTK_FILE_CANCEL,
+  GTK_FILE_DESTROY,
+  GTK_FILE_ACTIVATE
+};
+
+static void
+FileSelOk (w, arg)
+     GtkWidget *w;
+     gpointer arg;
+{
+  *(int*)arg = GTK_FILE_OK;
+}
+
+static void
+FileSelCancel (w, arg)
+     GtkWidget *w;
+     gpointer arg;
+{
+  *(int*)arg = GTK_FILE_CANCEL;
+}
+
+static void
+FileSelDestroy (w, arg)
+     GtkWidget *w;
+     gpointer arg;
+{
+  *(int*)arg = GTK_FILE_DESTROY;
+}
+
+static void
+FileSelActivated (w, arg)
+     GtkWidget *w;
+     gpointer arg;
+{
+  *(int*)arg = GTK_FILE_ACTIVATE;
+}
+
+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;
+{
+  GtkWidget* filewin;
+  GtkFileSelection* filesel;
+  char *fn;
+  int gtk_file_done = GTK_FILE_NOT_DONE;
+  Lisp_Object file = Qnil;
+  Lisp_Object def_nodir = Qnil;
+  int count = specpdl_ptr - specpdl;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
+
+  GCPRO6 (prompt, dir, default_filename, mustmatch, def_nodir, file);
+  CHECK_STRING (prompt);
+  CHECK_STRING (dir);
+
+  /* Prevent redisplay.  */
+  specbind (Qinhibit_redisplay, Qt);
+
+  BLOCK_INPUT;
+
+  filewin = gtk_file_selection_new (SDATA (prompt));
+  filesel = GTK_FILE_SELECTION (filewin);
+      
+  g_signal_connect (filesel->ok_button,
+                    "clicked",
+                    G_CALLBACK (FileSelOk),
+                    &gtk_file_done);
+  g_signal_connect (filesel->cancel_button,
+                    "clicked",
+                    G_CALLBACK (FileSelCancel),
+                    &gtk_file_done);
+  g_signal_connect (filesel,
+                    "destroy",
+                    G_CALLBACK (FileSelDestroy),
+                    &gtk_file_done);
+
+  /* KOKO: GTK fileselection dialog does not have separate directory and
+     default filename options. */
+  /* dir = Fexpand_file_name (dir, Qnil);*/
+  if (STRINGP (default_filename))
+    {
+      gtk_file_selection_set_filename (filesel, SDATA (default_filename));
+    }
+
+  if (! NILP (mustmatch))
+    {
+      GtkTreeSelection *sel;
+      sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (filesel->file_list));
+      g_signal_connect (sel,
+                        "changed",
+                        G_CALLBACK (FileSelActivated),
+                        &gtk_file_done);
+      gtk_widget_set_sensitive (filesel->ok_button, FALSE);
+      gtk_widget_set_sensitive (filesel->file_list, FALSE);
+      gtk_file_selection_hide_fileop_buttons (filesel);
+      if (STRINGP (default_filename))
+        {
+          def_nodir = Ffile_name_nondirectory (default_filename);
+          /* The row below doesn't seem to work the way it does in Motif,
+             i.e. only show files with this name.  Must do this some
+             other way.
+          gtk_file_selection_complete(filesel, SDATA (def_nodir));
+          */
+        }
+    }
+
+  
+  gtk_widget_show (filewin);
+  while (gtk_file_done == GTK_FILE_NOT_DONE)
+    {
+      gtk_main_iteration ();
+      if (NILP (mustmatch)
+          || NILP (def_nodir)
+          || gtk_file_done == GTK_FILE_CANCEL
+          || gtk_file_done == GTK_FILE_DESTROY
+          || gtk_file_done == GTK_FILE_OK)
+        continue;
+      
+      fn = (char*)gtk_file_selection_get_filename (filesel);
+      file = build_string (fn);
+
+      gtk_widget_set_sensitive (filesel->ok_button,
+                                ! NILP (Ffile_exists_p (file)));
+
+      file = Ffile_name_nondirectory (file);
+
+      /* This is not so nice, but there is no official way to do this
+         i.e. without using undocumented things in filesel. */
+      if (strcmp (SDATA (def_nodir), SDATA (file)) != 0)
+        {
+          gtk_file_selection_set_filename (filesel, SDATA (def_nodir));
+          gtk_widget_set_sensitive (filesel->ok_button, FALSE);
+        }
+
+      gtk_file_done = GTK_FILE_NOT_DONE;
+    }
+      
+
+  if (gtk_file_done == GTK_FILE_OK)
+    {
+      fn = (char*)gtk_file_selection_get_filename (filesel);
+      file = build_string (fn);
+    }
+  else if (gtk_file_done == GTK_FILE_DESTROY)
+    {
+      filesel = 0;
+    }
+  
+  if (filesel) gtk_widget_destroy (filewin);
+
+  UNBLOCK_INPUT;
+  UNGCPRO;
+
+  /* Make "Cancel" equivalent to C-g.  */
+  if (NILP (file))
+    Fsignal (Qquit, Qnil);
+  
+  return unbind_to (count, file);
+}
+
+#endif /* USE_GTK */
 
 \f
 /***********************************************************************
Index: src/xmenu.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xmenu.c,v
retrieving revision 1.237
diff -u -I*~ -r1.237 xmenu.c
--- src/xmenu.c	14 Nov 2002 14:21:11 -0000	1.237
+++ src/xmenu.c	9 Dec 2002 04:45:52 -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 */
 
@@ -117,6 +119,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,
@@ -592,7 +601,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 (" >"));
@@ -605,7 +614,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)))
     {
@@ -972,7 +981,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.  */
   {
@@ -1013,7 +1022,7 @@
 #endif
 }
 \f
-#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
@@ -1022,6 +1031,7 @@
    NOTE: All calls to popup_get_selection should be protected
    with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
 
+#ifdef USE_X_TOOLKIT
 void
 popup_get_selection (initial_event, dpyinfo, id)
      XEvent *initial_event;
@@ -1122,6 +1132,25 @@
       interrupt_input_pending = 1;
     }
 }
+#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 = 1;
+
+  /* Process events in the Gtk event loop until done.  */
+  xg_pass_through_events = TRUE;
+  while (popup_activated_flag)
+    {
+      gtk_main_iteration ();
+    }
+  xg_pass_through_events = FALSE;
+}
+#endif
 
 /* Activate the menu bar of frame F.
    This is called from keyboard.c when it gets the
@@ -1144,9 +1173,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)
@@ -1168,11 +1208,18 @@
 /* This callback is invoked when the user selects a menubar cascade
    pushbutton, but before the pulldown menu is posted.  */
 
+#ifdef USE_GTK
+static void
+popup_activate_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+#else
 static void
 popup_activate_callback (widget, id, client_data)
      Widget widget;
      LWLIB_ID id;
      XtPointer client_data;
+#endif
 {
   popup_activated_flag = 1;
 }
@@ -1180,35 +1227,64 @@
 /* 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;
+#else
 static void
 popup_deactivate_callback (widget, id, client_data)
      Widget widget;
      LWLIB_ID id;
      XtPointer client_data;
+#endif
 {
   popup_activated_flag = 0;
 }
 
-/* Lwlib callback called when menu items are highlighted/unhighlighted
+/* 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.  */
 
+#ifdef USE_GTK
+void
+menu_highlight_callback (widget, call_data)
+     GtkWidget *widget;
+     gpointer call_data;
+#else
 void
 menu_highlight_callback (widget, id, call_data)
      Widget widget;
      LWLIB_ID id;
      void *call_data;
+#endif
 {
-  widget_value *wv = (widget_value *) call_data;
   struct frame *f;
   Lisp_Object frame, help;
 
+#ifdef USE_GTK
+  struct menu_gtk_data *cl_data;
+  cl_data = (struct menu_gtk_data*) g_object_get_data (G_OBJECT (widget),
+                                                       G_FRAME_DATA);
+  if (! cl_data) return;
+  
+  f = cl_data->f;
+
+  /* NYI */
+  return;
+  
+#else
+  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);
+#endif
+
   if (f)
     {
       XSETFRAME (frame, f);
@@ -1218,7 +1294,11 @@
     {
       /* WIDGET is the popup menu.  It's parent is the frame's 
 	 widget.  See which frame that is.  */
+#ifdef USE_GTK
+      GtkWidget *frame_widget = gtk_widget_get_parent (widget);
+#else
       Widget frame_widget = XtParent (widget);
+#endif
       Lisp_Object tail;
 
       for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
@@ -1234,32 +1314,66 @@
     }
 }
 
+/* Gtk calls callbacks just because we tell it what item should be
+   selected in a radio group.  If this variable is set to z non-zero
+   value, we are creating menus and don't want callbacks right now.
+*/
+#ifdef USE_GTK
+static int xg_crazy_callback_abort = 0;
+#endif
+
 /* 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.  */
-
+#ifdef USE_GTK
+static void
+menubar_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+#else
 static void
 menubar_selection_callback (widget, id, client_data)
      Widget widget;
      LWLIB_ID id;
      XtPointer client_data;
+#endif
 {
   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;
+  int menu_bar_items_used;
+
+#ifdef USE_GTK
+  FRAME_PTR f;
+  struct menu_gtk_data *cl_data;
+
+  if (xg_crazy_callback_abort)
+    return;
+  
+  cl_data = (struct menu_gtk_data*) g_object_get_data (G_OBJECT (widget),
+                                                       G_FRAME_DATA);
+  if (! cl_data || ! cl_data->f)
+    return;
 
+  menu_bar_items_used = cl_data->menu_bar_items_used;
+  f = cl_data->f;
+  vector = cl_data->menu_bar_vector;
+#else
+  FRAME_PTR f = menubar_id_to_frame (id);
+  menu_bar_items_used = f->menu_bar_items_used;
   if (!f)
     return;
-  entry = Qnil;
-  subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
   vector = f->menu_bar_vector;
+#endif
+
+  entry = Qnil;
+  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))
 	{
@@ -1592,6 +1706,9 @@
 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;
   
@@ -1626,6 +1743,7 @@
   /* Force the pane widget to resize itself with the right values.  */
   EmacsFrameSetCharSize (x->edit_widget, columns, rows);
   UNBLOCK_INPUT;
+#endif
   return 1;
 }
 
@@ -1639,20 +1757,26 @@
      int first_time;
      int deep_p;
 {
+#ifdef USE_GTK
+  GtkWidget *menubar_widget = f->output_data.x->menubar_widget;
+#else
   Widget menubar_widget = f->output_data.x->menubar_widget;
+  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;
 
-  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;
@@ -1859,6 +1983,38 @@
 
   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 (popup_activate_callback),
+                                 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, 
+                            0,
+                            G_CALLBACK (popup_activate_callback),
+                            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!) */
@@ -1902,13 +2058,17 @@
       }
 #endif /* USE_LUCID */
 #endif /* 0 */
-
     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;
 }
 
@@ -1935,6 +2095,9 @@
 free_frame_menubar (f)
      FRAME_PTR f;
 {
+#ifdef USE_GTK
+  xg_free_frame_menubar (f);
+#else /* not USE_GTK */
   Widget menubar_widget;
 
   menubar_widget = f->output_data.x->menubar_widget;
@@ -1976,9 +2139,10 @@
       
       UNBLOCK_INPUT;
     }
+#endif /* not USE_GTK */
 }
 
-#endif /* USE_X_TOOLKIT */
+#endif /* USE_X_TOOLKIT || USE_GTK */
 \f
 /* xmenu_show actually displays a menu using the panes and items in menu_items
    and returns the value selected from it.
@@ -1996,7 +2160,7 @@
    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)
 
 /* We need a unique id for each widget handled by the Lucid Widget
    library.
@@ -2006,15 +2170,24 @@
 
    For menu bars, we use numbers starting at 0, counted in
    next_menubar_widget_id.  */
+#ifdef USE_X_TOOLKIT
 LWLIB_ID widget_id_tick;
+#endif
 
 static Lisp_Object *volatile menu_item_selection;
 
+#ifdef USE_GTK
+static void
+popup_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+#else
 static void
 popup_selection_callback (widget, id, client_data)
      Widget widget;
      LWLIB_ID id;
      XtPointer client_data;
+#endif
 {
   menu_item_selection = (Lisp_Object *) client_data;
 }
@@ -2030,17 +2203,21 @@
      char **error;
 {
   int i;
+#ifdef USE_GTK
+  GtkWidget *menu;
+#else
   LWLIB_ID menu_id;
   Widget menu;
   Arg av[2];
   int ac = 0;
+  XButtonPressedEvent dummy;
+#endif
   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;
 
@@ -2233,6 +2410,14 @@
     }
 
   /* Actually create the menu.  */
+#ifdef USE_GTK
+  menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
+                           1,
+                           0,
+                           G_CALLBACK (popup_selection_callback),
+                           G_CALLBACK (popup_deactivate_callback),
+                           G_CALLBACK (menu_highlight_callback));
+#else
   menu_id = widget_id_tick++;
   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
 			   f->output_data.x->widget, 1, 0,
@@ -2240,6 +2425,7 @@
 			   popup_deactivate_callback,
 			   menu_highlight_callback);
 
+#endif
   /* Adjust coordinates to relative to the outer (window manager) window.  */
   {
     Window child;
@@ -2271,6 +2457,30 @@
   x += f->output_data.x->left_pos;
   y += f->output_data.x->top_pos;
 
+#ifdef USE_GTK
+  for (i = 0; i < 5; i++)
+    if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+      break;
+
+  /* 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.  */
+  gtk_menu_popup (GTK_MENU (menu), 0, 0, 0, 0, i, 0);
+  
+  /* Process events that apply to the menu.  */
+  popup_widget_loop ();
+
+  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 */
   dummy.type = ButtonPress;
   dummy.serial = 0;
   dummy.send_event = 0;
@@ -2311,6 +2521,7 @@
      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 */
 
   /* Find the selected item, and its pane, to return
      the proper value.  */
@@ -2370,19 +2581,28 @@
   return Qnil;
 }
 \f
+#ifdef USE_GTK
+static void
+dialog_selection_callback (widget, client_data)
+     GtkWidget *widget;
+     gpointer client_data;
+#else
 static void
 dialog_selection_callback (widget, id, client_data)
      Widget widget;
      LWLIB_ID id;
      XtPointer client_data;
+#endif
 {
   /* 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;
+#ifdef USE_X_TOOLKIT
   BLOCK_INPUT;
   lw_destroy_all_widgets (id);
   UNBLOCK_INPUT;
+#endif
   popup_activated_flag = 0;
 }
 
@@ -2398,8 +2618,12 @@
      char **error;
 {
   int i, nb_buttons=0;
+#ifdef USE_GTK
+  GtkWidget *menu;
+#else
   LWLIB_ID dialog_id;
   Widget menu;
+#endif
   char dialog_name[6];
 
   widget_value *wv, *first_wv = 0, *prev_wv = 0;
@@ -2510,11 +2734,19 @@
   }
 
   /* Actually create the dialog.  */
+#ifdef USE_GTK
+  menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
+                           0, 0,
+                           G_CALLBACK (dialog_selection_callback),
+                           G_CALLBACK (popup_deactivate_callback),
+                           0);
+#else
   dialog_id = widget_id_tick++;
   menu = 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);
+#endif
   /* Free the widget_value objects we used to specify the contents.  */
   free_menubar_widget_value_tree (first_wv);
 
@@ -2522,6 +2754,18 @@
   menu_item_selection = 0;
 
   /* Display the menu.  */
+#ifdef USE_GTK
+  if (menu)
+    {
+      /* Display the menu.  */
+      gtk_widget_show_all (menu);
+
+      /* Process events that apply to the menu.  */
+      popup_widget_loop ();
+  
+      if (menu_item_selection != 0) gtk_widget_destroy (menu);
+    }
+#else
   lw_pop_up_all_widgets (dialog_id);
   popup_activated_flag = 1;
 
@@ -2529,7 +2773,7 @@
   popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
 
   lw_destroy_all_widgets (dialog_id); 
-
+#endif
   /* Find the selected item, and its pane, to return
      the proper value.  */
   if (menu_item_selection != 0)
@@ -2576,7 +2820,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.  */
Index: src/xterm.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xterm.c,v
retrieving revision 1.764
diff -u -I*~ -r1.764 xterm.c
--- src/xterm.c	17 Nov 2002 23:49:32 -0000	1.764
+++ src/xterm.c	9 Dec 2002 04:46:00 -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
@@ -7074,7 +7080,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
@@ -8494,10 +8500,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 +8512,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 +8569,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 +8663,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]);
@@ -8663,7 +8675,6 @@
   ievent->modifiers = 0;
 }
 
-
 #ifdef USE_MOTIF
 
 /* Minimum and maximum values used for Motif scroll bars.  */
@@ -8749,8 +8760,82 @@
 }
 
 
-#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 slider_size;
+  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);
+  slider_size = (adj->upper - adj->lower)/adj->page_size;
+
+  p = g_object_get_data (G_OBJECT (widget), G_LAST_SB_DATA);
+  if (! p)
+    {
+      p = (gdouble*) xmalloc (sizeof (gdouble));
+      *p = GTK_SB_MIN;
+      g_object_set_data (G_OBJECT (widget), G_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 = GTK_SB_RANGE;
+      portion = position;
+      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,7 +8918,7 @@
   x_send_scroll_bar_event (bar->window, part, position, height);
 }
 
-
+#endif /* not USE_GTK */
 #endif /* not USE_MOTIF */
 
 
@@ -8845,15 +8930,21 @@
      struct frame *f;
      struct scroll_bar *bar;
 {
+#ifndef USE_GTK
   Window xwindow;
   Widget widget;
   Arg av[20];
   int ac = 0;
+#endif
   char *scroll_bar_name = "verticalScrollBar";
   unsigned long pixel;
 
   BLOCK_INPUT;
 
+#ifdef USE_GTK
+  xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+                        scroll_bar_name);
+#else /* not USE_GTK */
 #ifdef USE_MOTIF
   /* Set resources.  Create the widget.  */
   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
@@ -9020,6 +9111,7 @@
   xwindow = XtWindow (widget);
   SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
 
+#endif /* not USE_GTK */
   UNBLOCK_INPUT;
 }
 
@@ -9032,12 +9124,17 @@
      struct scroll_bar *bar;
      int portion, position, whole;
 {
+#ifndef USE_GTK
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
   float top, shown;
+#endif
 
   BLOCK_INPUT;
 
+#ifdef USE_GTK
+  xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+#else
 #ifdef USE_MOTIF
 
   /* We use an estimate of 30 chars per line rather than the real
@@ -9146,6 +9243,7 @@
       }
   }
 #endif /* !USE_MOTIF */
+#endif /* not USE_GTK */
 
   UNBLOCK_INPUT;
 }
@@ -9237,6 +9335,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 +9351,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 +9486,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
@@ -9471,6 +9583,17 @@
 	mask |= CWHeight;
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_GTK
+      if (mask)
+        {
+          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));
+        }
+#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.  */
@@ -9486,6 +9609,7 @@
 			   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
@@ -10107,111 +10231,106 @@
 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
 #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
 
-/* Read events coming from the X server.
-   This routine is called by the SIGIO handler.
-   We return as soon as there are no more events to be read.
+enum
+{
+  X_EVENT_NORMAL,
+  X_EVENT_GOTO_OUT,
+  X_EVENT_GOTO_OTHER
+};
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
-   We return the number of characters stored into the buffer,
-   thus pretending to be `read'.
+#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;
+static int xg_drop_event;
+
+static int handle_one_xevent P_ ((struct x_display_info *dpyinfo,
+                                  XEvent *eventp,
+                                  struct input_event **bufp_r,
+                                  int *numcharsp,
+                                  int *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 gtk_pass_through_events is TRUE we want events to go to GTK only.
+     But Expose is passed to the Emacs loop so redraw is done correctly.
+     gtk_pass_through_events is set to TRUE by menu popups and dialogs. */
+  if (xg_pass_through_events && xev->type != Expose)
+    return GDK_FILTER_CONTINUE;
+  
+  xg_drop_event = 0;
+  if (current_numcharsp)
+    {
+      current_count += handle_one_xevent (current_dpyinfo,
+                                          xev,
+                                          current_bufp,
+                                          current_numcharsp,
+                                          &current_finish);
+    }
+  else
+    {
+      struct x_display_info *dpyinfo;
+      struct input_event bufp[10];
+      struct input_event *bufpp = bufp;
+      int numchars = 10;
+
+      for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+          if (dpyinfo->display == GDK_DISPLAY ())
+            break;
+
+      if (dpyinfo)
+        handle_one_xevent (dpyinfo,
+                           xev,
+                           &bufpp,
+                           &numchars,
+                           &current_finish);
+
+      /* KOKO: Store emacs events? */
+    }
+
+  if (current_finish == X_EVENT_GOTO_OUT || xg_drop_event)
+    return GDK_FILTER_REMOVE;
+
+  return GDK_FILTER_CONTINUE;
+	}
+#endif /* USE_GTK */
+
+/* Handles the XEvent EVENT on display DPYINFO.
+
+   *FINISH is non-zero if caller should stop processing events,
+   *FINISH is zero if caller should continue reading events.
+
+   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. */
 
-   EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, bufp, numchars, expected)
-     register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
-     int expected;
-{
+handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+     struct x_display_info *dpyinfo;
+     XEvent *eventp;
+     /* register */ struct input_event **bufp_r;
+     /* register */ int *numcharsp;
+     int *finish;
+	  {
   int count = 0;
   int nbytes = 0;
-  XEvent event;
   struct frame *f;
-  int event_found = 0;
-  struct x_display_info *dpyinfo;
   struct coding_system coding;
-
-  if (interrupt_input_blocked)
-    {
-      interrupt_input_pending = 1;
-      return -1;
-    }
-
-  interrupt_input_pending = 0;
-  BLOCK_INPUT;
-
-  /* So people can tell when we have read the available input.  */
-  input_signal_count++;
-
-  if (numchars <= 0)
-    abort ();			/* Don't think this happens.  */
-
-  ++handling_signal;
-
-  /* Find the display we are supposed to read input for.
-     It's the one communicating on descriptor SD.  */
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-    {
-#if 0 /* This ought to be unnecessary; let's verify it.  */
-#ifdef FIOSNBIO
-      /* If available, Xlib uses FIOSNBIO to make the socket
-	 non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
-	 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
-	 a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
-      fcntl (dpyinfo->connection, F_SETFL, 0);
-#endif /* ! defined (FIOSNBIO) */
-#endif
-
-#if 0 /* This code can't be made to work, with multiple displays,
-	 and appears not to be used on any system any more.
-	 Also keyboard.c doesn't turn O_NDELAY on and off
-	 for X connections.  */
-#ifndef SIGIO
-#ifndef HAVE_SELECT
-      if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
-	{
-	  extern int read_alarm_should_throw;
-	  read_alarm_should_throw = 1;
-	  XPeekEvent (dpyinfo->display, &event);
-	  read_alarm_should_throw = 0;
-	}
-#endif /* HAVE_SELECT */
-#endif /* SIGIO */
-#endif
-
-      /* For debugging, this gives a way to fake an I/O error.  */
-      if (dpyinfo == XTread_socket_fake_io_error)
-	{
-	  XTread_socket_fake_io_error = 0;
-	  x_io_error_quitter (dpyinfo->display);
-	}
-
-#ifdef HAVE_X_SM
-      BLOCK_INPUT;
-      count += x_session_check_input (bufp, &numchars);
-      UNBLOCK_INPUT;
-#endif
-
-      while (XPending (dpyinfo->display))
-	{
-	  XNextEvent (dpyinfo->display, &event);
-
-#ifdef HAVE_X_I18N
-	  {
-	    /* Filter events for the current X input method.
-	       XFilterEvent returns non-zero if the input method has
-	       consumed the event.  We pass the frame's X window to
-	       XFilterEvent because that's the one for which the IC
-	       was created.  */
-	    struct frame *f1 = x_any_window_to_frame (dpyinfo,
-						      event.xclient.window);
-	    if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
-	      break;
-	  }
-#endif
-	  event_found = 1;
+  struct input_event *bufp = *bufp_r;
+  int numchars = *numcharsp;
+  XEvent event = *eventp;
 
 	  switch (event.type)
 	    {
@@ -10316,11 +10435,17 @@
 			    bufp->arg = Qnil;
 			    bufp++;
 
-			    count += 1;
-			    numchars -= 1;
-			  }
-		      }
-		  }
+
+                    count += 1;
+                    numchars -= 1;
+#ifdef USE_GTK
+                    /* Can't pass this to GTK, it will delete
+                       widgets beyond our control.  Go figure. */
+                    xg_drop_event = 1;
+#endif
+                  }
+              }
+          }
 		else if (event.xclient.message_type
 			 == dpyinfo->Xatom_wm_configure_denied)
 		  {
@@ -10526,12 +10651,15 @@
 	    case GraphicsExpose:	/* This occurs when an XCopyArea's
 					   source area was obscured or not
 					   available.  */
-	      f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
-	      if (f)
-		{
-		  expose_frame (f,
-				event.xgraphicsexpose.x, event.xgraphicsexpose.y,
-				event.xgraphicsexpose.width,
+      f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
+      if (f)
+        {
+#ifdef USE_GTK
+          xg_drop_event = 1;
+#endif
+          expose_frame (f,
+                        event.xgraphicsexpose.x, event.xgraphicsexpose.y,
+                        event.xgraphicsexpose.width,
 				event.xgraphicsexpose.height);
 		}
 #ifdef USE_X_TOOLKIT
@@ -11186,12 +11314,16 @@
 
 	    case ConfigureNotify:
 	      f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
-	      if (f)
-		{
+      if (f)
+        {
 #ifndef USE_X_TOOLKIT
-                  /* 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
+#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
 		     need to reset it below.  */
                   int dont_resize =
                     ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
@@ -11214,26 +11346,37 @@
 		      || event.xconfigure.height != f->output_data.x->pixel_height)
 		    {
 		      change_frame_size (f, rows, columns, 0, 1, 0);
-		      SET_FRAME_GARBAGED (f);
-		      cancel_mouse_face (f);
-		    }
+              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;
+          f->output_data.x->pixel_width = event.xconfigure.width;
+          f->output_data.x->pixel_height = event.xconfigure.height;
 
-		  /* 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,
+#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);
-                  if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
-                    f->output_data.x->want_fullscreen &=
-                      ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+          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);
+          if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+            xic_set_statusarea (f);
 #endif
 
 		  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
@@ -11328,14 +11471,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_flag
+            &&
+#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
@@ -11343,12 +11491,15 @@
 		    && event.xbutton.y >= 0
 		    && event.xbutton.y < f->output_data.x->menubar_height
 		    && event.xbutton.same_screen)
-		  {
-		    SET_SAVED_BUTTON_EVENT;
-		    XSETFRAME (last_mouse_press_frame, f);
-		  }
-		else if (event.type == ButtonPress)
-		  {
+          {
+            SET_SAVED_BUTTON_EVENT;
+            XSETFRAME (last_mouse_press_frame, f);
+#ifdef USE_GTK
+            xg_drop_event = 1;
+#endif
+          }
+        else if (event.type == ButtonPress)
+          {
 		    last_mouse_press_frame = Qnil;
 		    goto OTHER;
 		  }
@@ -11369,7 +11520,7 @@
 #endif /* USE_MOTIF */
 		else
 		  goto OTHER;
-#endif /* USE_X_TOOLKIT */
+#endif /* USE_X_TOOLKIT || USE_GTK */
 	      }
 	      break;
 
@@ -11399,16 +11550,171 @@
 	    OTHER:
 #ifdef USE_X_TOOLKIT
 	      BLOCK_INPUT;
-	      XtDispatchEvent (&event);
-	      UNBLOCK_INPUT;
+    XtDispatchEvent (&event);
+    UNBLOCK_INPUT;
 #endif /* USE_X_TOOLKIT */
-	      break;
-	    }
+    *finish = X_EVENT_GOTO_OTHER;
+    break;
+    goto ret;
+    }
+
+  *finish = X_EVENT_NORMAL;
+  goto ret;
+  
+ out:
+  *finish = X_EVENT_GOTO_OUT;
+
+ ret:
+  *bufp_r = bufp;
+  *numcharsp = numchars;
+  *eventp = event;
+  
+  return count;
+}
+
+/* Read events coming from the X server.
+   This routine is called by the SIGIO handler.
+   We return as soon as there are no more events to be read.
+
+   Events representing keys are stored in buffer BUFP,
+   which can hold up to NUMCHARS characters.
+   We return the number of characters stored into the buffer,
+   thus pretending to be `read'.
+
+   EXPECTED is nonzero if the caller knows input is available.  */
+
+static int
+XTread_socket (sd, bufp, numchars, expected)
+     register int sd;
+     /* register */ struct input_event *bufp;
+     /* register */ int numchars;
+     int expected;
+{
+  int count = 0;
+  int nbytes = 0;
+  XEvent event;
+  int event_found = 0;
+  struct x_display_info *dpyinfo;
+
+  if (interrupt_input_blocked)
+    {
+      interrupt_input_pending = 1;
+      return -1;
+    }
+
+  interrupt_input_pending = 0;
+  BLOCK_INPUT;
+
+  /* So people can tell when we have read the available input.  */
+  input_signal_count++;
+
+  if (numchars <= 0)
+    abort ();			/* Don't think this happens.  */
+
+  ++handling_signal;
+
+  /* Find the display we are supposed to read input for.
+     It's the one communicating on descriptor SD.  */
+  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+    {
+#if 0 /* This ought to be unnecessary; let's verify it.  */
+#ifdef FIOSNBIO
+      /* If available, Xlib uses FIOSNBIO to make the socket
+	 non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
+	 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
+	 a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
+      fcntl (dpyinfo->connection, F_SETFL, 0);
+#endif /* ! defined (FIOSNBIO) */
+#endif
+
+#if 0 /* This code can't be made to work, with multiple displays,
+	 and appears not to be used on any system any more.
+	 Also keyboard.c doesn't turn O_NDELAY on and off
+	 for X connections.  */
+#ifndef SIGIO
+#ifndef HAVE_SELECT
+      if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
+	{
+	  extern int read_alarm_should_throw;
+	  read_alarm_should_throw = 1;
+	  XPeekEvent (dpyinfo->display, &event);
+	  read_alarm_should_throw = 0;
 	}
+#endif /* HAVE_SELECT */
+#endif /* SIGIO */
+#endif
+
+      /* For debugging, this gives a way to fake an I/O error.  */
+      if (dpyinfo == XTread_socket_fake_io_error)
+	{
+	  XTread_socket_fake_io_error = 0;
+	  x_io_error_quitter (dpyinfo->display);
+	}
+
+#ifdef HAVE_X_SM
+      BLOCK_INPUT;
+      count += x_session_check_input (bufp, &numchars);
+      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 ())
+        {
+          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;
+          
+	  XNextEvent (dpyinfo->display, &event);
+
+#ifdef HAVE_X_I18N
+	  {
+	    /* Filter events for the current X input method.
+	       XFilterEvent returns non-zero if the input method has
+	       consumed the event.  We pass the frame's X window to
+	       XFilterEvent because that's the one for which the IC
+	       was created.  */
+	    struct frame *f1 = x_any_window_to_frame (dpyinfo,
+						      event.xclient.window);
+	    if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
+	      break;
+	  }
+#endif
+	  event_found = 1;
+
+          count += handle_one_xevent (dpyinfo,
+                                      &event,
+                                      &bufp,
+                                      &numchars,
+                                      &finish);
+
+          if (finish == X_EVENT_GOTO_OUT)
+            goto out;
+        }
+#endif /* USE_GTK */
     }
 
  out:;
-
   /* On some systems, an X bug causes Emacs to get no more events
      when the window is destroyed.  Detect that.  (1994.)  */
   if (! event_found)
@@ -12862,11 +13168,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.
@@ -12997,13 +13299,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),
+  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
 	       modified_left, modified_top);
-#endif /* not USE_X_TOOLKIT */
   UNBLOCK_INPUT;
 }
 
@@ -13189,7 +13486,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)
     {
@@ -13385,7 +13687,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
@@ -13536,6 +13842,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,
@@ -13570,6 +13884,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
@@ -13609,6 +13924,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))
@@ -13743,6 +14074,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 */
@@ -13836,16 +14179,20 @@
      long flags;
      int user_position;
 {
+#ifdef USE_GTK
+  /* Must use GTK routines here, otherwise Gtk resets the size hints
+     to its own defaults. */
+  xg_set_wm_size_hints (f, flags, user_position);
+#else /* not USE_GTK */
   XSizeHints size_hints;
 
 #ifdef USE_X_TOOLKIT
   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 */;
@@ -13971,6 +14318,7 @@
 #else
   XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
 #endif
+#endif /* not USE_GTK */
 }
 
 /* Used for IconicState or NormalState */
@@ -14804,6 +15152,28 @@
       x_initialized = 1;
     }
 
+#ifdef USE_GTK
+  {
+    int argc = 0;
+    char *argv[3];
+    char **argv2 = argv;
+    GdkAtom atom;
+
+    /* KOKO, must pass -display and such */
+    argv[0] = initial_argv[0];
+    argv[1] = argv[2] = 0;
+    argc = 1;
+
+    gtk_init (&argc, &argv2);
+
+    dpy = GDK_DISPLAY ();
+    /* NULL window -> events for all windows go to our function */
+    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+
+    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:
@@ -14844,6 +15214,7 @@
 #endif
   dpy = XOpenDisplay (SDATA (display_name));
 #endif /* not USE_X_TOOLKIT */
+#endif /* not USE_GTK*/
 
   /* Detect failure.  */
   if (dpy == 0)
@@ -15303,9 +15674,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.  */
@@ -15385,6 +15758,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
Index: src/xterm.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xterm.h,v
retrieving revision 1.136
diff -u -I*~ -r1.136 xterm.h
--- src/xterm.h	30 Aug 2002 12:05:31 -0000	1.136
+++ src/xterm.h	9 Dec 2002 04:46:00 -0000
@@ -35,6 +35,11 @@
 #include <X11/StringDefs.h>
 #endif
 
+#ifdef USE_GTK
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#endif
+
 /* The class of this X application.  */
 #define EMACS_CLASS "Emacs"
 \f
@@ -348,7 +353,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));
@@ -446,6 +451,21 @@
   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 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;
@@ -619,7 +639,7 @@
 enum
 {
   /* Values for focus_state, used as bit mask.
-     EXPLICIT means if we received a FocusIn for the frame and know it has
+     EXPLICIT means we received a FocusIn for the frame and know it has
      the focus.  IMPLICIT means we recevied an EnterNotify and the frame
      may have the focus if no window manager is running.
      FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
@@ -638,8 +658,22 @@
                                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)

[-- Attachment #5: Type: text/plain, Size: 45 bytes --]



Thanks,

-Miles
-- 
I'd rather be consing.

[-- Attachment #6: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09  5:14 ` Miles Bader
@ 2002-12-09 12:44   ` Jan D.
  2002-12-09 13:20     ` Miles Bader
  2002-12-09 13:23     ` Andreas Schwab
  0 siblings, 2 replies; 11+ messages in thread
From: Jan D. @ 2002-12-09 12:44 UTC (permalink / raw)
  Cc: emacs-devel

> 
>  (1) Some hunks didn't apply for some reason, though the failed hunks
>      _did_ apply when I tried in diff-mode, so perhaps there's a
>      character encoding issue.  I've appended a patch generated with
>      `cvs diff' that the patch program seems to be happy with.

I dont know why that happend, maybe a mailer issue.  Thanks for
the fixed patch.

>  (2) HAVE_GTK isn't defined in src/config.in, and I had problems getting
>      autoheader to do so (the autoheader invocation in the top-level
>      Makefile seems to not be correct, though maybe I screwed something
>      up).  I've also included this change in the patch at the end of
>      this message.

I don't understand why HAVE_GTK needs to be in config.in.  Can you
explain?

>  (3) The `xg_win_to_widget' function in gtkutil.c contained intermixed
>      declarations and statements, which is not legal C (I _think_ it's
>      legal in C99, but most people are using older compilers).

Spoiled by GCC 3 and years of C++.  I'll switch to GCC 2.95 for Emacs.

>  (4) It looks like the user has to give the `--with-gtk' option to
>      configure to enable GTK.  I think using `--with-x-toolkit=gtk'
>      would be more correct, at least from a user's perspective.

I just selected what other GTK programs seems to use.  In theory GTK
can run on other platforms than X (not this port though), But I can switch
(or have both?) if thats desired.

Thanks,

	Jan D.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 12:44   ` Jan D.
@ 2002-12-09 13:20     ` Miles Bader
  2002-12-09 14:42       ` Alan Shutko
  2002-12-09 16:21       ` Jan D.
  2002-12-09 13:23     ` Andreas Schwab
  1 sibling, 2 replies; 11+ messages in thread
From: Miles Bader @ 2002-12-09 13:20 UTC (permalink / raw)
  Cc: emacs-devel

On Mon, Dec 09, 2002 at 01:44:03PM +0100, Jan D. wrote:
> I don't understand why HAVE_GTK needs to be in config.in.  Can you
> explain?

Because autoconf will never insert a define itself (into config.h), it needs
a template to modify, which in the case of emacs is src/config.in.  Surely
you needed to do this yourself, to compile anything!

> Spoiled by GCC 3 and years of C++.  I'll switch to GCC 2.95 for Emacs.

I assume that gcc 3.x has an option to only accept older versions of C.

> >  (4) It looks like the user has to give the `--with-gtk' option to
> >      configure to enable GTK.  I think using `--with-x-toolkit=gtk'
> >      would be more correct, at least from a user's perspective.
> 
> I just selected what other GTK programs seems to use.  In theory GTK
> can run on other platforms than X (not this port though), But I can switch
> (or have both?) if thats desired.

Well, if it's some sort of standard, then I suppose you could support both.

--with-x-toolkit is better though, because it makes explicit the fact that
GTK and the other supported toolkits are mutually exclusive.  Perhaps the
programs you're thinking of can only use one GUI toolkit, which is enabled
using --with-gtk?

-Miles

-- 
`...the Soviet Union was sliding in to an economic collapse so comprehensive
 that in the end its factories produced not goods but bads: finished products
 less valuable than the raw materials they were made from.'  [The Economist]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 12:44   ` Jan D.
  2002-12-09 13:20     ` Miles Bader
@ 2002-12-09 13:23     ` Andreas Schwab
  2002-12-09 17:25       ` Jan D.
  1 sibling, 1 reply; 11+ messages in thread
From: Andreas Schwab @ 2002-12-09 13:23 UTC (permalink / raw)
  Cc: miles

"Jan D." <jan.h.d@swipnet.se> writes:

|> I don't understand why HAVE_GTK needs to be in config.in.  Can you
|> explain?

All AC_DEFINE'd symbols must be in config.in.  You should use the modern
form of AC_DEFINE, with the comment as the third parameter.  The file
src/config.in is supposed to be generated only by autoheader.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 13:20     ` Miles Bader
@ 2002-12-09 14:42       ` Alan Shutko
  2002-12-09 15:24         ` Miles Bader
                           ` (2 more replies)
  2002-12-09 16:21       ` Jan D.
  1 sibling, 3 replies; 11+ messages in thread
From: Alan Shutko @ 2002-12-09 14:42 UTC (permalink / raw)
  Cc: Jan D.

Miles Bader <miles@gnu.org> writes:

> --with-x-toolkit is better though, because it makes explicit the fact that
> GTK and the other supported toolkits are mutually exclusive.  Perhaps the
> programs you're thinking of can only use one GUI toolkit, which is enabled
> using --with-gtk?

One important thing about --with-gtk is that it's really
--with-gtk=/path, which allows you to specify which gtk to use.
(--with-gtk is a degenerate case which says use gtk wherever you can
find it.)

Maybe --with-gtk should continue to specify where to find gtk, and
--with-x-toolkit=gtk can turn on gtk?  But it seems annoying to have
to specify --with-x-toolkit=gtk if you're already specifying a gtk
path.

-- 
Alan Shutko <ats@acm.org> - In a variety of flavors!
Bunker of Boig. Prepare to be assumptiated, meathead!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 14:42       ` Alan Shutko
@ 2002-12-09 15:24         ` Miles Bader
  2002-12-09 16:27         ` Jan D.
  2002-12-10 21:30         ` Richard Stallman
  2 siblings, 0 replies; 11+ messages in thread
From: Miles Bader @ 2002-12-09 15:24 UTC (permalink / raw)
  Cc: Jan D.

On Mon, Dec 09, 2002 at 09:42:43AM -0500, Alan Shutko wrote:
> Maybe --with-gtk should continue to specify where to find gtk, and
> --with-x-toolkit=gtk can turn on gtk?  But it seems annoying to have
> to specify --with-x-toolkit=gtk if you're already specifying a gtk
> path.

I think that:

  * --with-gtk=<anything> should turn on GTK, even if --with-x-toolkit=gtk is
    not specified, and that specifying --with-gtk simultaneously with
    --with-x-toolkit=<anything-but-gtk> should be an error.

  * --with-x-toolkit=gtk should _also_ turn on GTK, even if --with-gtk is not
    specified.

That way users can use whichever method they find most natural.

-Miles
-- 
P.S.  All information contained in the above letter is false,
      for reasons of military security.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 13:20     ` Miles Bader
  2002-12-09 14:42       ` Alan Shutko
@ 2002-12-09 16:21       ` Jan D.
  1 sibling, 0 replies; 11+ messages in thread
From: Jan D. @ 2002-12-09 16:21 UTC (permalink / raw)
  Cc: emacs-devel

> 
> On Mon, Dec 09, 2002 at 01:44:03PM +0100, Jan D. wrote:
> > I don't understand why HAVE_GTK needs to be in config.in.  Can you
> > explain?
> 
> Because autoconf will never insert a define itself (into config.h), it needs
> a template to modify, which in the case of emacs is src/config.in.  Surely
> you needed to do this yourself, to compile anything!

I did edit config.in manually and then promptly forgot about it.
I didn't realize it was a generated file.


> > >  (4) It looks like the user has to give the `--with-gtk' option to
> > >      configure to enable GTK.  I think using `--with-x-toolkit=gtk'
> > >      would be more correct, at least from a user's perspective.
> > 
> > I just selected what other GTK programs seems to use.  In theory GTK
> > can run on other platforms than X (not this port though), But I can switch
> > (or have both?) if thats desired.
> 
> Well, if it's some sort of standard, then I suppose you could support both.
> 
> --with-x-toolkit is better though, because it makes explicit the fact that
> GTK and the other supported toolkits are mutually exclusive.  Perhaps the
> programs you're thinking of can only use one GUI toolkit, which is enabled
> using --with-gtk?

It may be so.  I can hardly call it standard, the only program I remember
right now is xscreensaver.  I'll change to --with-x-toolkit=gtk.

	Jan D.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 14:42       ` Alan Shutko
  2002-12-09 15:24         ` Miles Bader
@ 2002-12-09 16:27         ` Jan D.
  2002-12-10 21:30         ` Richard Stallman
  2 siblings, 0 replies; 11+ messages in thread
From: Jan D. @ 2002-12-09 16:27 UTC (permalink / raw)
  Cc: emacs-devel

> 
> Miles Bader <miles@gnu.org> writes:
> 
> > --with-x-toolkit is better though, because it makes explicit the fact that
> > GTK and the other supported toolkits are mutually exclusive.  Perhaps the
> > programs you're thinking of can only use one GUI toolkit, which is enabled
> > using --with-gtk?
> 
> One important thing about --with-gtk is that it's really
> --with-gtk=/path, which allows you to specify which gtk to use.
> (--with-gtk is a degenerate case which says use gtk wherever you can
> find it.)
> 
> Maybe --with-gtk should continue to specify where to find gtk, and
> --with-x-toolkit=gtk can turn on gtk?  But it seems annoying to have
> to specify --with-x-toolkit=gtk if you're already specifying a gtk
> path.

What I saw from gnome2 and the likes, the preferred thing seems to use
--with-pkg-config-prog=/path/to/pkg_config and get the paths from that
program.  I've added --with-pkg-config-prog in configure.in.
I think that --with-gtk=/path was the GTK 1.x way to specify paths.  GTK 2.x
requires pkg_config.  pkg_config is a bit easier to handle, as it
sets all the libraries, ldflags and cflags correct, as opposed to have
configure look for required libraries.

	Jan D.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 13:23     ` Andreas Schwab
@ 2002-12-09 17:25       ` Jan D.
  0 siblings, 0 replies; 11+ messages in thread
From: Jan D. @ 2002-12-09 17:25 UTC (permalink / raw)
  Cc: emacs-devel

> 
> All AC_DEFINE'd symbols must be in config.in.  You should use the modern
> form of AC_DEFINE, with the comment as the third parameter.  The file
> src/config.in is supposed to be generated only by autoheader.

Thanks for the explanation, I will fix this.

	Jan D.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: GTK patches part 1
  2002-12-09 14:42       ` Alan Shutko
  2002-12-09 15:24         ` Miles Bader
  2002-12-09 16:27         ` Jan D.
@ 2002-12-10 21:30         ` Richard Stallman
  2 siblings, 0 replies; 11+ messages in thread
From: Richard Stallman @ 2002-12-10 21:30 UTC (permalink / raw)
  Cc: miles

    One important thing about --with-gtk is that it's really
    --with-gtk=/path, which allows you to specify which gtk to use.
    (--with-gtk is a degenerate case which says use gtk wherever you can
    find it.)

A --with option is not supposed to take a directory name argumemt.
>From the GNU coding standards:

    Do not use a @samp{--with} option to specify the file name to use to
    find certain files.  That is outside the scope of what @samp{--with}
    options are for.

--with-gtk should mean "use GTK" and nothing else.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2002-12-10 21:30 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-08 19:19 GTK patches part 1 Jan D.
2002-12-09  5:14 ` Miles Bader
2002-12-09 12:44   ` Jan D.
2002-12-09 13:20     ` Miles Bader
2002-12-09 14:42       ` Alan Shutko
2002-12-09 15:24         ` Miles Bader
2002-12-09 16:27         ` Jan D.
2002-12-10 21:30         ` Richard Stallman
2002-12-09 16:21       ` Jan D.
2002-12-09 13:23     ` Andreas Schwab
2002-12-09 17:25       ` Jan D.

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.