03e46cd04176586570774e0882a51acf21efed51
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 75c60eb..d5b8e92 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -181,6 +181,7 @@ gtk_public_h_sources =          \
 	gtkenums.h		\
 	gtkeventbox.h		\
 	gtkexpander.h		\
+	gtkextendedlayout.h	\
 	gtkfilechooser.h        \
 	gtkfilechooserbutton.h  \
 	gtkfilechooserdialog.h  \
@@ -443,6 +444,7 @@ gtk_base_c_sources =            \
 	gtkentrycompletion.c	\
 	gtkeventbox.c		\
 	gtkexpander.c		\
+	gtkextendedlayout.c	\
 	gtkfilechooser.c	\
 	gtkfilechooserbutton.c	\
 	gtkfilechooserdefault.c	\
diff --git a/gtk/gtk.h b/gtk/gtk.h
index bdfaef9..c3051bd 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -81,6 +81,7 @@
 #include <gtk/gtkenums.h>
 #include <gtk/gtkeventbox.h>
 #include <gtk/gtkexpander.h>
+#include <gtk/gtkextendedlayout.h>
 #include <gtk/gtkfilesel.h>
 #include <gtk/gtkfixed.h>
 #include <gtk/gtkfilechooserbutton.h>
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index b049b29..cfb34a9 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -1320,6 +1320,20 @@ gtk_expander_set_use_underline
 #endif
 #endif
 
+#if IN_HEADER(__GTK_EXTENDED_LAYOUT_H__)
+#if IN_FILE(__GTK_EXTENDED_LAYOUT_C__)
+gtk_extended_layout_get_type G_GNUC_CONST
+gtk_extended_layout_get_features
+gtk_extended_layout_get_height_for_width
+gtk_extended_layout_get_width_for_height
+gtk_extended_layout_get_natural_size
+gtk_extended_layout_get_baselines
+gtk_extended_layout_set_baseline_offset
+gtk_extended_layout_get_single_baseline
+gtk_extended_layout_get_padding
+#endif
+#endif
+
 #if IN_HEADER(__GTK_FILE_CHOOSER_H__)
 #if IN_FILE(__GTK_FILE_CHOOSER_C__)
 gtk_file_chooser_add_filter
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 6fabacf..eeb3ac7 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -82,6 +82,15 @@ typedef enum
   GTK_BUTTONBOX_CENTER
 } GtkButtonBoxStyle;
 
+/* Baseline alignment policy */
+typedef enum
+{
+  GTK_BASELINE_NONE,
+  GTK_BASELINE_FIRST,
+  GTK_BASELINE_AVERAGE,
+  GTK_BASELINE_LAST
+} GtkBaselinePolicy;
+
 /* Curve types */
 typedef enum
 {
diff --git a/gtk/gtkextendedlayout.c b/gtk/gtkextendedlayout.c
new file mode 100644
index 0000000..3b43974
--- /dev/null
+++ b/gtk/gtkextendedlayout.c
@@ -0,0 +1,284 @@
+/* gtkextendedlayout.c
+ * Copyright (C) 2007 Mathias Hasselmann <mathias.hasselmann@gmx.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+#include "gtkextendedlayout.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+GType
+gtk_extended_layout_get_type (void)
+{
+  static GType extended_layout_type = 0;
+
+  if (G_UNLIKELY(!extended_layout_type))
+    extended_layout_type =
+      g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkExtendedLayout"),
+				     sizeof (GtkExtendedLayoutIface),
+				     NULL, 0, NULL, 0);
+
+  return extended_layout_type;
+}
+
+/**
+ * gtk_extended_layout_get_features:
+ * @layout: a #GtkExtendedLayout
+ *
+ * Query which extended layout features are supported.
+ *
+ * Returns: the #GtkExtendedLayoutFeatures supported
+ *
+ * Since: 2.14
+ **/
+GtkExtendedLayoutFeatures
+gtk_extended_layout_get_features (GtkExtendedLayout *layout)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_val_if_fail (GTK_IS_EXTENDED_LAYOUT (layout), 0);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_val_if_fail (iface->get_features, 0);
+  return iface->get_features(layout);
+}
+
+/**
+ * gtk_extended_layout_get_height_for_width:
+ * @layout: a #GtkExtendedLayout
+ * @width: the horizontal space available
+ *
+ * Query which vertical space this extended layout item would require,
+ * given the specified amount of horizontal space is made available.
+ *
+ * Returns: the height required when #width is assigned or -1 on error
+ *
+ * Since: 2.14
+ **/
+gint
+gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
+                                          gint               width)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_val_if_fail (GTK_IS_EXTENDED_LAYOUT (layout), -1);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_val_if_fail (iface->get_height_for_width, -1);
+  return iface->get_height_for_width(layout, width);
+}
+
+/**
+ * gtk_extended_layout_get_width_for_height:
+ * @layout: a #GtkExtendedLayout
+ * @height: the vertical space available
+ *
+ * Query which horizontal space this extended layout item would require,
+ * given the specified amount of vertical space is made available.
+ *
+ * Returns: the width required when #height is assigned or -1 on error
+ *
+ * Since: 2.14
+ **/
+gint
+gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
+                                          gint               height)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_val_if_fail (GTK_IS_EXTENDED_LAYOUT (layout), -1);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_val_if_fail (iface->get_width_for_height, -1);
+  return iface->get_width_for_height(layout, height);
+}
+
+/**
+ * gtk_extended_layout_get_natural_size:
+ * @layout: a #GtkExtendedLayout
+ * @requisition: a #GtkRequisition to be filled in
+ *
+ * Query the natural (preferred) size of the layout item.
+ * This natural size can be larger than the requested size,
+ * e.g. if the item contains optional or ellipized text.
+ *
+ * Since: 2.14
+ **/
+void
+gtk_extended_layout_get_natural_size (GtkExtendedLayout *layout,
+                                      GtkRequisition    *requisition)
+{
+  GtkWidgetAuxInfo *aux_info = NULL;
+  GtkExtendedLayoutIface *iface;
+
+  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+  g_return_if_fail (NULL != requisition);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_if_fail (iface->get_natural_size);
+  iface->get_natural_size(layout, requisition);
+
+/* XXX The following hack is needed to ensure natural_size >= requested_size
+ *     even if GtkWidget and GtkSizeGroup tweak a widget's size requisition. */
+/* FIXME Should I just use gtk_widget_size_request? This would be more reliable
+ *       but also would hide bugs in natural_size implementations. */
+
+  if (GTK_IS_WIDGET (layout))
+    aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), FALSE);
+
+  if (aux_info)
+    {
+      if (aux_info->width > 0)
+	requisition->width = MAX (requisition->width, aux_info->width);
+      if (aux_info && aux_info->height > 0)
+	requisition->height = MAX (requisition->height, aux_info->height);
+    }
+}
+
+/**
+ * gtk_extended_layout_get_baselines:
+ * @layout: a #GtkExtendedLayout
+ * @baselines: an array of baselines to be filled in
+ *
+ * Query the baselines of the layout item. Baselines are imaginary
+ * horizontal lines used to vertically align text and images.
+ *
+ * Returns: the number of entries in @baselines or -1 on error
+ *
+ * Since: 2.14
+ **/
+gint
+gtk_extended_layout_get_baselines (GtkExtendedLayout  *layout,
+                                   gint              **baselines)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_val_if_fail (GTK_IS_EXTENDED_LAYOUT (layout), -1);
+  g_return_val_if_fail (NULL != baselines, -1);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_val_if_fail (iface->get_baselines, -1);
+  return iface->get_baselines(layout, baselines);
+}
+
+/**
+ * gtk_extended_layout_set_baseline_offset:
+ * @layout: a #GtkExtendedLayout
+ * @offset: the offset to consider
+ *
+ * Informs the layout item about the offset it should apply to its baselines,
+ * to properly align them with all other baseline aware children of its parent.
+ *
+ * Since: 2.14
+ **/
+void
+gtk_extended_layout_set_baseline_offset (GtkExtendedLayout *layout,
+                                         gint               offset)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_if_fail (iface->set_baseline_offset);
+  iface->set_baseline_offset (layout, offset);
+}
+
+/**
+ * gtk_extended_layout_get_single_baseline:
+ * @layout: a #GtkExtendedLayout
+ * @policy: specifies the policy for choosing a baseline
+ *
+ * Queries a single baseline of the layout item.
+ *
+ * Since: 2.14
+ **/
+gint
+gtk_extended_layout_get_single_baseline (GtkExtendedLayout *layout,
+                                         GtkBaselinePolicy  policy)
+{
+  gint *baselines = NULL;
+  gint offset = -1;
+  gint count, i;
+
+  g_return_val_if_fail (GTK_BASELINE_NONE != policy, -1);
+
+  count = gtk_extended_layout_get_baselines (layout, &baselines);
+
+  if (count > 0)
+    {
+      switch (policy)
+        {
+          case GTK_BASELINE_NONE:
+            break;
+
+          case GTK_BASELINE_FIRST:
+            offset = baselines [0];
+            break;
+
+          case GTK_BASELINE_LAST:
+            offset = baselines [count - 1];
+            break;
+
+          case GTK_BASELINE_AVERAGE:
+            for (i = 0, offset = 0; i < count; ++i)
+              offset += baselines[i];
+
+            offset = (offset + count - 1) / count;
+            break;
+        }
+
+      g_free (baselines);
+    }
+
+  return offset;
+}
+
+/**
+ * gtk_extended_layout_get_padding:
+ * @layout: a #GtkExtendedLayout
+ * @padding: an #GtkBorder to be filled with the padding
+ *
+ * Query the padding this layout item puts arround its content.
+ *
+ * Since: 2.14
+ **/
+void
+gtk_extended_layout_get_padding (GtkExtendedLayout *layout,
+                                 GtkBorder         *padding)
+{
+  GtkExtendedLayoutIface *iface;
+
+  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+  g_return_if_fail (NULL != padding);
+
+  iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
+
+  g_return_if_fail (iface->get_padding);
+  iface->get_padding(layout, padding);
+}
+
+#define __GTK_EXTENDED_LAYOUT_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkextendedlayout.h b/gtk/gtkextendedlayout.h
new file mode 100644
index 0000000..d9c2b59
--- /dev/null
+++ b/gtk/gtkextendedlayout.h
@@ -0,0 +1,103 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2007 Mathias Hasselmann <mathias.hasselmann@gmx.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_EXTENDED_LAYOUT_H__
+#define __GTK_EXTENDED_LAYOUT_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_EXTENDED_LAYOUT            (gtk_extended_layout_get_type ())
+#define GTK_EXTENDED_LAYOUT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_EXTENDED_LAYOUT, GtkExtendedLayout))
+#define GTK_EXTENDED_LAYOUT_CLASS(klass)    ((GtkExtendedLayoutIface*)g_type_interface_peek ((klass), GTK_TYPE_EXTENDED_LAYOUT))
+#define GTK_IS_EXTENDED_LAYOUT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_EXTENDED_LAYOUT))
+#define GTK_EXTENDED_LAYOUT_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_EXTENDED_LAYOUT, GtkExtendedLayoutIface))
+
+#define GTK_EXTENDED_LAYOUT_HAS_WIDTH_FOR_HEIGHT(obj) \
+  (GTK_IS_EXTENDED_LAYOUT((obj)) && (GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT & \
+   gtk_extended_layout_get_features ((GtkExtendedLayout*)(obj))))
+#define GTK_EXTENDED_LAYOUT_HAS_HEIGHT_FOR_WIDTH(obj) \
+  (GTK_IS_EXTENDED_LAYOUT((obj)) && (GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH & \
+   gtk_extended_layout_get_features ((GtkExtendedLayout*)(obj))))
+#define GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE(obj) \
+  (GTK_IS_EXTENDED_LAYOUT((obj)) && (GTK_EXTENDED_LAYOUT_NATURAL_SIZE & \
+   gtk_extended_layout_get_features ((GtkExtendedLayout*)(obj))))
+#define GTK_EXTENDED_LAYOUT_HAS_BASELINES(obj) \
+  (GTK_IS_EXTENDED_LAYOUT((obj)) && (GTK_EXTENDED_LAYOUT_BASELINES & \
+   gtk_extended_layout_get_features ((GtkExtendedLayout*)(obj))))
+#define GTK_EXTENDED_LAYOUT_HAS_PADDING(obj) \
+  (GTK_IS_EXTENDED_LAYOUT((obj)) && (GTK_EXTENDED_LAYOUT_PADDING & \
+   gtk_extended_layout_get_features ((GtkExtendedLayout*)(obj))))
+
+typedef struct _GtkExtendedLayout           GtkExtendedLayout;
+typedef struct _GtkExtendedLayoutIface      GtkExtendedLayoutIface;
+
+/*< flags >*/
+typedef enum {
+  GTK_EXTENDED_LAYOUT_NONE             = 0,
+  GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT = 1 << 0,
+  GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH = 1 << 1,
+  GTK_EXTENDED_LAYOUT_NATURAL_SIZE     = 1 << 2,
+  GTK_EXTENDED_LAYOUT_BASELINES        = 1 << 3,
+  GTK_EXTENDED_LAYOUT_PADDING          = 1 << 4
+} GtkExtendedLayoutFeatures;
+
+struct _GtkExtendedLayoutIface
+{
+  GTypeInterface g_iface;
+
+  /* virtual table */
+
+  GtkExtendedLayoutFeatures (*get_features)         (GtkExtendedLayout  *layout);
+  gint                      (*get_height_for_width) (GtkExtendedLayout  *layout,
+                                                     gint                width);
+  gint                      (*get_width_for_height) (GtkExtendedLayout  *layout,
+                                                     gint                height);
+  void                      (*get_natural_size)     (GtkExtendedLayout  *layout,
+                                                     GtkRequisition     *requisition);
+  gint                      (*get_baselines)        (GtkExtendedLayout  *layout,
+                                                     gint              **baselines);
+  void                      (*set_baseline_offset)  (GtkExtendedLayout  *layout,
+                                                     gint                offset);
+  void                      (*get_padding)          (GtkExtendedLayout  *layout,
+                                                     GtkBorder          *padding);
+};
+
+
+GType                     gtk_extended_layout_get_type             (void) G_GNUC_CONST;
+GtkExtendedLayoutFeatures gtk_extended_layout_get_features         (GtkExtendedLayout  *layout);
+gint                      gtk_extended_layout_get_height_for_width (GtkExtendedLayout  *layout,
+                                                                    gint                width);
+gint                      gtk_extended_layout_get_width_for_height (GtkExtendedLayout  *layout,
+                                                                    gint                height);
+void                      gtk_extended_layout_get_natural_size     (GtkExtendedLayout  *layout,
+                                                                    GtkRequisition     *requisition);
+gint                      gtk_extended_layout_get_baselines        (GtkExtendedLayout  *layout,
+                                                                    gint              **baselines);
+void                      gtk_extended_layout_set_baseline_offset  (GtkExtendedLayout  *layout,
+                                                                    gint                offset);
+gint                      gtk_extended_layout_get_single_baseline  (GtkExtendedLayout  *layout,
+                                                                    GtkBaselinePolicy   policy);
+void                      gtk_extended_layout_get_padding          (GtkExtendedLayout  *layout,
+                                                                    GtkBorder          *padding);
+
+G_END_DECLS
+
+#endif /* __GTK_EXTENDED_LAYOUT_H__ */
