diff src/toolbar-gtk.c @ 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 fdefd0186b75
children 79c6ff3eef26
line wrap: on
line diff
--- 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