changeset 714:02339d4ebed4

[xemacs-hg @ 2001-12-23 20:28:19 by wmperry] 2001-12-22 William M. Perry <wmperry@gnu.org> * glyphs-gtk.c (gtk_xpm_instantiate): Don't bother doing the xpm-color-symbols checks, they are impossible to implement with GTK's XPM implementation. :( 2001-12-13 William M. Perry <wmperry@gnu.org> * select-gtk.c (gtk_own_selection): Update to follow the new method signature. Ignore owned_p as it appears to only be used for motif hacks. * redisplay-gtk.c (gtk_output_string): Fixed some warnings about signed/unsigned comparison. (gtk_output_gdk_pixmap): Remove clipping code as per change by andy@xemacs.org to the X11 code. (gtk_output_pixmap): Make this follow the output_pixmap method conventions and expose it. (gtk_output_horizontal_line): Renamed from output_hline, and expose it in our method structure. (gtk_ring_bell): Don't ring the bell if volume <= 0 * toolbar-gtk.c (gtk_output_toolbar_button): (gtk_output_frame_toolbars): (gtk_redraw_exposed_toolbars): (gtk_redraw_frame_toolbars): These are now just aliases for the common_XXX() routines in toolbar-common.c * toolbar-common.c: New common toolbar implementation. This file uses only the redisplay_XXX() functions and device methods to draw the toolbar, and so should be portable across all windowing systems (other than tty, and even then I imagine text-based stuff would work if you had a way to select it).
author wmperry
date Sun, 23 Dec 2001 20:28:22 +0000
parents c2c346111c9a
children add5a821a048
files src/ChangeLog src/console-gtk.h src/glyphs-gtk.c src/menubar-gtk.c src/redisplay-gtk.c src/toolbar-common.c src/toolbar-gtk.c
diffstat 7 files changed, 138 insertions(+), 871 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/ChangeLog	Sun Dec 23 20:28:22 2001 +0000
@@ -1,3 +1,37 @@
+2001-12-22  William M. Perry  <wmperry@gnu.org>
+
+	* glyphs-gtk.c (gtk_xpm_instantiate): Don't bother doing the
+	xpm-color-symbols checks, they are impossible to implement with
+	GTK's XPM implementation. :(
+
+2001-12-13  William M. Perry  <wmperry@gnu.org>
+
+	* select-gtk.c (gtk_own_selection): Update to follow the new
+	method signature.  Ignore owned_p as it appears to only be used
+	for motif hacks.
+
+	* redisplay-gtk.c (gtk_output_string): Fixed some warnings about
+	signed/unsigned comparison.
+	(gtk_output_gdk_pixmap): Remove clipping code as per change by
+	andy@xemacs.org to the X11 code.
+	(gtk_output_pixmap): Make this follow the output_pixmap method
+	conventions and expose it.
+	(gtk_output_horizontal_line): Renamed from output_hline, and
+	expose it in our method structure.
+	(gtk_ring_bell): Don't ring the bell if volume <= 0
+
+	* toolbar-gtk.c (gtk_output_toolbar_button): 
+	(gtk_output_frame_toolbars): 
+	(gtk_redraw_exposed_toolbars): 
+	(gtk_redraw_frame_toolbars): These are now just aliases for the
+	common_XXX() routines in toolbar-common.c
+
+	* toolbar-common.c: New common toolbar implementation.  This file
+	uses only the redisplay_XXX() functions and device methods to draw
+	the toolbar, and so should be portable across all windowing
+	systems (other than tty, and even then I imagine text-based stuff
+	would work if you had a way to select it).
+
 2001-12-11  Andy Piper  <andy@xemacs.org>
 
 	* dialog-msw.c (dialog_popped_down): new function. unset popup_up_p.
--- a/src/console-gtk.h	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/console-gtk.h	Sun Dec 23 20:28:22 2001 +0000
@@ -222,14 +222,10 @@
 		      int start_pixpos, int width, face_index findex,
 		      int cursor, int cursor_start, int cursor_width,
 		      int cursor_height);
-void gtk_output_gdk_pixmap (struct frame *f, struct Lisp_Image_Instance *p,
-			    int x, int y, int clip_x, int clip_y,
-			    int clip_width, int clip_height, int width,
-			    int height, int pixmap_offset,
-			    GdkColor *fg, GdkColor *bg,
-			    GdkGC *override_gc);
 void gtk_output_shadows (struct frame *f, int x, int y, int width,
 		       int height, int shadow_thickness);
+GdkGC *gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
+		   Lisp_Object bg_pmap, Lisp_Object lwidth);
 
 int gtk_initialize_frame_menubar (struct frame *f);
 void gtk_init_modifier_mapping (struct device *d);
--- a/src/glyphs-gtk.c	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/glyphs-gtk.c	Sun Dec 23 20:28:22 2001 +0000
@@ -1,4 +1,4 @@
-/* X-specific Lisp objects.
+/* GTK-specific Lisp objects.
    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
    Copyright (C) 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1995 Tinker Systems
@@ -1083,6 +1083,7 @@
 /**********************************************************************
  *                             XPM                                    *
  **********************************************************************/
+
 static void
 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
 {
@@ -1182,77 +1183,9 @@
     report_file_error ("Writing temp file", build_string (filename_out));
 }
 
-struct color_symbol
-{
-  char*		name;
-  GdkColor	color;
-};
-
-static struct color_symbol*
-extract_xpm_color_names (Lisp_Object device,
-			 Lisp_Object domain,
-			 Lisp_Object color_symbol_alist,
-			 int* nsymbols)
-{
-  /* This function can GC */
-  Lisp_Object rest;
-  Lisp_Object results = Qnil;
-  int i, j;
-  struct color_symbol *colortbl;
-  struct gcpro gcpro1, gcpro2;
-
-  GCPRO2 (results, device);
-
-  /* We built up results to be (("name" . #<color>) ...) so that if an
-     error happens we don't lose any malloc()ed data, or more importantly,
-     leave any pixels allocated in the server. */
-  i = 0;
-  LIST_LOOP (rest, color_symbol_alist)
-    {
-      Lisp_Object cons = XCAR (rest);
-      Lisp_Object name = XCAR (cons);
-      Lisp_Object value = XCDR (cons);
-      if (NILP (value))
-	continue;
-      if (STRINGP (value))
-	value =
-	  Fmake_color_instance
-	  (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
-      else
-        {
-          assert (COLOR_SPECIFIERP (value));
-          value = Fspecifier_instance (value, domain, Qnil, Qnil);
-        }
-
-      if (NILP (value))
-        continue;
-      results = noseeum_cons (noseeum_cons (name, value), results);
-      i++;
-    }
-  UNGCPRO;			/* no more evaluation */
-
-  *nsymbols=i;
-  if (i == 0) return 0;
-
-  colortbl = xnew_array_and_zero (struct color_symbol, i);
-
-  for (j=0; j<i; j++)
-    {
-      Lisp_Object cons = XCAR (results);
-      colortbl[j].color = 
-	* COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
-
-      colortbl[j].name = (char *) XSTRING_DATA (XCAR (cons));
-      free_cons (XCONS (cons));
-      cons = results;
-      results = XCDR (results);
-      free_cons (XCONS (cons));
-    }
-  return colortbl;
-}
-
 static void
-gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+gtk_xpm_instantiate (Lisp_Object image_instance,
+		     Lisp_Object instantiator,
 		     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
 		     int dest_mask, Lisp_Object domain)
 {
@@ -1267,9 +1200,7 @@
   GdkPixmap *pixmap;
   GdkPixmap *mask = 0;
   GdkWindow *window = 0;
-  int nsymbols = 0, i = 0;
-  struct color_symbol *color_symbols = NULL;
-  GdkColor *transparent_color = NULL;
+  int i = 0;
   Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
 							   Q_color_symbols);
   enum image_instance_type type;
@@ -1300,23 +1231,10 @@
 
   assert (!NILP (data));
 
-  /* Need to get the transparent color here */
-  color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, &nsymbols);
-  for (i = 0; i < nsymbols; i++)
-    {
-      if (!strcasecmp ("BgColor", color_symbols[i].name) ||
-	  !strcasecmp ("None", color_symbols[i].name))
-	{
-	  transparent_color = &color_symbols[i].color;
-	}
-    }
-
   write_lisp_string_to_temp_file (data, temp_file_name);
-  pixmap = gdk_pixmap_create_from_xpm (window, &mask, transparent_color, temp_file_name);
+  pixmap = gdk_pixmap_create_from_xpm (window, &mask, NULL, temp_file_name);
   unlink (temp_file_name);
 
-  if (color_symbols) xfree (color_symbols);
-
   if (!pixmap)
   {
     signal_image_error ("Error reading pixmap", data);
@@ -1383,6 +1301,7 @@
       abort ();
     }
 }
+
 #endif /* HAVE_XPM */
 
 
--- a/src/menubar-gtk.c	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/menubar-gtk.c	Sun Dec 23 20:28:22 2001 +0000
@@ -1216,11 +1216,21 @@
 gtk_popup_menu (Lisp_Object menu_desc, Lisp_Object event)
 {
   struct Lisp_Event *eev = NULL;
-  GtkWidget *widget = menu_descriptor_to_widget (menu_desc);
-  GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
-  gpointer id = gtk_object_get_data (GTK_OBJECT (widget), XEMACS_MENU_GUIID_TAG);
+  GtkWidget *widget = NULL;
+  GtkWidget *menu = NULL;
+  gpointer id = NULL;
 
+  /* Do basic error checking first... */
+  if (SYMBOLP (menu_desc))
+    menu_desc = Fsymbol_value (menu_desc);
+  CHECK_CONS (menu_desc);
+  CHECK_STRING (XCAR (menu_desc));
+
+  /* Now lets get down to business... */
+  widget = menu_descriptor_to_widget (menu_desc);
+  menu = GTK_MENU_ITEM (widget)->submenu;
   gtk_widget_set_name (widget, "XEmacsPopupMenu");
+  id = gtk_object_get_data (GTK_OBJECT (widget), XEMACS_MENU_GUIID_TAG);
 
   __activate_menu (GTK_MENU_ITEM (widget), id);
 
--- a/src/redisplay-gtk.c	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/redisplay-gtk.c	Sun Dec 23 20:28:22 2001 +0000
@@ -1,4 +1,4 @@
-/* X output and frame manipulation routines.
+/* GTK output and frame manipulation routines.
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1994 Lucid, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
@@ -55,18 +55,22 @@
 
 #define EOL_CURSOR_WIDTH	5
 
-static void gtk_output_pixmap (struct window *w, struct display_line *dl,
-			       Lisp_Object image_instance, int xpos,
-			       int xoffset,
-			       int start_pixpos, int width, face_index findex,
-			       int cursor_start, int cursor_width,
-			       int cursor_height);
+static void gtk_output_pixmap (struct window *w,
+			       Lisp_Object image_instance,
+			       struct display_box *db,
+			       struct display_glyph_area *dga,
+			       face_index findex,
+			       int cursor_start,
+			       int cursor_width,
+			       int cursor_height,
+			       int bgpixmap);
 static void gtk_output_vertical_divider (struct window *w, int clear);
 static void gtk_output_blank (struct window *w, struct display_line *dl,
 			      struct rune *rb, int start_pixpos,
 			      int cursor_start, int cursor_width);
-static void gtk_output_hline (struct window *w, struct display_line *dl,
-			      struct rune *rb);
+static void gtk_output_horizontal_line (struct window *w,
+					struct display_line *dl,
+					struct rune *rb);
 static void gtk_redraw_exposed_window (struct window *w, int x, int y,
 				       int width, int height);
 static void gtk_redraw_exposed_windows (Lisp_Object window, int x, int y,
@@ -399,7 +403,7 @@
                      We borrow the shadow_thickness_changed flag for
                      now. */
 		  w->shadow_thickness_changed = 1;
-		  gtk_output_hline (w, dl, rb);
+		  gtk_output_horizontal_line (w, dl, rb);
 		}
 
 	      elt++;
@@ -449,10 +453,9 @@
 
 		  case IMAGE_MONO_PIXMAP:
 		  case IMAGE_COLOR_PIXMAP:
-		    gtk_output_pixmap (w, dl, instance, xpos,
-				       rb->object.dglyph.xoffset, start_pixpos,
-				       rb->width, findex, cursor_start,
-				       cursor_width, cursor_height);
+		    redisplay_output_pixmap (w, instance, &dbox, &dga,
+					     findex,cursor_start,
+					     cursor_width, cursor_height, 0);
 		    break;
 
 		  case IMAGE_POINTER:
@@ -643,14 +646,14 @@
  Starting Y position of cursor is the top of the text line.
  The cursor is drawn sometimes whether or not CURSOR is set. ???
  ****************************************************************************/
-void
-gdk_draw_text_image (GdkDrawable *drawable,
-		     GdkFont     *font,
-		     GdkGC       *gc,
-		     gint         x,
-		     gint         y,
-		     const gchar *text,
-		     gint         text_length);
+static
+void gdk_draw_text_image (GdkDrawable *drawable,
+			  GdkFont     *font,
+			  GdkGC       *gc,
+			  gint         x,
+			  gint         y,
+			  const gchar *text,
+			  gint         text_length);
 
 void
 gtk_output_string (struct window *w, struct display_line *dl,
@@ -1045,10 +1048,10 @@
 		 gint         width,
 		 gint         height);
 
-void
+static void
 gtk_output_gdk_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x,
-		       int y, int clip_x, int clip_y, int clip_width,
-		       int clip_height, int width, int height, int pixmap_offset,
+		       int y, int xoffset, int yoffset,
+		       int width, int height, 
 		       GdkColor *fg, GdkColor *bg, GdkGC *override_gc)
 {
   struct device *d = XDEVICE (f->device);
@@ -1057,7 +1060,6 @@
   GdkGC *gc;
   GdkGCValues gcv;
   unsigned long pixmap_mask;
-  int need_clipping = (clip_x || clip_y);
 
   if (!override_gc)
     {
@@ -1071,8 +1073,8 @@
 	{
 	  gcv.function = GDK_COPY;
 	  gcv.clip_mask = IMAGE_INSTANCE_GTK_MASK (p);
-	  gcv.clip_x_origin = x;
-	  gcv.clip_y_origin = y - pixmap_offset;
+	  gcv.clip_x_origin = x - xoffset;
+	  gcv.clip_y_origin = y - yoffset;
 	  pixmap_mask |= (GDK_GC_FUNCTION | GDK_GC_CLIP_MASK | GDK_GC_CLIP_X_ORIGIN |
 			  GDK_GC_CLIP_Y_ORIGIN);
 	  /* Can't set a clip rectangle below because we already have a mask.
@@ -1080,8 +1082,9 @@
 	     everything outside the clip region.  Is it worth it?
 	     Is it possible to get an equivalent effect by changing the
 	     args to XCopyArea below rather than messing with a clip box?
-	     - dkindred@cs.cmu.edu */
-	  need_clipping = 0;
+	     - dkindred@cs.cmu.edu
+	     Yes. We don't clip at all now - andy@xemacs.org
+          */
 	}
 
       gc = gc_cache_lookup (DEVICE_GTK_GC_CACHE (d), &gcv, pixmap_mask);
@@ -1092,47 +1095,32 @@
       /* override_gc might have a mask already--we don't want to nuke it.
 	 Maybe we can insist that override_gc have no mask, or use
 	 one of the suggestions above. */
-      need_clipping = 0;
-    }
-
-  if (need_clipping)
-    {
-      GdkRectangle clip_box;
-
-      clip_box.x = clip_x;
-      clip_box.y = clip_y;
-      clip_box.width = clip_width;
-      clip_box.height = clip_height;
-
-      gdk_gc_set_clip_rectangle (gc, &clip_box);
-      gdk_gc_set_clip_origin (gc, x, y);
     }
 
   if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
     {
       gdk_draw_pixmap (GDK_DRAWABLE (x_win), gc,
 		       IMAGE_INSTANCE_GTK_PIXMAP (p),
-		       0, pixmap_offset, x, y, width, height);
+		       xoffset, yoffset, x, y, width, height);
     }
   else
     {
       our_draw_bitmap (GDK_DRAWABLE (x_win), gc,
 		       IMAGE_INSTANCE_GTK_PIXMAP (p),
-		       0, pixmap_offset, x, y, width, height);
+		       xoffset, yoffset, x, y, width, height);
     }
-
-  if (need_clipping)
-  {
-      gdk_gc_set_clip_rectangle (gc, NULL);
-      gdk_gc_set_clip_origin (gc, 0, 0);
-  }
 }
 
 static void
-gtk_output_pixmap (struct window *w, struct display_line *dl,
-		   Lisp_Object image_instance, int xpos, int xoffset,
-		   int start_pixpos, int width, face_index findex,
-		   int cursor_start, int cursor_width, int cursor_height)
+gtk_output_pixmap (struct window *w,
+		   Lisp_Object image_instance,
+		   struct display_box *db,
+		   struct display_glyph_area *dga,
+		   face_index findex,
+		   int cursor_start,
+		   int cursor_width,
+		   int cursor_height,
+		   int bg_pixmap)
 {
   struct frame *f = XFRAME (w->frame);
   struct device *d = XDEVICE (f->device);
@@ -1140,89 +1128,9 @@
   Lisp_Object window;
 
   GdkWindow *x_win = GET_GTK_WIDGET_WINDOW (FRAME_GTK_TEXT_WIDGET (f));
-  int lheight = dl->ascent + dl->descent - dl->clip;
-  int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight :
-		 IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
-  int pwidth = min (width + xoffset, (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p));
-  int clip_x, clip_y, clip_width, clip_height;
-
-  /* The pixmap_offset is used to center the pixmap on lines which are
-     shorter than it is.  This results in odd effects when scrolling
-     pixmaps off of the bottom.  Let's try not using it. */
-#if 0
-  int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2;
-#else
-  int pixmap_offset = 0;
-#endif
 
   XSETWINDOW (window, w);
 
-  if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset)
-    {
-      if (start_pixpos > xpos && start_pixpos > xpos + width)
-	return;
-
-      clip_x = xoffset;
-      clip_width = width;
-      if (start_pixpos > xpos)
-	{
-	  clip_x += (start_pixpos - xpos);
-	  clip_width -= (start_pixpos - xpos);
-	}
-    }
-  else
-    {
-      clip_x = 0;
-      clip_width = 0;
-    }
-
-  /* Place markers for possible future functionality (clipping the top
-     half instead of the bottom half; think pixel scrolling). */
-  clip_y = 0;
-  clip_height = pheight;
-
-  /* Clear the area the pixmap is going into.  The pixmap itself will
-     always take care of the full width.  We don't want to clear where
-     it is going to go in order to avoid flicker.  So, all we have to
-     take care of is any area above or below the pixmap. */
-  /* #### We take a shortcut for now.  We know that since we have
-     pixmap_offset hardwired to 0 that the pixmap is against the top
-     edge so all we have to worry about is below it. */
-  /* #### Unless the pixmap has a mask in which case we have to clear
-     the whole damn thing since we can't yet clear just the area not
-     included in the mask. */
-  if (((int) (dl->ypos - dl->ascent + pheight) <
-       (int) (dl->ypos + dl->descent - dl->clip))
-      || IMAGE_INSTANCE_GTK_MASK (p))
-    {
-      int clear_x, clear_y, clear_width, clear_height;
-
-      if (IMAGE_INSTANCE_GTK_MASK (p))
-	{
-	  clear_y = dl->ypos - dl->ascent;
-	  clear_height = lheight;
-	}
-      else
-	{
-	  clear_y = dl->ypos - dl->ascent + pheight;
-	  clear_height = lheight - pheight;
-	}
-
-      if (start_pixpos >= 0 && start_pixpos > xpos)
-	{
-	  clear_x = start_pixpos;
-	  clear_width = xpos + width - start_pixpos;
-	}
-      else
-	{
-	  clear_x = xpos;
-	  clear_width = width;
-	}
-
-      redisplay_clear_region (window, findex, clear_x, clear_y,
-			      clear_width, clear_height);
-    }
-
   /* Output the pixmap. */
   {
     Lisp_Object tmp_pixel;
@@ -1233,20 +1141,19 @@
     tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
     tmp_bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (tmp_pixel));
 
-    gtk_output_gdk_pixmap (f, p, xpos - xoffset, dl->ypos - dl->ascent, clip_x,
-			   clip_y, clip_width, clip_height,
-			   pwidth, pheight, pixmap_offset,
-			   tmp_fcolor, tmp_bcolor, 0);
+    gtk_output_gdk_pixmap (f, p, db->xpos, db->ypos,
+			   dga->xoffset, dga->yoffset,
+			   dga->width, dga->height,
+			   tmp_fcolor, tmp_bcolor, NULL);
   }
 
   /* Draw a cursor over top of the pixmap. */
-  if (cursor_width && cursor_height && (cursor_start >= xpos)
+  if (cursor_width && cursor_height && (cursor_start >= db->xpos)
       && !NILP (w->text_cursor_visible_p)
-      && (cursor_start < xpos + pwidth))
+      && (cursor_start < (db->xpos + dga->width)))
     {
       GdkGC *gc;
       int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d));
-      int y = dl->ypos - dl->ascent;
       struct face_cachel *cursor_cachel =
 	WINDOW_FACE_CACHEL (w,
 			    get_builtin_face_cache_index
@@ -1254,11 +1161,11 @@
 
       gc = gtk_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
 
-      if (cursor_width > xpos + pwidth - cursor_start)
-	cursor_width = xpos + pwidth - cursor_start;
+      if (cursor_width > db->xpos + dga->width - cursor_start)
+	cursor_width = db->xpos + dga->width - cursor_start;
 
       gdk_draw_rectangle (GDK_DRAWABLE (x_win), gc, focus ? TRUE : FALSE,
-			  cursor_start, y, cursor_width,
+			  cursor_start, db->ypos, cursor_width,
 			  cursor_height);
     }
 }
@@ -1426,12 +1333,14 @@
 }
 
 /*****************************************************************************
- gtk_output_hline
+ gtk_output_horizontal_line
 
  Output a horizontal line in the foreground of its face.
  ****************************************************************************/
 static void
-gtk_output_hline (struct window *w, struct display_line *dl, struct rune *rb)
+gtk_output_horizontal_line (struct window *w,
+			    struct display_line *dl,
+			    struct rune *rb)
 {
   struct frame *f = XFRAME (w->frame);
   struct device *d = XDEVICE (f->device);
@@ -1919,8 +1828,11 @@
 static void
 gtk_ring_bell (struct device *d, int volume, int pitch, int duration)
 {
-	/* Gdk does not allow us to control the duration / pitch / volume */
-	gdk_beep ();
+  /* Gdk does not allow us to control the duration / pitch / volume */
+  if (volume > 0)
+    {
+      gdk_beep ();
+    }
 }
 
 
@@ -1944,7 +1856,7 @@
   CONSOLE_HAS_METHOD (gtk, ring_bell);
   CONSOLE_HAS_METHOD (gtk, bevel_area);
   CONSOLE_HAS_METHOD (gtk, output_string);
-  /*  CONSOLE_HAS_METHOD (gtk, output_pixmap); */
+  CONSOLE_HAS_METHOD (gtk, output_pixmap);
 }
 
 /* This makes me feel incredibly dirty... but there is no other way to
@@ -1954,14 +1866,14 @@
 
 #include <gdk/gdkx.h>
 
-void
-gdk_draw_text_image (GdkDrawable *drawable,
-		     GdkFont     *font,
-		     GdkGC       *gc,
-		     gint         x,
-		     gint         y,
-		     const gchar *text,
-		     gint         text_length)
+static
+void gdk_draw_text_image (GdkDrawable *drawable,
+			  GdkFont     *font,
+			  GdkGC       *gc,
+			  gint         x,
+			  gint         y,
+			  const gchar *text,
+			  gint         text_length)
 {
 #if !USE_X_SPECIFIC_DRAW_ROUTINES
   int width = gdk_text_measure (font, text, text_length);
--- a/src/toolbar-common.c	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/toolbar-common.c	Sun Dec 23 20:28:22 2001 +0000
@@ -703,4 +703,3 @@
     common_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
 				    FRAME_PIXHEIGHT (f));
 }
-
--- a/src/toolbar-gtk.c	Sun Dec 23 01:11:00 2001 +0000
+++ b/src/toolbar-gtk.c	Sun Dec 23 20:28:22 2001 +0000
@@ -1,4 +1,4 @@
-/* toolbar implementation -- X interface.
+/* toolbar implementation -- GTK interface.
    Copyright (C) 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1995, 1996 Ben Wing.
@@ -25,621 +25,18 @@
 
 #include <config.h>
 #include "lisp.h"
-
+#include "frame.h"
+#include "toolbar-common.h"
 #include "console-gtk.h"
-#include "glyphs-gtk.h"
-#include "objects-gtk.h"
-#include "gtk-xemacs.h"
-#include "gccache-gtk.h"
-
-#include "faces.h"
-#include "frame.h"
-#include "toolbar.h"
-#include "window.h"
-
-extern GdkGC *gtk_get_gc (struct device *d, Lisp_Object font, Lisp_Object fg, Lisp_Object bg,
-			  Lisp_Object bg_pmap, Lisp_Object lwidth);
-
-static GdkGC *get_toolbar_gc (struct frame *f)
-{
-  Lisp_Object fg, bg;
-  Lisp_Object frame;
-
-  XSETFRAME (frame, f);
-
-  fg = Fspecifier_instance (Fget (Vtoolbar_face, Qforeground, Qnil), frame, Qnil, Qnil);
-  bg = Fspecifier_instance (Fget (Vtoolbar_face, Qbackground, Qnil), frame, Qnil, Qnil);
-				   
-  /* Need to swap the foreground/background here or most themes look bug ugly */
-  return (gtk_get_gc (XDEVICE (FRAME_DEVICE (f)), Qnil, bg, fg, Qnil, Qnil));
-}
-
-static void
-gtk_draw_blank_toolbar_button (struct frame *f, int x, int y, int width,
-			       int height, int threed, int border_width,
-			       int vertical)
-{
-  GtkXEmacs *ef = GTK_XEMACS (FRAME_GTK_TEXT_WIDGET (f));
-  int sx = x, sy = y, swidth = width, sheight = height;
-  GdkWindow *x_win = GTK_WIDGET (ef)->window;
-  GdkGC *background_gc = get_toolbar_gc (f);
-
-  if (vertical)
-    {
-      sx += border_width;
-      swidth -= 2 * border_width;
-    }
-  else
-    {
-      sy += border_width;
-      sheight -= 2 * border_width;
-    }
-
-  /* Blank the entire area. */
-  gdk_draw_rectangle (x_win, background_gc, TRUE, sx, sy, swidth, sheight);
-
-  /* Draw the outline. */
-  if (threed)
-    gtk_output_shadows (f, sx, sy, swidth, sheight, 2);
-
-  /* Do the border */
-  gdk_draw_rectangle (x_win, background_gc, TRUE, x, y,
-		      (vertical ? border_width : width),
-		      (vertical ? height : border_width));
-  gdk_draw_rectangle (x_win, background_gc, TRUE,
-		      (vertical ? sx + swidth : x),
-		      (vertical ? y : sy + sheight),
-		      (vertical ? border_width : width),
-		      (vertical ? height : border_width));
-}
-
-static void
-gtk_output_toolbar_button (struct frame *f, Lisp_Object button)
-{
-  int shadow_thickness = 2;
-  int x_adj, y_adj, width_adj, height_adj;
-  GdkWindow *x_win = FRAME_GTK_TEXT_WIDGET (f)->window;
-  GdkGC *background_gc = get_toolbar_gc (f);
-  Lisp_Object instance, frame, window, glyph;
-  struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
-  struct Lisp_Image_Instance *p;
-  struct window *w;
-  int vertical = tb->vertical;
-  int border_width = tb->border_width;
-
-  if (vertical)
-    {
-      x_adj = border_width;
-      width_adj = - 2 * border_width;
-      y_adj = 0;
-      height_adj = 0;
-    }
-  else
-    {
-      x_adj = 0;
-      width_adj = 0;
-      y_adj = border_width;
-      height_adj = - 2 * border_width;
-    }
-
-  XSETFRAME (frame, f);
-  window = FRAME_LAST_NONMINIBUF_WINDOW (f);
-  w = XWINDOW (window);
-
-  glyph = get_toolbar_button_glyph (w, tb);
-
-  if (tb->enabled)
-    {
-      if (tb->down)
-	{
-	  shadow_thickness = -2;
-	}
-      else
-	{
-	  shadow_thickness = 2;
-	}
-    }
-  else
-    {
-      shadow_thickness = 0;
-    }
-
-  background_gc = get_toolbar_gc (f);
-
-  /* Clear the entire area. */
-  gdk_draw_rectangle (x_win, background_gc, TRUE,
-		      tb->x + x_adj,
-		      tb->y + y_adj,
-		      tb->width + width_adj,
-		      tb->height + height_adj);
-
-  /* Draw the outline. */
-  if (shadow_thickness)
-    gtk_output_shadows (f, tb->x + x_adj, tb->y + y_adj,
-			tb->width + width_adj, tb->height + height_adj,
-			shadow_thickness);
-
-  /* Do the border. */
-  gdk_draw_rectangle (x_win, background_gc, TRUE, tb->x, tb->y,
-		      (vertical ? border_width : tb->width),
-		      (vertical ? tb->height : border_width));
-
-  gdk_draw_rectangle (x_win, background_gc, TRUE,
-		      (vertical ? tb->x + tb->width - border_width : tb->x),
-		      (vertical ? tb->y : tb->y + tb->height - border_width),
-		      (vertical ? border_width : tb->width),
-		      (vertical ? tb->height : border_width));
-
-  background_gc = get_toolbar_gc (f);
-
-  /* #### It is currently possible for users to trash us by directly
-     changing the toolbar glyphs.  Avoid crashing in that case. */
-  if (GLYPHP (glyph))
-    instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
-  else
-    instance = Qnil;
-
-  if (IMAGE_INSTANCEP (instance))
-    {
-      int width = tb->width + width_adj - shadow_thickness * 2;
-      int height = tb->height + height_adj - shadow_thickness * 2;
-      int x_offset = x_adj + shadow_thickness;
-      int y_offset = y_adj + shadow_thickness;
-
-      p = XIMAGE_INSTANCE (instance);
-
-      if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
-	{
-	  if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p))
-	    {
-	      x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p))
-			   / 2);
-	      width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
-	    }
-	  if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
-	    {
-	      y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
-			   / 2);
-	      height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
-	    }
-
-	  gtk_output_gdk_pixmap (f, XIMAGE_INSTANCE (instance), tb->x + x_offset,
-				 tb->y + y_offset, 0, 0, 0, 0, width, height,
-				 0, 0, 0, background_gc);
-	}
-      else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT)
-	{
-	  /* #### We need to make the face used configurable. */
-	  struct face_cachel *cachel =
-	    WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
-	  struct display_line dl;
-	  Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p);
-	  unsigned char charsets[NUM_LEADING_BYTES];
-	  Emchar_dynarr *buf;
-	  struct font_metric_info fm;
-
-	  /* This could be true if we were called via the Expose event
-             handler.  Mark the button as dirty and return
-             immediately. */
-	  if (f->window_face_cache_reset)
-	    {
-	      tb->dirty = 1;
-	      MARK_TOOLBAR_CHANGED;
-	      return;
-	    }
-	  buf = Dynarr_new (Emchar);
-	  convert_intbyte_string_into_emchar_dynarr
-	    (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
-	  find_charsets_in_emchar_string (charsets, Dynarr_atp (buf, 0),
-					  Dynarr_length (buf));
-	  ensure_face_cachel_complete (cachel, window, charsets);
-	  face_cachel_charset_font_metric_info (cachel, charsets, &fm);
-
-	  dl.ascent = fm.ascent;
-	  dl.descent = fm.descent;
-	  dl.ypos = tb->y + y_offset + fm.ascent;
-
-	  if (fm.ascent + fm.descent <= height)
-	    {
-	      dl.ypos += (height - fm.ascent - fm.descent) / 2;
-	      dl.clip = 0;
-	    }
-	  else
-	    {
-	      dl.clip = fm.ascent + fm.descent - height;
-	    }
-
-	  gtk_output_string (w, &dl, buf, tb->x + x_offset, 0, 0, width,
-			     DEFAULT_INDEX, 0, 0, 0, 0);
-	  Dynarr_free (buf);
-	}
-
-      /* We silently ignore the image if it isn't a pixmap or text. */
-    }
-
-  tb->dirty = 0;
-}
-
-static int
-gtk_get_button_size (struct frame *f, Lisp_Object window,
-		     struct toolbar_button *tb, int vert, int pos)
-{
-  int shadow_thickness = 2;
-  int size;
-
-  if (tb->blank)
-    {
-      if (!NILP (tb->down_glyph))
-	size = XINT (tb->down_glyph);
-      else
-	size = DEFAULT_TOOLBAR_BLANK_SIZE;
-    }
-  else
-    {
-      struct window *w = XWINDOW (window);
-      Lisp_Object glyph = get_toolbar_button_glyph (w, tb);
-
-      /* Unless, of course, the user has done something stupid like
-         change the glyph out from under us.  Use a blank placeholder
-         in that case. */
-      if (NILP (glyph))
-	return XINT (f->toolbar_size[pos]);
-
-      if (vert)
-	size = glyph_height (glyph, window);
-      else
-	size = glyph_width (glyph, window);
-    }
-
-  if (!size)
-    {
-      /* If the glyph doesn't have a size we'll insert a blank
-         placeholder instead. */
-      return XINT (f->toolbar_size[pos]);
-    }
-
-  size += shadow_thickness * 2;
-
-  return (size);
-}
 
-#define GTK_OUTPUT_BUTTONS_LOOP(left)					\
-  do {									\
-    while (!NILP (button))						\
-      {									\
-	struct toolbar_button *tb = XTOOLBAR_BUTTON (button);		\
-	int size, height, width;					\
-									\
-	if (left && tb->pushright)					\
-	  break;							\
-									\
-        size = gtk_get_button_size (f, window, tb, vert, pos);		\
-									\
-	if (vert)							\
-	  {								\
-	    width = bar_width;						\
-	    if (y + size > max_pixpos)					\
-	      height = max_pixpos - y;					\
-	    else							\
-	      height = size;						\
-	  }								\
-	else								\
-	  {								\
-	    if (x + size > max_pixpos)					\
-	      width = max_pixpos - x;					\
-	    else							\
-	      width = size;						\
-	    height = bar_height;					\
-	  }								\
-									\
-	if (tb->x != x							\
-	    || tb->y != y						\
-	    || tb->width != width					\
-	    || tb->height != height					\
-	    || tb->dirty)						\
-	  {								\
-	    if (width && height)					\
-	      {								\
-		tb->x = x;						\
-		tb->y = y;						\
-		tb->width = width;					\
-		tb->height = height;					\
-	        tb->border_width = border_width;			\
-	        tb->vertical = vert;					\
-									\
-                if (tb->blank || NILP (tb->up_glyph))			\
-		  {							\
-		    int threed = (EQ (Qt, tb->up_glyph) ? 1 : 0);	\
-		    gtk_draw_blank_toolbar_button (f, x, y, width,	\
-						 height, threed,	\
-						 border_width, vert);	\
-		  }							\
-	        else							\
-		  gtk_output_toolbar_button (f, button);		\
-	      }								\
-	  }								\
-									\
-	if (vert)							\
-	  y += height;							\
-	else								\
-	  x += width;							\
-									\
-	if ((vert && y == max_pixpos) || (!vert && x == max_pixpos))	\
-	  button = Qnil;						\
-	else								\
-	  button = tb->next;						\
-      }									\
-  } while (0)
-
-#define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag)			\
-  do {									\
-    switch (pos)							\
-      {									\
-      case TOP_TOOLBAR:							\
-	(frame)->top_toolbar_was_visible = flag;			\
-	break;								\
-      case BOTTOM_TOOLBAR:						\
-	(frame)->bottom_toolbar_was_visible = flag;			\
-	break;								\
-      case LEFT_TOOLBAR:						\
-	(frame)->left_toolbar_was_visible = flag;			\
-	break;								\
-      case RIGHT_TOOLBAR:						\
-	(frame)->right_toolbar_was_visible = flag;			\
-	break;								\
-      default:								\
-	abort ();							\
-      }									\
-  } while (0)
-
-static void
-gtk_output_toolbar (struct frame *f, enum toolbar_pos pos)
-{
-  int x, y, bar_width, bar_height, vert;
-  int max_pixpos, right_size, right_start, blank_size;
-  int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
-  Lisp_Object button, window;
-  GdkWindow *x_win = FRAME_GTK_TEXT_WIDGET (f)->window;
-  GdkGC *background_gc = get_toolbar_gc (f);
-
-  get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1);
-  window = FRAME_LAST_NONMINIBUF_WINDOW (f);
-
-  /* Do the border */
-  gdk_draw_rectangle (x_win, background_gc, TRUE, x, y,
-		      (vert ? bar_width : border_width),
-		      (vert ? border_width : bar_height));
-  gdk_draw_rectangle (x_win, background_gc, TRUE,
-		      (vert ? x : x + bar_width - border_width),
-		      (vert ? y + bar_height - border_width : y),
-		      (vert ? bar_width : border_width),
-		      (vert ? border_width : bar_height));
-
-  if (vert)
-    {
-      max_pixpos = y + bar_height - border_width;
-      y += border_width;
-    }
-  else
-    {
-      max_pixpos = x + bar_width - border_width;
-      x += border_width;
-    }
-
-  button = FRAME_TOOLBAR_BUTTONS (f, pos);
-  right_size = 0;
-
-  /* First loop over all of the buttons to determine how much room we
-     need for left hand and right hand buttons.  This loop will also
-     make sure that all instances are instantiated so when we actually
-     output them they will come up immediately. */
-  while (!NILP (button))
-    {
-      struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
-      int size = gtk_get_button_size (f, window, tb, vert, pos);
-
-      if (tb->pushright)
-	right_size += size;
-
-      button = tb->next;
-    }
-
-  button = FRAME_TOOLBAR_BUTTONS (f, pos);
-
-  /* Loop over the left buttons, updating and outputting them. */
-  GTK_OUTPUT_BUTTONS_LOOP (1);
-
-  /* Now determine where the right buttons start. */
-  right_start = max_pixpos - right_size;
-  if (right_start < (vert ? y : x))
-    right_start = (vert ? y : x);
-
-  /* Output the blank which goes from the end of the left buttons to
-     the start of the right. */
-  blank_size = right_start - (vert ? y : x);
-  if (blank_size)
-    {
-      int height, width;
-
-      if (vert)
-	{
-	  width = bar_width;
-	  height = blank_size;
-	}
-      else
-	{
-	  width = blank_size;
-	  height = bar_height;
-	}
-
-      /*
-       * Use a 3D pushright separator only if there isn't a toolbar
-       * border.  A flat separator meshes with the border and looks
-       * better.
-       */
-      gtk_draw_blank_toolbar_button (f, x, y, width, height, !border_width,
-				     border_width, vert);
-
-      if (vert)
-	y += height;
-      else
-	x += width;
-    }
-
-  /* Loop over the right buttons, updating and outputting them. */
-  GTK_OUTPUT_BUTTONS_LOOP (0);
-
-  if (!vert)
-    {
-      Lisp_Object frame;
-
-      XSETFRAME (frame, f);
-      redisplay_clear_region (frame,
-			      DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1,
-			      bar_height);
-    }
-
-  SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
-
-  gdk_flush ();
-}
-
-static void
-gtk_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change)
-{
-  Lisp_Object frame;
-  int x, y, width, height, vert;
-
-  get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1);
-  XSETFRAME (frame, f);
-
-  /* The thickness_change parameter is used by the toolbar resize routines
-     to clear any excess toolbar if the size shrinks. */
-  if (thickness_change < 0)
-    {
-      if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR)
-	{
-	  x = x + width + thickness_change;
-	  width = -thickness_change;
-	}
-      else
-	{
-	  y = y + height + thickness_change;
-	  height = -thickness_change;
-	}
-    }
-
-  SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
-
-  redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height);
-  gdk_flush ();
-}
-
-static void
-gtk_output_frame_toolbars (struct frame *f)
-{
-  assert (FRAME_GTK_P (f));
-
-  if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
-    gtk_output_toolbar (f, TOP_TOOLBAR);
-  else if (f->top_toolbar_was_visible)
-    gtk_clear_toolbar (f, TOP_TOOLBAR, 0);
-
-  if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
-    gtk_output_toolbar (f, BOTTOM_TOOLBAR);
-  else if (f->bottom_toolbar_was_visible)
-    gtk_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
-
-  if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
-    gtk_output_toolbar (f, LEFT_TOOLBAR);
-  else if (f->left_toolbar_was_visible)
-    gtk_clear_toolbar (f, LEFT_TOOLBAR, 0);
-
-  if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
-    gtk_output_toolbar (f, RIGHT_TOOLBAR);
-  else if (f->right_toolbar_was_visible)
-    gtk_clear_toolbar (f, RIGHT_TOOLBAR, 0);
-}
-
-static void
-gtk_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y,
-			    int width, int height)
-{
-  int bar_x, bar_y, bar_width, bar_height, vert;
-  Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
-
-  get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
-		      &vert, 1);
-
-  if (((y + height) < bar_y) || (y > (bar_y + bar_height)))
-    return;
-  if (((x + width) < bar_x) || (x > (bar_x + bar_width)))
-    return;
-
-  while (!NILP (button))
-    {
-      struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
-
-      if (vert)
-	{
-	  if (((tb->y + tb->height) > y) && (tb->y < (y + height)))
-	    tb->dirty = 1;
-
-	  /* If this is true we have gone past the exposed region. */
-	  if (tb->y > (y + height))
-	    break;
-	}
-      else
-	{
-	  if (((tb->x + tb->width) > x) && (tb->x < (x + width)))
-	    tb->dirty = 1;
-
-	  /* If this is true we have gone past the exposed region. */
-	  if (tb->x > (x + width))
-	    break;
-	}
-
-      button = tb->next;
-    }
-
-  /* Even if none of the buttons is in the area, the blank region at
-     the very least must be because the first thing we did is verify
-     that some portion of the toolbar is in the exposed region. */
-  gtk_output_toolbar (f, pos);
-}
-
-static void
-gtk_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
-			     int height)
-{
-  assert (FRAME_GTK_P (f));
-
-  if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
-    gtk_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height);
-
-  if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
-    gtk_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height);
-
-  if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
-    gtk_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height);
-
-  if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
-    gtk_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height);
-}
-
-static void
-gtk_redraw_frame_toolbars (struct frame *f)
-{
-  /* There are certain startup paths that lead to update_EmacsFrame in
-     faces.c being called before a new frame is fully initialized.  In
-     particular before we have actually mapped it.  That routine can
-     call this one.  So, we need to make sure that the frame is
-     actually ready before we try and draw all over it. */
-
-  if (GTK_WIDGET_REALIZED (FRAME_GTK_TEXT_WIDGET (f)))
-    gtk_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
-				 FRAME_PIXHEIGHT (f));
-}
+/* We should really create a 'common' console type and fill it with
+** all the shared code.  We would then just use
+** CONSOLE_INHERITS_METHOD(x,common,blah)
+*/
+#define gtk_output_frame_toolbars common_output_frame_toolbars
+#define gtk_output_toolbar_button common_output_toolbar_button
+#define gtk_redraw_exposed_toolbars common_redraw_exposed_toolbars
+#define gtk_redraw_frame_toolbars common_redraw_frame_toolbars
 
 
 static void