emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

GTK patches part 1


From: Jan D.
Subject: GTK patches part 1
Date: Sun, 8 Dec 2002 20:19:56 +0100 (CET)

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 address@hidden@
  TOOLKIT_DEFINES = address@hidden@
  #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
+ address@hidden@
+ 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 */
  
  
  
--- 555,561 ----
      }
    return 0;
  }
! #endif /* USE_X_TOOLKIT || USE_GTK */
  
  
  
***************
*** 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 */
  
  
  /***********************************************************************
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
  }
  
! #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
  }
  
! #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 */
  
  /* 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 */
  
  /* 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;
  }
  
+ #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
    /* address@hidden 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"
  
***************
*** 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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]