Overflow, signedness and related fixes for images.
[bpt/emacs.git] / src / gtkutil.c
index 9d3bfe6..70bc18a 100644 (file)
@@ -42,6 +42,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_GTK3
 #include <gtk/gtkx.h>
+#include "emacsgtkfixed.h"
 #endif
 
 #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
@@ -88,12 +89,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
 
-/* Get the current value of the range, truncated to an integer.  */
-static int
-int_gtk_range_get_value (GtkRange *range)
-{
-  return gtk_range_get_value (range);
-}
+static void update_theme_scrollbar_width (void);
 
 \f
 /***********************************************************************
@@ -273,8 +269,8 @@ xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
                                       GDK_COLORSPACE_RGB,
                                       FALSE,
                                       xim->bitmap_unit,
-                                      (int) width,
-                                      (int) height,
+                                      width,
+                                      height,
                                       xim->bytes_per_line,
                                       NULL,
                                       NULL);
@@ -637,6 +633,9 @@ qttip_cb (GtkWidget  *widget,
   struct x_output *x = f->output_data.x;
   if (x->ttip_widget == NULL)
     {
+      GtkWidget *p;
+      GList *list, *iter;
+
       g_object_set (G_OBJECT (widget), "has-tooltip", FALSE, NULL);
       x->ttip_widget = tooltip;
       g_object_ref (G_OBJECT (tooltip));
@@ -644,6 +643,18 @@ qttip_cb (GtkWidget  *widget,
       g_object_ref (G_OBJECT (x->ttip_lbl));
       gtk_tooltip_set_custom (tooltip, x->ttip_lbl);
       x->ttip_window = GTK_WINDOW (gtk_widget_get_toplevel (x->ttip_lbl));
+
+      /* Change stupid Gtk+ default line wrapping.  */
+      p = gtk_widget_get_parent (x->ttip_lbl);
+      list = gtk_container_get_children (GTK_CONTAINER (p));
+      for (iter = list; iter; iter = g_list_next (iter))
+        {
+          GtkWidget *w = GTK_WIDGET (iter->data);
+          if (GTK_IS_LABEL (w))
+            gtk_label_set_line_wrap (GTK_LABEL (w), FALSE);
+        }
+      g_list_free (list);
+
       /* ATK needs an empty title for some reason.  */
       gtk_window_set_title (x->ttip_window, "");
       /* Realize so we can safely get screen later on.  */
@@ -663,8 +674,8 @@ qttip_cb (GtkWidget  *widget,
 
 int
 xg_prepare_tooltip (FRAME_PTR f,
-                      Lisp_Object string,
-                      int *width,
+                    Lisp_Object string,
+                    int *width,
                     int *height)
 {
 #ifndef USE_GTK_TOOLTIP
@@ -701,10 +712,9 @@ xg_prepare_tooltip (FRAME_PTR f,
                      (gtk_widget_get_display (GTK_WIDGET (x->ttip_window))),
                      "gdk-display-current-tooltip", NULL);
 
-  /* Put out dummy widget in so we can get callbacks for unrealize and
+  /* Put our dummy widget in so we can get callbacks for unrealize and
      hierarchy-changed.  */
   gtk_tooltip_set_custom (x->ttip_widget, widget);
-
   gtk_tooltip_set_text (x->ttip_widget, SSDATA (encoded_string));
   gtk_widget_get_preferred_size (GTK_WIDGET (x->ttip_window), NULL, &req);
   if (width) *width = req.width;
@@ -735,7 +745,7 @@ xg_show_tooltip (FRAME_PTR f, int root_x, int root_y)
 }
 
 /* Hide tooltip if shown.  Do nothing if not shown.
-   Return non-zero if tip was hidden, non-ero if not (i.e. not using
+   Return non-zero if tip was hidden, non-zero if not (i.e. not using
    system tooltips).  */
 
 int
@@ -1015,13 +1025,32 @@ style_changed_cb (GObject *go,
   struct input_event event;
   GdkDisplay *gdpy = (GdkDisplay *) user_data;
   const char *display_name = gdk_display_get_name (gdpy);
+  Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
 
   EVENT_INIT (event);
   event.kind = CONFIG_CHANGED_EVENT;
-  event.frame_or_window = make_string (display_name, strlen (display_name));
+  event.frame_or_window = build_string (display_name);
   /* Theme doesn't change often, so intern is called seldom.  */
   event.arg = intern ("theme-name");
   kbd_buffer_store_event (&event);
+
+  update_theme_scrollbar_width ();
+
+  /* If scroll bar width changed, we need set the new size on all frames
+     on this display.  */
+  if (dpy)
+    {
+      Lisp_Object rest, frame;
+      FOR_EACH_FRAME (rest, frame)
+        {
+          FRAME_PTR f = XFRAME (frame);
+          if (FRAME_X_DISPLAY (f) == dpy)
+            {
+              x_set_scroll_bar_default_width (f);
+              xg_frame_set_char_size (f, FRAME_COLS (f), FRAME_LINES (f));
+            }
+        }
+    }
 }
 
 /* Called when a delete-event occurs on WIDGET.  */
@@ -1069,7 +1098,12 @@ xg_create_frame_widgets (FRAME_PTR f)
 
   wvbox = gtk_vbox_new (FALSE, 0);
   whbox = gtk_hbox_new (FALSE, 0);
-  wfixed = gtk_fixed_new ();  /* Must have this to place scroll bars  */
+
+#ifdef HAVE_GTK3
+  wfixed = emacs_fixed_new (f);
+#else
+  wfixed = gtk_fixed_new ();
+#endif
 
   if (! wtop || ! wvbox || ! whbox || ! wfixed)
     {
@@ -1162,6 +1196,7 @@ xg_create_frame_widgets (FRAME_PTR f)
   gtk_widget_modify_style (wfixed, style);
 #else
   gtk_widget_set_can_focus (wfixed, TRUE);
+  gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE);
 #endif
 
 #ifdef USE_GTK_TOOLTIP
@@ -1303,7 +1338,7 @@ x_wm_set_size_hint (FRAME_PTR f, long int flags, int user_position)
     {
       BLOCK_INPUT;
       gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                                    NULL, &size_hints, hint_flags);
+                                     NULL, &size_hints, hint_flags);
       f->output_data.x->size_hints = size_hints;
       f->output_data.x->hint_flags = hint_flags;
       UNBLOCK_INPUT;
@@ -3250,6 +3285,10 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
 
 int xg_ignore_gtk_scrollbar;
 
+/* The width of the scroll bar for the current theme.  */
+
+static int scroll_bar_width_for_theme;
+
 /* Xlib's `Window' fits in 32 bits.  But we want to store pointers, and they
    may be larger than 32 bits.  Keep a mapping from integer index to widget
    pointers to get around the 32 bit limitation.  */
@@ -3326,6 +3365,34 @@ xg_get_widget_from_map (int idx)
   return 0;
 }
 
+static void
+update_theme_scrollbar_width (void)
+{
+#ifdef HAVE_GTK3
+  GtkAdjustment *vadj;
+#else
+  GtkObject *vadj;
+#endif
+  GtkWidget *wscroll;
+  int w = 0, b = 0;
+
+  vadj = gtk_adjustment_new (XG_SB_MIN, XG_SB_MIN, XG_SB_MAX, 0.1, 0.1, 0.1);
+  wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj));
+  g_object_ref_sink (G_OBJECT (wscroll));
+  gtk_widget_style_get (wscroll, "slider-width", &w, "trough-border", &b, NULL);
+  gtk_widget_destroy (wscroll);
+  g_object_unref (G_OBJECT (wscroll));
+  w += 2*b;
+  if (w < 16) w = 16;
+  scroll_bar_width_for_theme = w;
+}
+
+int
+xg_get_default_scrollbar_width (void)
+{
+  return scroll_bar_width_for_theme;
+}
+
 /* Return the scrollbar id for X Window WID on display DPY.
    Return -1 if WID not in id_to_widget.  */
 
@@ -3354,7 +3421,7 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid)
 static void
 xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
 {
-  int id = (int) (EMACS_INT) data; /* The EMACS_INT cast avoids a warning. */
+  int id = (intptr_t) data;
   xg_remove_widget_from_map (id);
 }
 
@@ -3375,7 +3442,7 @@ xg_create_scroll_bar (FRAME_PTR f,
 {
   GtkWidget *wscroll;
   GtkWidget *webox;
-  int scroll_id;
+  intptr_t scroll_id;
 #ifdef HAVE_GTK3
   GtkAdjustment *vadj;
 #else
@@ -3397,11 +3464,10 @@ xg_create_scroll_bar (FRAME_PTR f,
 
   scroll_id = xg_store_widget_in_map (wscroll);
 
-  /* The EMACS_INT cast avoids a warning. */
   g_signal_connect (G_OBJECT (wscroll),
                     "destroy",
                     G_CALLBACK (xg_gtk_scroll_destroy),
-                    (gpointer) (EMACS_INT) scroll_id);
+                    (gpointer) scroll_id);
   g_signal_connect (G_OBJECT (wscroll),
                     "change-value",
                     scroll_callback,
@@ -3510,6 +3576,15 @@ xg_update_scrollbar_pos (FRAME_PTR f,
     }
 }
 
+/* Get the current value of the range, truncated to an integer.  */
+
+static int
+int_gtk_range_get_value (GtkRange *range)
+{
+  return gtk_range_get_value (range);
+}
+
+
 /* Set the thumb size and position of scroll bar BAR.  We are currently
    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
 
@@ -3571,7 +3646,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
              gtk_adjustment_set_page_size (adj, size);
              gtk_adjustment_set_step_increment (adj, new_step);
              /* Assume a page increment is about 95% of the page size  */
-             gtk_adjustment_set_page_increment (adj,(int) (0.95*size));
+             gtk_adjustment_set_page_increment (adj, size - size / 20);
              changed = 1;
            }
        }
@@ -3663,8 +3738,8 @@ xg_tool_bar_button_cb (GtkWidget *widget,
                        GdkEventButton *event,
                        gpointer user_data)
 {
-  /* Casts to avoid warnings when gpointer is 64 bits and int is 32 bits */
-  gpointer ptr = (gpointer) (EMACS_INT) event->state;
+  intptr_t state = event->state;
+  gpointer ptr = (gpointer) state;
   g_object_set_data (G_OBJECT (widget), XG_TOOL_BAR_LAST_MODIFIER, ptr);
   return FALSE;
 }
@@ -3678,10 +3753,9 @@ xg_tool_bar_button_cb (GtkWidget *widget,
 static void
 xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
 {
-  /* The EMACS_INT cast avoids a warning. */
-  int idx = (int) (EMACS_INT) client_data;
+  intptr_t idx = (intptr_t) client_data;
   gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
-  int mod = (int) (EMACS_INT) gmod;
+  intptr_t mod = (intptr_t) gmod;
 
   FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
   Lisp_Object key, frame;
@@ -3960,8 +4034,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
                            GdkEventCrossing *event,
                            gpointer client_data)
 {
-  /* The EMACS_INT cast avoids a warning. */
-  int idx = (int) (EMACS_INT) client_data;
+  intptr_t idx = (intptr_t) client_data;
   FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
   Lisp_Object help, frame;
 
@@ -4155,14 +4228,16 @@ xg_make_tool_item (FRAME_PTR f,
 
   if (wimage)
     {
-      /* The EMACS_INT cast avoids a warning. */
+      intptr_t ii = i;
+      gpointer gi = (gpointer) ii;
+
       g_signal_connect (G_OBJECT (ti), "create-menu-proxy",
                         G_CALLBACK (xg_tool_bar_menu_proxy),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
 
       g_signal_connect (G_OBJECT (wb), "clicked",
                         G_CALLBACK (xg_tool_bar_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
 
       g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
 
@@ -4193,11 +4268,11 @@ xg_make_tool_item (FRAME_PTR f,
       g_signal_connect (G_OBJECT (weventbox),
                         "enter-notify-event",
                         G_CALLBACK (xg_tool_bar_help_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
       g_signal_connect (G_OBJECT (weventbox),
                         "leave-notify-event",
                         G_CALLBACK (xg_tool_bar_help_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
     }
 
   if (wbutton) *wbutton = wb;
@@ -4354,7 +4429,7 @@ update_frame_tool_bar (FRAME_PTR f)
       int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
       int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
       int idx;
-      int img_id;
+      ptrdiff_t img_id;
       int icon_size = 0;
       struct image *img = NULL;
       Lisp_Object image;
@@ -4662,6 +4737,7 @@ xg_initialize (void)
                                           (GTK_TYPE_MENU_SHELL));
   gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
                                 "cancel", 0);
+  update_theme_scrollbar_width ();
 }
 
 #endif /* USE_GTK */