]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderertext.c
Change FSF Address
[~andy/gtk] / gtk / gtkcellrenderertext.c
1 /* gtkcellrenderertext.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gtkcellrenderertext.h"
21
22 #include <stdlib.h>
23
24 #include "gtkeditable.h"
25 #include "gtkentry.h"
26 #include "gtksizerequest.h"
27 #include "gtkmarshalers.h"
28 #include "gtkintl.h"
29 #include "gtkprivate.h"
30 #include "gtktreeprivate.h"
31 #include "a11y/gtktextcellaccessible.h"
32
33
34 /**
35  * SECTION:gtkcellrenderertext
36  * @Short_description: Renders text in a cell
37  * @Title: GtkCellRendererText
38  *
39  * A #GtkCellRendererText renders a given text in its cell, using the font, color and
40  * style information provided by its properties. The text will be ellipsized if it is
41  * too long and the #GtkCellRendererText:ellipsize property allows it.
42  *
43  * If the #GtkCellRenderer:mode is %GTK_CELL_RENDERER_MODE_EDITABLE,
44  * the #GtkCellRendererText allows to edit its text using an entry.
45  */
46
47
48 static void gtk_cell_renderer_text_finalize   (GObject                  *object);
49
50 static void gtk_cell_renderer_text_get_property  (GObject                  *object,
51                                                   guint                     param_id,
52                                                   GValue                   *value,
53                                                   GParamSpec               *pspec);
54 static void gtk_cell_renderer_text_set_property  (GObject                  *object,
55                                                   guint                     param_id,
56                                                   const GValue             *value,
57                                                   GParamSpec               *pspec);
58 static void gtk_cell_renderer_text_render     (GtkCellRenderer          *cell,
59                                                cairo_t                  *cr,
60                                                GtkWidget                *widget,
61                                                const GdkRectangle       *background_area,
62                                                const GdkRectangle       *cell_area,
63                                                GtkCellRendererState      flags);
64
65 static GtkCellEditable *gtk_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
66                                                               GdkEvent             *event,
67                                                               GtkWidget            *widget,
68                                                               const gchar          *path,
69                                                               const GdkRectangle   *background_area,
70                                                               const GdkRectangle   *cell_area,
71                                                               GtkCellRendererState  flags);
72
73 static void       gtk_cell_renderer_text_get_preferred_width            (GtkCellRenderer       *cell,
74                                                                          GtkWidget             *widget,
75                                                                          gint                  *minimal_size,
76                                                                          gint                  *natural_size);
77 static void       gtk_cell_renderer_text_get_preferred_height           (GtkCellRenderer       *cell,
78                                                                          GtkWidget             *widget,
79                                                                          gint                  *minimal_size,
80                                                                          gint                  *natural_size);
81 static void       gtk_cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer       *cell,
82                                                                          GtkWidget             *widget,
83                                                                          gint                   width,
84                                                                          gint                  *minimum_height,
85                                                                          gint                  *natural_height);
86 static void       gtk_cell_renderer_text_get_aligned_area               (GtkCellRenderer       *cell,
87                                                                          GtkWidget             *widget,
88                                                                          GtkCellRendererState   flags,
89                                                                          const GdkRectangle    *cell_area,
90                                                                          GdkRectangle          *aligned_area);
91
92
93
94 enum {
95   EDITED,
96   LAST_SIGNAL
97 };
98
99 enum {
100   PROP_0,
101
102   PROP_TEXT,
103   PROP_MARKUP,
104   PROP_ATTRIBUTES,
105   PROP_SINGLE_PARAGRAPH_MODE,
106   PROP_WIDTH_CHARS,
107   PROP_MAX_WIDTH_CHARS,
108   PROP_WRAP_WIDTH,
109   PROP_ALIGN,
110   
111   /* Style args */
112   PROP_BACKGROUND,
113   PROP_FOREGROUND,
114   PROP_BACKGROUND_GDK,
115   PROP_FOREGROUND_GDK,
116   PROP_BACKGROUND_RGBA,
117   PROP_FOREGROUND_RGBA,
118   PROP_FONT,
119   PROP_FONT_DESC,
120   PROP_FAMILY,
121   PROP_STYLE,
122   PROP_VARIANT,
123   PROP_WEIGHT,
124   PROP_STRETCH,
125   PROP_SIZE,
126   PROP_SIZE_POINTS,
127   PROP_SCALE,
128   PROP_EDITABLE,
129   PROP_STRIKETHROUGH,
130   PROP_UNDERLINE,
131   PROP_RISE,
132   PROP_LANGUAGE,
133   PROP_ELLIPSIZE,
134   PROP_WRAP_MODE,
135   
136   /* Whether-a-style-arg-is-set args */
137   PROP_BACKGROUND_SET,
138   PROP_FOREGROUND_SET,
139   PROP_FAMILY_SET,
140   PROP_STYLE_SET,
141   PROP_VARIANT_SET,
142   PROP_WEIGHT_SET,
143   PROP_STRETCH_SET,
144   PROP_SIZE_SET,
145   PROP_SCALE_SET,
146   PROP_EDITABLE_SET,
147   PROP_STRIKETHROUGH_SET,
148   PROP_UNDERLINE_SET,
149   PROP_RISE_SET,
150   PROP_LANGUAGE_SET,
151   PROP_ELLIPSIZE_SET,
152   PROP_ALIGN_SET
153 };
154
155 static guint text_cell_renderer_signals [LAST_SIGNAL];
156
157 #define GTK_CELL_RENDERER_TEXT_PATH "gtk-cell-renderer-text-path"
158
159 struct _GtkCellRendererTextPrivate
160 {
161   GtkWidget *entry;
162
163   PangoAttrList        *extra_attrs;
164   GdkRGBA               foreground;
165   GdkRGBA               background;
166   PangoAlignment        align;
167   PangoEllipsizeMode    ellipsize;
168   PangoFontDescription *font;
169   PangoLanguage        *language;
170   PangoUnderline        underline_style;
171   PangoWrapMode         wrap_mode;
172
173   gchar *text;
174
175   gdouble font_scale;
176
177   gint rise;
178   gint fixed_height_rows;
179   gint width_chars;
180   gint max_width_chars;
181   gint wrap_width;
182
183   guint in_entry_menu     : 1;
184   guint strikethrough     : 1;
185   guint editable          : 1;
186   guint scale_set         : 1;
187   guint foreground_set    : 1;
188   guint background_set    : 1;
189   guint underline_set     : 1;
190   guint rise_set          : 1;
191   guint strikethrough_set : 1;
192   guint editable_set      : 1;
193   guint calc_fixed_height : 1;
194   guint single_paragraph  : 1;
195   guint language_set      : 1;
196   guint markup_set        : 1;
197   guint ellipsize_set     : 1;
198   guint align_set         : 1;
199
200   gulong focus_out_id;
201   gulong populate_popup_id;
202   gulong entry_menu_popdown_timeout;
203 };
204
205 G_DEFINE_TYPE (GtkCellRendererText, gtk_cell_renderer_text, GTK_TYPE_CELL_RENDERER)
206
207 static void
208 gtk_cell_renderer_text_init (GtkCellRendererText *celltext)
209 {
210   GtkCellRendererTextPrivate *priv;
211   GtkCellRenderer *cell = GTK_CELL_RENDERER (celltext);
212
213   celltext->priv = G_TYPE_INSTANCE_GET_PRIVATE (celltext,
214                                                 GTK_TYPE_CELL_RENDERER_TEXT,
215                                                 GtkCellRendererTextPrivate);
216   priv = celltext->priv;
217
218   gtk_cell_renderer_set_alignment (cell, 0.0, 0.5);
219   gtk_cell_renderer_set_padding (cell, 2, 2);
220   priv->font_scale = 1.0;
221   priv->fixed_height_rows = -1;
222   priv->font = pango_font_description_new ();
223
224   priv->width_chars = -1;
225   priv->max_width_chars = -1;
226   priv->wrap_width = -1;
227   priv->wrap_mode = PANGO_WRAP_CHAR;
228   priv->align = PANGO_ALIGN_LEFT;
229   priv->align_set = FALSE;
230 }
231
232 static void
233 gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
234 {
235   GObjectClass *object_class = G_OBJECT_CLASS (class);
236   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
237
238   object_class->finalize = gtk_cell_renderer_text_finalize;
239   
240   object_class->get_property = gtk_cell_renderer_text_get_property;
241   object_class->set_property = gtk_cell_renderer_text_set_property;
242
243   cell_class->render = gtk_cell_renderer_text_render;
244   cell_class->start_editing = gtk_cell_renderer_text_start_editing;
245   cell_class->get_preferred_width = gtk_cell_renderer_text_get_preferred_width;
246   cell_class->get_preferred_height = gtk_cell_renderer_text_get_preferred_height;
247   cell_class->get_preferred_height_for_width = gtk_cell_renderer_text_get_preferred_height_for_width;
248   cell_class->get_aligned_area = gtk_cell_renderer_text_get_aligned_area;
249
250   g_object_class_install_property (object_class,
251                                    PROP_TEXT,
252                                    g_param_spec_string ("text",
253                                                         P_("Text"),
254                                                         P_("Text to render"),
255                                                         NULL,
256                                                         GTK_PARAM_READWRITE));
257   
258   g_object_class_install_property (object_class,
259                                    PROP_MARKUP,
260                                    g_param_spec_string ("markup",
261                                                         P_("Markup"),
262                                                         P_("Marked up text to render"),
263                                                         NULL,
264                                                         GTK_PARAM_WRITABLE));
265
266   g_object_class_install_property (object_class,
267                                    PROP_ATTRIBUTES,
268                                    g_param_spec_boxed ("attributes",
269                                                        P_("Attributes"),
270                                                        P_("A list of style attributes to apply to the text of the renderer"),
271                                                        PANGO_TYPE_ATTR_LIST,
272                                                        GTK_PARAM_READWRITE));
273
274   g_object_class_install_property (object_class,
275                                    PROP_SINGLE_PARAGRAPH_MODE,
276                                    g_param_spec_boolean ("single-paragraph-mode",
277                                                          P_("Single Paragraph Mode"),
278                                                          P_("Whether to keep all text in a single paragraph"),
279                                                          FALSE,
280                                                          GTK_PARAM_READWRITE));
281
282   
283   g_object_class_install_property (object_class,
284                                    PROP_BACKGROUND,
285                                    g_param_spec_string ("background",
286                                                         P_("Background color name"),
287                                                         P_("Background color as a string"),
288                                                         NULL,
289                                                         GTK_PARAM_WRITABLE));
290
291   /**
292    * GtkCellRendererText:background-gdk:
293    *
294    * Background color as a #GdkColor
295    *
296    * Deprecated: 3.4: Use #GtkCellRendererText:background-rgba instead.
297    */
298   g_object_class_install_property (object_class,
299                                    PROP_BACKGROUND_GDK,
300                                    g_param_spec_boxed ("background-gdk",
301                                                        P_("Background color"),
302                                                        P_("Background color as a GdkColor"),
303                                                        GDK_TYPE_COLOR,
304                                                        GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
305
306   /**
307    * GtkCellRendererText:background-rgba:
308    *
309    * Background color as a #GdkRGBA
310    *
311    * Since: 3.0
312    */
313   g_object_class_install_property (object_class,
314                                    PROP_BACKGROUND_RGBA,
315                                    g_param_spec_boxed ("background-rgba",
316                                                        P_("Background color as RGBA"),
317                                                        P_("Background color as a GdkRGBA"),
318                                                        GDK_TYPE_RGBA,
319                                                        GTK_PARAM_READWRITE));
320   g_object_class_install_property (object_class,
321                                    PROP_FOREGROUND,
322                                    g_param_spec_string ("foreground",
323                                                         P_("Foreground color name"),
324                                                         P_("Foreground color as a string"),
325                                                         NULL,
326                                                         GTK_PARAM_WRITABLE));
327
328   /**
329    * GtkCellRendererText:foreground-gdk:
330    *
331    * Foreground color as a #GdkColor
332    *
333    * Deprecated: 3.4: Use #GtkCellRendererText:foreground-rgba instead.
334    */
335   g_object_class_install_property (object_class,
336                                    PROP_FOREGROUND_GDK,
337                                    g_param_spec_boxed ("foreground-gdk",
338                                                        P_("Foreground color"),
339                                                        P_("Foreground color as a GdkColor"),
340                                                        GDK_TYPE_COLOR,
341                                                        GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
342
343   /**
344    * GtkCellRendererText:foreground-rgba:
345    *
346    * Foreground color as a #GdkRGBA
347    *
348    * Since: 3.0
349    */
350   g_object_class_install_property (object_class,
351                                    PROP_FOREGROUND_RGBA,
352                                    g_param_spec_boxed ("foreground-rgba",
353                                                        P_("Foreground color as RGBA"),
354                                                        P_("Foreground color as a GdkRGBA"),
355                                                        GDK_TYPE_RGBA,
356                                                        GTK_PARAM_READWRITE));
357
358
359   g_object_class_install_property (object_class,
360                                    PROP_EDITABLE,
361                                    g_param_spec_boolean ("editable",
362                                                          P_("Editable"),
363                                                          P_("Whether the text can be modified by the user"),
364                                                          FALSE,
365                                                          GTK_PARAM_READWRITE));
366
367   g_object_class_install_property (object_class,
368                                    PROP_FONT,
369                                    g_param_spec_string ("font",
370                                                         P_("Font"),
371                                                         P_("Font description as a string, e.g. \"Sans Italic 12\""),
372                                                         NULL,
373                                                         GTK_PARAM_READWRITE));
374
375   g_object_class_install_property (object_class,
376                                    PROP_FONT_DESC,
377                                    g_param_spec_boxed ("font-desc",
378                                                        P_("Font"),
379                                                        P_("Font description as a PangoFontDescription struct"),
380                                                        PANGO_TYPE_FONT_DESCRIPTION,
381                                                        GTK_PARAM_READWRITE));
382
383   
384   g_object_class_install_property (object_class,
385                                    PROP_FAMILY,
386                                    g_param_spec_string ("family",
387                                                         P_("Font family"),
388                                                         P_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
389                                                         NULL,
390                                                         GTK_PARAM_READWRITE));
391
392   g_object_class_install_property (object_class,
393                                    PROP_STYLE,
394                                    g_param_spec_enum ("style",
395                                                       P_("Font style"),
396                                                       P_("Font style"),
397                                                       PANGO_TYPE_STYLE,
398                                                       PANGO_STYLE_NORMAL,
399                                                       GTK_PARAM_READWRITE));
400
401   g_object_class_install_property (object_class,
402                                    PROP_VARIANT,
403                                    g_param_spec_enum ("variant",
404                                                      P_("Font variant"),
405                                                      P_("Font variant"),
406                                                       PANGO_TYPE_VARIANT,
407                                                       PANGO_VARIANT_NORMAL,
408                                                       GTK_PARAM_READWRITE));
409   
410   g_object_class_install_property (object_class,
411                                    PROP_WEIGHT,
412                                    g_param_spec_int ("weight",
413                                                      P_("Font weight"),
414                                                      P_("Font weight"),
415                                                      0,
416                                                      G_MAXINT,
417                                                      PANGO_WEIGHT_NORMAL,
418                                                      GTK_PARAM_READWRITE));
419
420    g_object_class_install_property (object_class,
421                                    PROP_STRETCH,
422                                    g_param_spec_enum ("stretch",
423                                                       P_("Font stretch"),
424                                                       P_("Font stretch"),
425                                                       PANGO_TYPE_STRETCH,
426                                                       PANGO_STRETCH_NORMAL,
427                                                       GTK_PARAM_READWRITE));
428   
429   g_object_class_install_property (object_class,
430                                    PROP_SIZE,
431                                    g_param_spec_int ("size",
432                                                      P_("Font size"),
433                                                      P_("Font size"),
434                                                      0,
435                                                      G_MAXINT,
436                                                      0,
437                                                      GTK_PARAM_READWRITE));
438
439   g_object_class_install_property (object_class,
440                                    PROP_SIZE_POINTS,
441                                    g_param_spec_double ("size-points",
442                                                         P_("Font points"),
443                                                         P_("Font size in points"),
444                                                         0.0,
445                                                         G_MAXDOUBLE,
446                                                         0.0,
447                                                         GTK_PARAM_READWRITE));  
448
449   g_object_class_install_property (object_class,
450                                    PROP_SCALE,
451                                    g_param_spec_double ("scale",
452                                                         P_("Font scale"),
453                                                         P_("Font scaling factor"),
454                                                         0.0,
455                                                         G_MAXDOUBLE,
456                                                         1.0,
457                                                         GTK_PARAM_READWRITE));
458   
459   g_object_class_install_property (object_class,
460                                    PROP_RISE,
461                                    g_param_spec_int ("rise",
462                                                      P_("Rise"),
463                                                      P_("Offset of text above the baseline "
464                                                         "(below the baseline if rise is negative)"),
465                                                      -G_MAXINT,
466                                                      G_MAXINT,
467                                                      0,
468                                                      GTK_PARAM_READWRITE));
469
470
471   g_object_class_install_property (object_class,
472                                    PROP_STRIKETHROUGH,
473                                    g_param_spec_boolean ("strikethrough",
474                                                          P_("Strikethrough"),
475                                                          P_("Whether to strike through the text"),
476                                                          FALSE,
477                                                          GTK_PARAM_READWRITE));
478   
479   g_object_class_install_property (object_class,
480                                    PROP_UNDERLINE,
481                                    g_param_spec_enum ("underline",
482                                                       P_("Underline"),
483                                                       P_("Style of underline for this text"),
484                                                       PANGO_TYPE_UNDERLINE,
485                                                       PANGO_UNDERLINE_NONE,
486                                                       GTK_PARAM_READWRITE));
487
488   g_object_class_install_property (object_class,
489                                    PROP_LANGUAGE,
490                                    g_param_spec_string ("language",
491                                                         P_("Language"),
492                                                         P_("The language this text is in, as an ISO code. "
493                                                            "Pango can use this as a hint when rendering the text. "
494                                                            "If you don't understand this parameter, you probably don't need it"),
495                                                         NULL,
496                                                         GTK_PARAM_READWRITE));
497
498
499   /**
500    * GtkCellRendererText:ellipsize:
501    *
502    * Specifies the preferred place to ellipsize the string, if the cell renderer 
503    * does not have enough room to display the entire string. Setting it to 
504    * %PANGO_ELLIPSIZE_NONE turns off ellipsizing. See the wrap-width property
505    * for another way of making the text fit into a given width.
506    *
507    * Since: 2.6
508    */
509   g_object_class_install_property (object_class,
510                                    PROP_ELLIPSIZE,
511                                    g_param_spec_enum ("ellipsize",
512                                                       P_("Ellipsize"),
513                                                       P_("The preferred place to ellipsize the string, "
514                                                          "if the cell renderer does not have enough room "
515                                                          "to display the entire string"),
516                                                       PANGO_TYPE_ELLIPSIZE_MODE,
517                                                       PANGO_ELLIPSIZE_NONE,
518                                                       GTK_PARAM_READWRITE));
519
520   /**
521    * GtkCellRendererText:width-chars:
522    * 
523    * The desired width of the cell, in characters. If this property is set to
524    * -1, the width will be calculated automatically, otherwise the cell will
525    * request either 3 characters or the property value, whichever is greater.
526    * 
527    * Since: 2.6
528    **/
529   g_object_class_install_property (object_class,
530                                    PROP_WIDTH_CHARS,
531                                    g_param_spec_int ("width-chars",
532                                                      P_("Width In Characters"),
533                                                      P_("The desired width of the label, in characters"),
534                                                      -1,
535                                                      G_MAXINT,
536                                                      -1,
537                                                      GTK_PARAM_READWRITE));
538   
539
540   /**
541    * GtkCellRendererText:max-width-chars:
542    * 
543    * The desired maximum width of the cell, in characters. If this property 
544    * is set to -1, the width will be calculated automatically.
545    *
546    * For cell renderers that ellipsize or wrap text; this property
547    * controls the maximum reported width of the cell. The
548    * cell should not receive any greater allocation unless it is
549    * set to expand in its #GtkCellLayout and all of the cell's siblings
550    * have received their natural width.
551    *
552    * Since: 3.0
553    **/
554   g_object_class_install_property (object_class,
555                                    PROP_MAX_WIDTH_CHARS,
556                                    g_param_spec_int ("max-width-chars",
557                                                      P_("Maximum Width In Characters"),
558                                                      P_("The maximum width of the cell, in characters"),
559                                                      -1,
560                                                      G_MAXINT,
561                                                      -1,
562                                                      GTK_PARAM_READWRITE));
563   
564   /**
565    * GtkCellRendererText:wrap-mode:
566    *
567    * Specifies how to break the string into multiple lines, if the cell 
568    * renderer does not have enough room to display the entire string. 
569    * This property has no effect unless the wrap-width property is set.
570    *
571    * Since: 2.8
572    */
573   g_object_class_install_property (object_class,
574                                    PROP_WRAP_MODE,
575                                    g_param_spec_enum ("wrap-mode",
576                                                       P_("Wrap mode"),
577                                                       P_("How to break the string into multiple lines, "
578                                                          "if the cell renderer does not have enough room "
579                                                          "to display the entire string"),
580                                                       PANGO_TYPE_WRAP_MODE,
581                                                       PANGO_WRAP_CHAR,
582                                                       GTK_PARAM_READWRITE));
583
584   /**
585    * GtkCellRendererText:wrap-width:
586    *
587    * Specifies the minimum width at which the text is wrapped. The wrap-mode property can 
588    * be used to influence at what character positions the line breaks can be placed.
589    * Setting wrap-width to -1 turns wrapping off.
590    *
591    * Since: 2.8
592    */
593   g_object_class_install_property (object_class,
594                                    PROP_WRAP_WIDTH,
595                                    g_param_spec_int ("wrap-width",
596                                                      P_("Wrap width"),
597                                                      P_("The width at which the text is wrapped"),
598                                                      -1,
599                                                      G_MAXINT,
600                                                      -1,
601                                                      GTK_PARAM_READWRITE));
602
603   /**
604    * GtkCellRendererText:alignment:
605    *
606    * Specifies how to align the lines of text with respect to each other. 
607    *
608    * Note that this property describes how to align the lines of text in 
609    * case there are several of them. The "xalign" property of #GtkCellRenderer, 
610    * on the other hand, sets the horizontal alignment of the whole text.
611    *
612    * Since: 2.10
613    */
614   g_object_class_install_property (object_class,
615                                    PROP_ALIGN,
616                                    g_param_spec_enum ("alignment",
617                                                       P_("Alignment"),
618                                                       P_("How to align the lines"),
619                                                       PANGO_TYPE_ALIGNMENT,
620                                                       PANGO_ALIGN_LEFT,
621                                                       GTK_PARAM_READWRITE));
622   
623
624
625   /* Style props are set or not */
626
627 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
628
629   ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
630                 P_("Background set"),
631                 P_("Whether this tag affects the background color"));
632
633   ADD_SET_PROP ("foreground-set", PROP_FOREGROUND_SET,
634                 P_("Foreground set"),
635                 P_("Whether this tag affects the foreground color"));
636   
637   ADD_SET_PROP ("editable-set", PROP_EDITABLE_SET,
638                 P_("Editability set"),
639                 P_("Whether this tag affects text editability"));
640
641   ADD_SET_PROP ("family-set", PROP_FAMILY_SET,
642                 P_("Font family set"),
643                 P_("Whether this tag affects the font family"));  
644
645   ADD_SET_PROP ("style-set", PROP_STYLE_SET,
646                 P_("Font style set"),
647                 P_("Whether this tag affects the font style"));
648
649   ADD_SET_PROP ("variant-set", PROP_VARIANT_SET,
650                 P_("Font variant set"),
651                 P_("Whether this tag affects the font variant"));
652
653   ADD_SET_PROP ("weight-set", PROP_WEIGHT_SET,
654                 P_("Font weight set"),
655                 P_("Whether this tag affects the font weight"));
656
657   ADD_SET_PROP ("stretch-set", PROP_STRETCH_SET,
658                 P_("Font stretch set"),
659                 P_("Whether this tag affects the font stretch"));
660
661   ADD_SET_PROP ("size-set", PROP_SIZE_SET,
662                 P_("Font size set"),
663                 P_("Whether this tag affects the font size"));
664
665   ADD_SET_PROP ("scale-set", PROP_SCALE_SET,
666                 P_("Font scale set"),
667                 P_("Whether this tag scales the font size by a factor"));
668   
669   ADD_SET_PROP ("rise-set", PROP_RISE_SET,
670                 P_("Rise set"),
671                 P_("Whether this tag affects the rise"));
672
673   ADD_SET_PROP ("strikethrough-set", PROP_STRIKETHROUGH_SET,
674                 P_("Strikethrough set"),
675                 P_("Whether this tag affects strikethrough"));
676
677   ADD_SET_PROP ("underline-set", PROP_UNDERLINE_SET,
678                 P_("Underline set"),
679                 P_("Whether this tag affects underlining"));
680
681   ADD_SET_PROP ("language-set", PROP_LANGUAGE_SET,
682                 P_("Language set"),
683                 P_("Whether this tag affects the language the text is rendered as"));
684
685   ADD_SET_PROP ("ellipsize-set", PROP_ELLIPSIZE_SET,
686                 P_("Ellipsize set"),
687                 P_("Whether this tag affects the ellipsize mode"));
688
689   ADD_SET_PROP ("align-set", PROP_ALIGN_SET,
690                 P_("Align set"),
691                 P_("Whether this tag affects the alignment mode"));
692
693   /**
694    * GtkCellRendererText::edited
695    * @renderer: the object which received the signal
696    * @path: the path identifying the edited cell
697    * @new_text: the new text
698    *
699    * This signal is emitted after @renderer has been edited.
700    *
701    * It is the responsibility of the application to update the model
702    * and store @new_text at the position indicated by @path.
703    */
704   text_cell_renderer_signals [EDITED] =
705     g_signal_new (I_("edited"),
706                   G_OBJECT_CLASS_TYPE (object_class),
707                   G_SIGNAL_RUN_LAST,
708                   G_STRUCT_OFFSET (GtkCellRendererTextClass, edited),
709                   NULL, NULL,
710                   _gtk_marshal_VOID__STRING_STRING,
711                   G_TYPE_NONE, 2,
712                   G_TYPE_STRING,
713                   G_TYPE_STRING);
714
715   g_type_class_add_private (object_class, sizeof (GtkCellRendererTextPrivate));
716
717   _gtk_cell_renderer_class_set_accessible_type (cell_class, GTK_TYPE_TEXT_CELL_ACCESSIBLE);
718 }
719
720 static void
721 gtk_cell_renderer_text_finalize (GObject *object)
722 {
723   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
724   GtkCellRendererTextPrivate *priv = celltext->priv;
725
726   pango_font_description_free (priv->font);
727
728   g_free (priv->text);
729
730   if (priv->extra_attrs)
731     pango_attr_list_unref (priv->extra_attrs);
732
733   if (priv->language)
734     g_object_unref (priv->language);
735
736   G_OBJECT_CLASS (gtk_cell_renderer_text_parent_class)->finalize (object);
737 }
738
739 static PangoFontMask
740 get_property_font_set_mask (guint prop_id)
741 {
742   switch (prop_id)
743     {
744     case PROP_FAMILY_SET:
745       return PANGO_FONT_MASK_FAMILY;
746     case PROP_STYLE_SET:
747       return PANGO_FONT_MASK_STYLE;
748     case PROP_VARIANT_SET:
749       return PANGO_FONT_MASK_VARIANT;
750     case PROP_WEIGHT_SET:
751       return PANGO_FONT_MASK_WEIGHT;
752     case PROP_STRETCH_SET:
753       return PANGO_FONT_MASK_STRETCH;
754     case PROP_SIZE_SET:
755       return PANGO_FONT_MASK_SIZE;
756     }
757
758   return 0;
759 }
760
761 static void
762 gtk_cell_renderer_text_get_property (GObject        *object,
763                                      guint           param_id,
764                                      GValue         *value,
765                                      GParamSpec     *pspec)
766 {
767   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
768   GtkCellRendererTextPrivate *priv = celltext->priv;
769
770   switch (param_id)
771     {
772     case PROP_TEXT:
773       g_value_set_string (value, priv->text);
774       break;
775
776     case PROP_ATTRIBUTES:
777       g_value_set_boxed (value, priv->extra_attrs);
778       break;
779
780     case PROP_SINGLE_PARAGRAPH_MODE:
781       g_value_set_boolean (value, priv->single_paragraph);
782       break;
783
784     case PROP_BACKGROUND_GDK:
785       {
786         GdkColor color;
787
788         color.red = (guint16) (priv->background.red * 65535);
789         color.green = (guint16) (priv->background.green * 65535);
790         color.blue = (guint16) (priv->background.blue * 65535);
791
792         g_value_set_boxed (value, &color);
793       }
794       break;
795
796     case PROP_FOREGROUND_GDK:
797       {
798         GdkColor color;
799
800         color.red = (guint16) (priv->foreground.red * 65535);
801         color.green = (guint16) (priv->foreground.green * 65535);
802         color.blue = (guint16) (priv->foreground.blue * 65535);
803
804         g_value_set_boxed (value, &color);
805       }
806       break;
807
808     case PROP_BACKGROUND_RGBA:
809       g_value_set_boxed (value, &priv->background);
810       break;
811
812     case PROP_FOREGROUND_RGBA:
813       g_value_set_boxed (value, &priv->foreground);
814       break;
815
816     case PROP_FONT:
817         g_value_take_string (value, pango_font_description_to_string (priv->font));
818       break;
819       
820     case PROP_FONT_DESC:
821       g_value_set_boxed (value, priv->font);
822       break;
823
824     case PROP_FAMILY:
825       g_value_set_string (value, pango_font_description_get_family (priv->font));
826       break;
827
828     case PROP_STYLE:
829       g_value_set_enum (value, pango_font_description_get_style (priv->font));
830       break;
831
832     case PROP_VARIANT:
833       g_value_set_enum (value, pango_font_description_get_variant (priv->font));
834       break;
835
836     case PROP_WEIGHT:
837       g_value_set_int (value, pango_font_description_get_weight (priv->font));
838       break;
839
840     case PROP_STRETCH:
841       g_value_set_enum (value, pango_font_description_get_stretch (priv->font));
842       break;
843
844     case PROP_SIZE:
845       g_value_set_int (value, pango_font_description_get_size (priv->font));
846       break;
847
848     case PROP_SIZE_POINTS:
849       g_value_set_double (value, ((double)pango_font_description_get_size (priv->font)) / (double)PANGO_SCALE);
850       break;
851
852     case PROP_SCALE:
853       g_value_set_double (value, priv->font_scale);
854       break;
855       
856     case PROP_EDITABLE:
857       g_value_set_boolean (value, priv->editable);
858       break;
859
860     case PROP_STRIKETHROUGH:
861       g_value_set_boolean (value, priv->strikethrough);
862       break;
863
864     case PROP_UNDERLINE:
865       g_value_set_enum (value, priv->underline_style);
866       break;
867
868     case PROP_RISE:
869       g_value_set_int (value, priv->rise);
870       break;  
871
872     case PROP_LANGUAGE:
873       g_value_set_static_string (value, pango_language_to_string (priv->language));
874       break;
875
876     case PROP_ELLIPSIZE:
877       g_value_set_enum (value, priv->ellipsize);
878       break;
879       
880     case PROP_WRAP_MODE:
881       g_value_set_enum (value, priv->wrap_mode);
882       break;
883
884     case PROP_WRAP_WIDTH:
885       g_value_set_int (value, priv->wrap_width);
886       break;
887       
888     case PROP_ALIGN:
889       g_value_set_enum (value, priv->align);
890       break;
891
892     case PROP_BACKGROUND_SET:
893       g_value_set_boolean (value, priv->background_set);
894       break;
895
896     case PROP_FOREGROUND_SET:
897       g_value_set_boolean (value, priv->foreground_set);
898       break;
899
900     case PROP_FAMILY_SET:
901     case PROP_STYLE_SET:
902     case PROP_VARIANT_SET:
903     case PROP_WEIGHT_SET:
904     case PROP_STRETCH_SET:
905     case PROP_SIZE_SET:
906       {
907         PangoFontMask mask = get_property_font_set_mask (param_id);
908         g_value_set_boolean (value, (pango_font_description_get_set_fields (priv->font) & mask) != 0);
909         
910         break;
911       }
912
913     case PROP_SCALE_SET:
914       g_value_set_boolean (value, priv->scale_set);
915       break;
916       
917     case PROP_EDITABLE_SET:
918       g_value_set_boolean (value, priv->editable_set);
919       break;
920
921     case PROP_STRIKETHROUGH_SET:
922       g_value_set_boolean (value, priv->strikethrough_set);
923       break;
924
925     case PROP_UNDERLINE_SET:
926       g_value_set_boolean (value, priv->underline_set);
927       break;
928
929     case  PROP_RISE_SET:
930       g_value_set_boolean (value, priv->rise_set);
931       break;
932
933     case PROP_LANGUAGE_SET:
934       g_value_set_boolean (value, priv->language_set);
935       break;
936
937     case PROP_ELLIPSIZE_SET:
938       g_value_set_boolean (value, priv->ellipsize_set);
939       break;
940
941     case PROP_ALIGN_SET:
942       g_value_set_boolean (value, priv->align_set);
943       break;
944       
945     case PROP_WIDTH_CHARS:
946       g_value_set_int (value, priv->width_chars);
947       break;  
948
949     case PROP_MAX_WIDTH_CHARS:
950       g_value_set_int (value, priv->max_width_chars);
951       break;  
952
953     case PROP_BACKGROUND:
954     case PROP_FOREGROUND:
955     case PROP_MARKUP:
956     default:
957       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
958       break;
959     }
960 }
961
962
963 static void
964 set_bg_color (GtkCellRendererText *celltext,
965               GdkRGBA             *rgba)
966 {
967   GtkCellRendererTextPrivate *priv = celltext->priv;
968
969   if (rgba)
970     {
971       if (!priv->background_set)
972         {
973           priv->background_set = TRUE;
974           g_object_notify (G_OBJECT (celltext), "background-set");
975         }
976
977       priv->background = *rgba;
978     }
979   else
980     {
981       if (priv->background_set)
982         {
983           priv->background_set = FALSE;
984           g_object_notify (G_OBJECT (celltext), "background-set");
985         }
986     }
987 }
988
989
990 static void
991 set_fg_color (GtkCellRendererText *celltext,
992               GdkRGBA             *rgba)
993 {
994   GtkCellRendererTextPrivate *priv = celltext->priv;
995
996   if (rgba)
997     {
998       if (!priv->foreground_set)
999         {
1000           priv->foreground_set = TRUE;
1001           g_object_notify (G_OBJECT (celltext), "foreground-set");
1002         }
1003
1004       priv->foreground = *rgba;
1005     }
1006   else
1007     {
1008       if (priv->foreground_set)
1009         {
1010           priv->foreground_set = FALSE;
1011           g_object_notify (G_OBJECT (celltext), "foreground-set");
1012         }
1013     }
1014 }
1015
1016 static PangoFontMask
1017 set_font_desc_fields (PangoFontDescription *desc,
1018                       PangoFontMask         to_set)
1019 {
1020   PangoFontMask changed_mask = 0;
1021   
1022   if (to_set & PANGO_FONT_MASK_FAMILY)
1023     {
1024       const char *family = pango_font_description_get_family (desc);
1025       if (!family)
1026         {
1027           family = "sans";
1028           changed_mask |= PANGO_FONT_MASK_FAMILY;
1029         }
1030
1031       pango_font_description_set_family (desc, family);
1032     }
1033   if (to_set & PANGO_FONT_MASK_STYLE)
1034     pango_font_description_set_style (desc, pango_font_description_get_style (desc));
1035   if (to_set & PANGO_FONT_MASK_VARIANT)
1036     pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
1037   if (to_set & PANGO_FONT_MASK_WEIGHT)
1038     pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
1039   if (to_set & PANGO_FONT_MASK_STRETCH)
1040     pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
1041   if (to_set & PANGO_FONT_MASK_SIZE)
1042     {
1043       gint size = pango_font_description_get_size (desc);
1044       if (size <= 0)
1045         {
1046           size = 10 * PANGO_SCALE;
1047           changed_mask |= PANGO_FONT_MASK_SIZE;
1048         }
1049       
1050       pango_font_description_set_size (desc, size);
1051     }
1052
1053   return changed_mask;
1054 }
1055
1056 static void
1057 notify_set_changed (GObject       *object,
1058                     PangoFontMask  changed_mask)
1059 {
1060   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1061     g_object_notify (object, "family-set");
1062   if (changed_mask & PANGO_FONT_MASK_STYLE)
1063     g_object_notify (object, "style-set");
1064   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1065     g_object_notify (object, "variant-set");
1066   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1067     g_object_notify (object, "weight-set");
1068   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1069     g_object_notify (object, "stretch-set");
1070   if (changed_mask & PANGO_FONT_MASK_SIZE)
1071     g_object_notify (object, "size-set");
1072 }
1073
1074 static void
1075 notify_fields_changed (GObject       *object,
1076                        PangoFontMask  changed_mask)
1077 {
1078   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1079     g_object_notify (object, "family");
1080   if (changed_mask & PANGO_FONT_MASK_STYLE)
1081     g_object_notify (object, "style");
1082   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1083     g_object_notify (object, "variant");
1084   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1085     g_object_notify (object, "weight");
1086   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1087     g_object_notify (object, "stretch");
1088   if (changed_mask & PANGO_FONT_MASK_SIZE)
1089     g_object_notify (object, "size");
1090 }
1091
1092 static void
1093 set_font_description (GtkCellRendererText  *celltext,
1094                       PangoFontDescription *font_desc)
1095 {
1096   GtkCellRendererTextPrivate *priv = celltext->priv;
1097   GObject *object = G_OBJECT (celltext);
1098   PangoFontDescription *new_font_desc;
1099   PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
1100   
1101   if (font_desc)
1102     new_font_desc = pango_font_description_copy (font_desc);
1103   else
1104     new_font_desc = pango_font_description_new ();
1105
1106   old_mask = pango_font_description_get_set_fields (priv->font);
1107   new_mask = pango_font_description_get_set_fields (new_font_desc);
1108
1109   changed_mask = old_mask | new_mask;
1110   set_changed_mask = old_mask ^ new_mask;
1111
1112   pango_font_description_free (priv->font);
1113   priv->font = new_font_desc;
1114   
1115   g_object_freeze_notify (object);
1116
1117   g_object_notify (object, "font-desc");
1118   g_object_notify (object, "font");
1119   
1120   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1121     g_object_notify (object, "family");
1122   if (changed_mask & PANGO_FONT_MASK_STYLE)
1123     g_object_notify (object, "style");
1124   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1125     g_object_notify (object, "variant");
1126   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1127     g_object_notify (object, "weight");
1128   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1129     g_object_notify (object, "stretch");
1130   if (changed_mask & PANGO_FONT_MASK_SIZE)
1131     {
1132       g_object_notify (object, "size");
1133       g_object_notify (object, "size-points");
1134     }
1135
1136   notify_set_changed (object, set_changed_mask);
1137   
1138   g_object_thaw_notify (object);
1139 }
1140
1141 static void
1142 gtk_cell_renderer_text_set_property (GObject      *object,
1143                                      guint         param_id,
1144                                      const GValue *value,
1145                                      GParamSpec   *pspec)
1146 {
1147   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
1148   GtkCellRendererTextPrivate *priv = celltext->priv;
1149
1150   switch (param_id)
1151     {
1152     case PROP_TEXT:
1153       g_free (priv->text);
1154
1155       if (priv->markup_set)
1156         {
1157           if (priv->extra_attrs)
1158             pango_attr_list_unref (priv->extra_attrs);
1159           priv->extra_attrs = NULL;
1160           priv->markup_set = FALSE;
1161         }
1162
1163       priv->text = g_value_dup_string (value);
1164       g_object_notify (object, "text");
1165       break;
1166
1167     case PROP_ATTRIBUTES:
1168       if (priv->extra_attrs)
1169         pango_attr_list_unref (priv->extra_attrs);
1170
1171       priv->extra_attrs = g_value_get_boxed (value);
1172       if (priv->extra_attrs)
1173         pango_attr_list_ref (priv->extra_attrs);
1174       break;
1175     case PROP_MARKUP:
1176       {
1177         const gchar *str;
1178         gchar *text = NULL;
1179         GError *error = NULL;
1180         PangoAttrList *attrs = NULL;
1181
1182         str = g_value_get_string (value);
1183         if (str && !pango_parse_markup (str,
1184                                         -1,
1185                                         0,
1186                                         &attrs,
1187                                         &text,
1188                                         NULL,
1189                                         &error))
1190           {
1191             g_warning ("Failed to set text from markup due to error parsing markup: %s",
1192                        error->message);
1193             g_error_free (error);
1194             return;
1195           }
1196
1197         g_free (priv->text);
1198
1199         if (priv->extra_attrs)
1200           pango_attr_list_unref (priv->extra_attrs);
1201
1202         priv->text = text;
1203         priv->extra_attrs = attrs;
1204         priv->markup_set = TRUE;
1205       }
1206       break;
1207
1208     case PROP_SINGLE_PARAGRAPH_MODE:
1209       priv->single_paragraph = g_value_get_boolean (value);
1210       break;
1211       
1212     case PROP_BACKGROUND:
1213       {
1214         GdkRGBA rgba;
1215
1216         if (!g_value_get_string (value))
1217           set_bg_color (celltext, NULL);       /* reset to background_set to FALSE */
1218         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1219           set_bg_color (celltext, &rgba);
1220         else
1221           g_warning ("Don't know color `%s'", g_value_get_string (value));
1222
1223         g_object_notify (object, "background-gdk");
1224       }
1225       break;
1226       
1227     case PROP_FOREGROUND:
1228       {
1229         GdkRGBA rgba;
1230
1231         if (!g_value_get_string (value))
1232           set_fg_color (celltext, NULL);       /* reset to foreground_set to FALSE */
1233         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1234           set_fg_color (celltext, &rgba);
1235         else
1236           g_warning ("Don't know color `%s'", g_value_get_string (value));
1237
1238         g_object_notify (object, "foreground-gdk");
1239       }
1240       break;
1241
1242     case PROP_BACKGROUND_GDK:
1243       {
1244         GdkColor *color;
1245
1246         color = g_value_get_boxed (value);
1247         if (color)
1248           {
1249             GdkRGBA rgba;
1250
1251             rgba.red = color->red / 65535.;
1252             rgba.green = color->green / 65535.;
1253             rgba.blue = color->blue / 65535.;
1254             rgba.alpha = 1;
1255
1256             set_bg_color (celltext, &rgba);
1257           }
1258         else
1259           {
1260             set_bg_color (celltext, NULL);
1261           }
1262       }
1263       break;
1264
1265     case PROP_FOREGROUND_GDK:
1266       {
1267         GdkColor *color;
1268
1269         color = g_value_get_boxed (value);
1270         if (color)
1271           {
1272             GdkRGBA rgba;
1273
1274             rgba.red = color->red / 65535.;
1275             rgba.green = color->green / 65535.;
1276             rgba.blue = color->blue / 65535.;
1277             rgba.alpha = 1;
1278
1279             set_fg_color (celltext, &rgba);
1280           }
1281         else
1282           {
1283             set_fg_color (celltext, NULL);
1284           }
1285       }
1286       break;
1287
1288     case PROP_BACKGROUND_RGBA:
1289       /* This notifies the GObject itself. */
1290       set_bg_color (celltext, g_value_get_boxed (value));
1291       break;
1292
1293     case PROP_FOREGROUND_RGBA:
1294       /* This notifies the GObject itself. */
1295       set_fg_color (celltext, g_value_get_boxed (value));
1296       break;
1297
1298     case PROP_FONT:
1299       {
1300         PangoFontDescription *font_desc = NULL;
1301         const gchar *name;
1302
1303         name = g_value_get_string (value);
1304
1305         if (name)
1306           font_desc = pango_font_description_from_string (name);
1307
1308         set_font_description (celltext, font_desc);
1309
1310         pango_font_description_free (font_desc);
1311         
1312         if (priv->fixed_height_rows != -1)
1313           priv->calc_fixed_height = TRUE;
1314       }
1315       break;
1316
1317     case PROP_FONT_DESC:
1318       set_font_description (celltext, g_value_get_boxed (value));
1319       
1320       if (priv->fixed_height_rows != -1)
1321         priv->calc_fixed_height = TRUE;
1322       break;
1323
1324     case PROP_FAMILY:
1325     case PROP_STYLE:
1326     case PROP_VARIANT:
1327     case PROP_WEIGHT:
1328     case PROP_STRETCH:
1329     case PROP_SIZE:
1330     case PROP_SIZE_POINTS:
1331       {
1332         PangoFontMask old_set_mask = pango_font_description_get_set_fields (priv->font);
1333         
1334         switch (param_id)
1335           {
1336           case PROP_FAMILY:
1337             pango_font_description_set_family (priv->font,
1338                                                g_value_get_string (value));
1339             break;
1340           case PROP_STYLE:
1341             pango_font_description_set_style (priv->font,
1342                                               g_value_get_enum (value));
1343             break;
1344           case PROP_VARIANT:
1345             pango_font_description_set_variant (priv->font,
1346                                                 g_value_get_enum (value));
1347             break;
1348           case PROP_WEIGHT:
1349             pango_font_description_set_weight (priv->font,
1350                                                g_value_get_int (value));
1351             break;
1352           case PROP_STRETCH:
1353             pango_font_description_set_stretch (priv->font,
1354                                                 g_value_get_enum (value));
1355             break;
1356           case PROP_SIZE:
1357             pango_font_description_set_size (priv->font,
1358                                              g_value_get_int (value));
1359             g_object_notify (object, "size-points");
1360             break;
1361           case PROP_SIZE_POINTS:
1362             pango_font_description_set_size (priv->font,
1363                                              g_value_get_double (value) * PANGO_SCALE);
1364             g_object_notify (object, "size");
1365             break;
1366           }
1367         
1368         if (priv->fixed_height_rows != -1)
1369           priv->calc_fixed_height = TRUE;
1370         
1371         notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (priv->font));
1372         g_object_notify (object, "font-desc");
1373         g_object_notify (object, "font");
1374
1375         break;
1376       }
1377       
1378     case PROP_SCALE:
1379       priv->font_scale = g_value_get_double (value);
1380       priv->scale_set = TRUE;
1381       if (priv->fixed_height_rows != -1)
1382         priv->calc_fixed_height = TRUE;
1383       g_object_notify (object, "scale-set");
1384       break;
1385       
1386     case PROP_EDITABLE:
1387       priv->editable = g_value_get_boolean (value);
1388       priv->editable_set = TRUE;
1389       if (priv->editable)
1390         g_object_set (celltext, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL);
1391       else
1392         g_object_set (celltext, "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
1393       g_object_notify (object, "editable-set");
1394       break;
1395
1396     case PROP_STRIKETHROUGH:
1397       priv->strikethrough = g_value_get_boolean (value);
1398       priv->strikethrough_set = TRUE;
1399       g_object_notify (object, "strikethrough-set");
1400       break;
1401
1402     case PROP_UNDERLINE:
1403       priv->underline_style = g_value_get_enum (value);
1404       priv->underline_set = TRUE;
1405       g_object_notify (object, "underline-set");
1406             
1407       break;
1408
1409     case PROP_RISE:
1410       priv->rise = g_value_get_int (value);
1411       priv->rise_set = TRUE;
1412       g_object_notify (object, "rise-set");
1413       if (priv->fixed_height_rows != -1)
1414         priv->calc_fixed_height = TRUE;
1415       break;  
1416
1417     case PROP_LANGUAGE:
1418       priv->language_set = TRUE;
1419       if (priv->language)
1420         g_object_unref (priv->language);
1421       priv->language = pango_language_from_string (g_value_get_string (value));
1422       g_object_notify (object, "language-set");
1423       break;
1424
1425     case PROP_ELLIPSIZE:
1426       priv->ellipsize = g_value_get_enum (value);
1427       priv->ellipsize_set = TRUE;
1428       g_object_notify (object, "ellipsize-set");
1429       break;
1430       
1431     case PROP_WRAP_MODE:
1432       priv->wrap_mode = g_value_get_enum (value);
1433       break;
1434       
1435     case PROP_WRAP_WIDTH:
1436       priv->wrap_width = g_value_get_int (value);
1437       break;
1438             
1439     case PROP_WIDTH_CHARS:
1440       priv->width_chars = g_value_get_int (value);
1441       break;  
1442
1443     case PROP_MAX_WIDTH_CHARS:
1444       priv->max_width_chars = g_value_get_int (value);
1445       break;  
1446
1447     case PROP_ALIGN:
1448       priv->align = g_value_get_enum (value);
1449       priv->align_set = TRUE;
1450       g_object_notify (object, "align-set");
1451       break;
1452
1453     case PROP_BACKGROUND_SET:
1454       priv->background_set = g_value_get_boolean (value);
1455       break;
1456
1457     case PROP_FOREGROUND_SET:
1458       priv->foreground_set = g_value_get_boolean (value);
1459       break;
1460
1461     case PROP_FAMILY_SET:
1462     case PROP_STYLE_SET:
1463     case PROP_VARIANT_SET:
1464     case PROP_WEIGHT_SET:
1465     case PROP_STRETCH_SET:
1466     case PROP_SIZE_SET:
1467       if (!g_value_get_boolean (value))
1468         {
1469           pango_font_description_unset_fields (priv->font,
1470                                                get_property_font_set_mask (param_id));
1471         }
1472       else
1473         {
1474           PangoFontMask changed_mask;
1475           
1476           changed_mask = set_font_desc_fields (priv->font,
1477                                                get_property_font_set_mask (param_id));
1478           notify_fields_changed (G_OBJECT (celltext), changed_mask);
1479         }
1480       break;
1481
1482     case PROP_SCALE_SET:
1483       priv->scale_set = g_value_get_boolean (value);
1484       break;
1485       
1486     case PROP_EDITABLE_SET:
1487       priv->editable_set = g_value_get_boolean (value);
1488       break;
1489
1490     case PROP_STRIKETHROUGH_SET:
1491       priv->strikethrough_set = g_value_get_boolean (value);
1492       break;
1493
1494     case PROP_UNDERLINE_SET:
1495       priv->underline_set = g_value_get_boolean (value);
1496       break;
1497
1498     case PROP_RISE_SET:
1499       priv->rise_set = g_value_get_boolean (value);
1500       break;
1501
1502     case PROP_LANGUAGE_SET:
1503       priv->language_set = g_value_get_boolean (value);
1504       break;
1505
1506     case PROP_ELLIPSIZE_SET:
1507       priv->ellipsize_set = g_value_get_boolean (value);
1508       break;
1509
1510     case PROP_ALIGN_SET:
1511       priv->align_set = g_value_get_boolean (value);
1512       break;
1513       
1514     default:
1515       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1516       break;
1517     }
1518 }
1519
1520 /**
1521  * gtk_cell_renderer_text_new:
1522  * 
1523  * Creates a new #GtkCellRendererText. Adjust how text is drawn using
1524  * object properties. Object properties can be
1525  * set globally (with g_object_set()). Also, with #GtkTreeViewColumn,
1526  * you can bind a property to a value in a #GtkTreeModel. For example,
1527  * you can bind the "text" property on the cell renderer to a string
1528  * value in the model, thus rendering a different string in each row
1529  * of the #GtkTreeView
1530  * 
1531  * Return value: the new cell renderer
1532  **/
1533 GtkCellRenderer *
1534 gtk_cell_renderer_text_new (void)
1535 {
1536   return g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, NULL);
1537 }
1538
1539 static void
1540 add_attr (PangoAttrList  *attr_list,
1541           PangoAttribute *attr)
1542 {
1543   attr->start_index = 0;
1544   attr->end_index = G_MAXINT;
1545   
1546   pango_attr_list_insert (attr_list, attr);
1547 }
1548
1549 static PangoLayout*
1550 get_layout (GtkCellRendererText *celltext,
1551             GtkWidget           *widget,
1552             const GdkRectangle  *cell_area,
1553             GtkCellRendererState flags)
1554 {
1555   GtkCellRendererTextPrivate *priv = celltext->priv;
1556   PangoAttrList *attr_list;
1557   PangoLayout *layout;
1558   PangoUnderline uline;
1559   gint xpad;
1560
1561   layout = gtk_widget_create_pango_layout (widget, priv->text);
1562
1563   gtk_cell_renderer_get_padding (GTK_CELL_RENDERER (celltext), &xpad, NULL);
1564
1565   if (priv->extra_attrs)
1566     attr_list = pango_attr_list_copy (priv->extra_attrs);
1567   else
1568     attr_list = pango_attr_list_new ();
1569
1570   pango_layout_set_single_paragraph_mode (layout, priv->single_paragraph);
1571
1572   if (cell_area)
1573     {
1574       /* Add options that affect appearance but not size */
1575       
1576       /* note that background doesn't go here, since it affects
1577        * background_area not the PangoLayout area
1578        */
1579       
1580       if (priv->foreground_set
1581           && (flags & GTK_CELL_RENDERER_SELECTED) == 0)
1582         {
1583           PangoColor color;
1584
1585           color.red = (guint16) (priv->foreground.red * 65535);
1586           color.green = (guint16) (priv->foreground.green * 65535);
1587           color.blue = (guint16) (priv->foreground.blue * 65535);
1588
1589           add_attr (attr_list,
1590                     pango_attr_foreground_new (color.red, color.green, color.blue));
1591         }
1592
1593       if (priv->strikethrough_set)
1594         add_attr (attr_list,
1595                   pango_attr_strikethrough_new (priv->strikethrough));
1596     }
1597
1598   add_attr (attr_list, pango_attr_font_desc_new (priv->font));
1599
1600   if (priv->scale_set &&
1601       priv->font_scale != 1.0)
1602     add_attr (attr_list, pango_attr_scale_new (priv->font_scale));
1603   
1604   if (priv->underline_set)
1605     uline = priv->underline_style;
1606   else
1607     uline = PANGO_UNDERLINE_NONE;
1608
1609   if (priv->language_set)
1610     add_attr (attr_list, pango_attr_language_new (priv->language));
1611   
1612   if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
1613     {
1614       switch (uline)
1615         {
1616         case PANGO_UNDERLINE_NONE:
1617           uline = PANGO_UNDERLINE_SINGLE;
1618           break;
1619
1620         case PANGO_UNDERLINE_SINGLE:
1621           uline = PANGO_UNDERLINE_DOUBLE;
1622           break;
1623
1624         default:
1625           break;
1626         }
1627     }
1628
1629   if (uline != PANGO_UNDERLINE_NONE)
1630     add_attr (attr_list, pango_attr_underline_new (priv->underline_style));
1631
1632   if (priv->rise_set)
1633     add_attr (attr_list, pango_attr_rise_new (priv->rise));
1634
1635   /* Now apply the attributes as they will effect the outcome
1636    * of pango_layout_get_extents() */
1637   pango_layout_set_attributes (layout, attr_list);
1638   pango_attr_list_unref (attr_list);
1639
1640   if (priv->ellipsize_set)
1641     pango_layout_set_ellipsize (layout, priv->ellipsize);
1642   else
1643     pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE);
1644
1645   if (priv->wrap_width != -1)
1646     {
1647       PangoRectangle rect;
1648       gint           width, text_width;
1649
1650       pango_layout_get_extents (layout, NULL, &rect);
1651       text_width = rect.width;
1652
1653       if (cell_area)
1654         width = (cell_area->width - xpad * 2) * PANGO_SCALE;
1655       else
1656         width = priv->wrap_width * PANGO_SCALE;
1657
1658       width = MIN (width, text_width);
1659
1660       pango_layout_set_width (layout, width);
1661       pango_layout_set_wrap (layout, priv->wrap_mode);
1662     }
1663   else
1664     {
1665       pango_layout_set_width (layout, -1);
1666       pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
1667     }
1668
1669   if (priv->align_set)
1670     pango_layout_set_alignment (layout, priv->align);
1671   else
1672     {
1673       PangoAlignment align;
1674
1675       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1676         align = PANGO_ALIGN_RIGHT;
1677       else
1678         align = PANGO_ALIGN_LEFT;
1679
1680       pango_layout_set_alignment (layout, align);
1681     }
1682   
1683   return layout;
1684 }
1685
1686
1687 static void
1688 get_size (GtkCellRenderer    *cell,
1689           GtkWidget          *widget,
1690           const GdkRectangle *cell_area,
1691           PangoLayout        *layout,
1692           gint               *x_offset,
1693           gint               *y_offset,
1694           gint               *width,
1695           gint               *height)
1696 {
1697   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
1698   GtkCellRendererTextPrivate *priv = celltext->priv;
1699   PangoRectangle rect;
1700   gint xpad, ypad;
1701   gint cell_width, cell_height;
1702
1703   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
1704
1705   if (priv->calc_fixed_height)
1706     {
1707       GtkStyleContext *style_context;
1708       GtkStateFlags state;
1709       PangoContext *context;
1710       PangoFontMetrics *metrics;
1711       PangoFontDescription *font_desc;
1712       gint row_height;
1713
1714       style_context = gtk_widget_get_style_context (widget);
1715       state = gtk_widget_get_state_flags (widget);
1716
1717       font_desc = pango_font_description_copy_static (gtk_style_context_get_font (style_context, state));
1718       pango_font_description_merge_static (font_desc, priv->font, TRUE);
1719
1720       if (priv->scale_set)
1721         pango_font_description_set_size (font_desc,
1722                                          priv->font_scale * pango_font_description_get_size (font_desc));
1723
1724       context = gtk_widget_get_pango_context (widget);
1725
1726       metrics = pango_context_get_metrics (context,
1727                                            font_desc,
1728                                            pango_context_get_language (context));
1729       row_height = (pango_font_metrics_get_ascent (metrics) +
1730                     pango_font_metrics_get_descent (metrics));
1731       pango_font_metrics_unref (metrics);
1732
1733       pango_font_description_free (font_desc);
1734
1735       gtk_cell_renderer_get_fixed_size (cell, &cell_width, &cell_height);
1736
1737       gtk_cell_renderer_set_fixed_size (cell,
1738                                         cell_width, 2 * ypad +
1739                                         priv->fixed_height_rows * PANGO_PIXELS (row_height));
1740       
1741       if (height)
1742         {
1743           *height = cell_height;
1744           height = NULL;
1745         }
1746       priv->calc_fixed_height = FALSE;
1747       if (width == NULL)
1748         return;
1749     }
1750   
1751   if (layout)
1752     g_object_ref (layout);
1753   else
1754     layout = get_layout (celltext, widget, NULL, 0);
1755
1756   pango_layout_get_pixel_extents (layout, NULL, &rect);
1757
1758   if (cell_area)
1759     {
1760       gfloat xalign, yalign;
1761
1762       gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
1763
1764       rect.height = MIN (rect.height, cell_area->height - 2 * ypad);
1765       rect.width  = MIN (rect.width, cell_area->width - 2 * xpad);
1766
1767       if (x_offset)
1768         {
1769           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1770             *x_offset = (1.0 - xalign) * (cell_area->width - (rect.width + (2 * xpad)));
1771           else 
1772             *x_offset = xalign * (cell_area->width - (rect.width + (2 * xpad)));
1773
1774           if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->wrap_width != -1)
1775             *x_offset = MAX(*x_offset, 0);
1776         }
1777       if (y_offset)
1778         {
1779           *y_offset = yalign * (cell_area->height - (rect.height + (2 * ypad)));
1780           *y_offset = MAX (*y_offset, 0);
1781         }
1782     }
1783   else
1784     {
1785       if (x_offset) *x_offset = 0;
1786       if (y_offset) *y_offset = 0;
1787     }
1788
1789   if (height)
1790     *height = ypad * 2 + rect.height;
1791
1792   if (width)
1793     *width = xpad * 2 + rect.width;
1794
1795   g_object_unref (layout);
1796 }
1797
1798 static void
1799 gtk_cell_renderer_text_render (GtkCellRenderer      *cell,
1800                                cairo_t              *cr,
1801                                GtkWidget            *widget,
1802                                const GdkRectangle   *background_area,
1803                                const GdkRectangle   *cell_area,
1804                                GtkCellRendererState  flags)
1805
1806 {
1807   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
1808   GtkCellRendererTextPrivate *priv = celltext->priv;
1809   GtkStyleContext *context;
1810   PangoLayout *layout;
1811   gint x_offset = 0;
1812   gint y_offset = 0;
1813   gint xpad, ypad;
1814   PangoRectangle rect;
1815
1816   layout = get_layout (celltext, widget, cell_area, flags);
1817   get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, NULL, NULL);
1818   context = gtk_widget_get_style_context (widget);
1819
1820   if (priv->background_set && (flags & GTK_CELL_RENDERER_SELECTED) == 0)
1821     {
1822       gdk_cairo_rectangle (cr, background_area);
1823       gdk_cairo_set_source_rgba (cr, &priv->background);
1824       cairo_fill (cr);
1825     }
1826
1827   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
1828
1829   if (priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE)
1830     pango_layout_set_width (layout,
1831                             (cell_area->width - x_offset - 2 * xpad) * PANGO_SCALE);
1832   else if (priv->wrap_width == -1)
1833     pango_layout_set_width (layout, -1);
1834
1835   pango_layout_get_pixel_extents (layout, NULL, &rect);
1836   x_offset = x_offset - rect.x;
1837
1838   cairo_save (cr);
1839
1840   gdk_cairo_rectangle (cr, cell_area);
1841   cairo_clip (cr);
1842
1843   gtk_render_layout (context, cr,
1844                      cell_area->x + x_offset + xpad,
1845                      cell_area->y + y_offset + ypad,
1846                      layout);
1847
1848   cairo_restore (cr);
1849
1850   g_object_unref (layout);
1851 }
1852
1853 static void
1854 gtk_cell_renderer_text_editing_done (GtkCellEditable *entry,
1855                                      gpointer         data)
1856 {
1857   GtkCellRendererTextPrivate *priv;
1858   const gchar *path;
1859   const gchar *new_text;
1860   gboolean canceled;
1861
1862   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
1863
1864   priv->entry = NULL;
1865
1866   if (priv->focus_out_id > 0)
1867     {
1868       g_signal_handler_disconnect (entry, priv->focus_out_id);
1869       priv->focus_out_id = 0;
1870     }
1871
1872   if (priv->populate_popup_id > 0)
1873     {
1874       g_signal_handler_disconnect (entry, priv->populate_popup_id);
1875       priv->populate_popup_id = 0;
1876     }
1877
1878   if (priv->entry_menu_popdown_timeout)
1879     {
1880       g_source_remove (priv->entry_menu_popdown_timeout);
1881       priv->entry_menu_popdown_timeout = 0;
1882     }
1883
1884   g_object_get (entry,
1885                 "editing-canceled", &canceled,
1886                 NULL);
1887   gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (data), canceled);
1888
1889   if (canceled)
1890     return;
1891
1892   path = g_object_get_data (G_OBJECT (entry), GTK_CELL_RENDERER_TEXT_PATH);
1893   new_text = gtk_entry_get_text (GTK_ENTRY (entry));
1894
1895   g_signal_emit (data, text_cell_renderer_signals[EDITED], 0, path, new_text);
1896 }
1897
1898 static gboolean
1899 popdown_timeout (gpointer data)
1900 {
1901   GtkCellRendererTextPrivate *priv;
1902
1903   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
1904
1905   priv->entry_menu_popdown_timeout = 0;
1906
1907   if (!gtk_widget_has_focus (priv->entry))
1908     gtk_cell_renderer_text_editing_done (GTK_CELL_EDITABLE (priv->entry), data);
1909
1910   return FALSE;
1911 }
1912
1913 static void
1914 gtk_cell_renderer_text_popup_unmap (GtkMenu *menu,
1915                                     gpointer data)
1916 {
1917   GtkCellRendererTextPrivate *priv;
1918
1919   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
1920
1921   priv->in_entry_menu = FALSE;
1922
1923   if (priv->entry_menu_popdown_timeout)
1924     return;
1925
1926   priv->entry_menu_popdown_timeout = gdk_threads_add_timeout (500, popdown_timeout,
1927                                                     data);
1928 }
1929
1930 static void
1931 gtk_cell_renderer_text_populate_popup (GtkEntry *entry,
1932                                        GtkMenu  *menu,
1933                                        gpointer  data)
1934 {
1935   GtkCellRendererTextPrivate *priv;
1936
1937   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
1938
1939   if (priv->entry_menu_popdown_timeout)
1940     {
1941       g_source_remove (priv->entry_menu_popdown_timeout);
1942       priv->entry_menu_popdown_timeout = 0;
1943     }
1944
1945   priv->in_entry_menu = TRUE;
1946
1947   g_signal_connect (menu, "unmap",
1948                     G_CALLBACK (gtk_cell_renderer_text_popup_unmap), data);
1949 }
1950
1951 static gboolean
1952 gtk_cell_renderer_text_focus_out_event (GtkWidget *entry,
1953                                         GdkEvent  *event,
1954                                         gpointer   data)
1955 {
1956   GtkCellRendererTextPrivate *priv;
1957
1958   priv = GTK_CELL_RENDERER_TEXT (data)->priv;
1959
1960   if (priv->in_entry_menu)
1961     return FALSE;
1962
1963   g_object_set (entry,
1964                 "editing-canceled", TRUE,
1965                 NULL);
1966   gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
1967   gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
1968
1969   /* entry needs focus-out-event */
1970   return FALSE;
1971 }
1972
1973 static GtkCellEditable *
1974 gtk_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
1975                                       GdkEvent             *event,
1976                                       GtkWidget            *widget,
1977                                       const gchar          *path,
1978                                       const GdkRectangle   *background_area,
1979                                       const GdkRectangle   *cell_area,
1980                                       GtkCellRendererState  flags)
1981 {
1982   GtkCellRendererText *celltext;
1983   GtkCellRendererTextPrivate *priv;
1984   gfloat xalign, yalign;
1985
1986   celltext = GTK_CELL_RENDERER_TEXT (cell);
1987   priv = celltext->priv;
1988
1989   /* If the cell isn't editable we return NULL. */
1990   if (priv->editable == FALSE)
1991     return NULL;
1992
1993   gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
1994
1995   priv->entry = gtk_entry_new ();
1996   gtk_entry_set_has_frame (GTK_ENTRY (priv->entry), FALSE);
1997   gtk_entry_set_alignment (GTK_ENTRY (priv->entry), xalign);
1998
1999   if (priv->text)
2000     gtk_entry_set_text (GTK_ENTRY (priv->entry), priv->text);
2001   g_object_set_data_full (G_OBJECT (priv->entry), I_(GTK_CELL_RENDERER_TEXT_PATH), g_strdup (path), g_free);
2002   
2003   gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
2004
2005   priv->in_entry_menu = FALSE;
2006   if (priv->entry_menu_popdown_timeout)
2007     {
2008       g_source_remove (priv->entry_menu_popdown_timeout);
2009       priv->entry_menu_popdown_timeout = 0;
2010     }
2011
2012   g_signal_connect (priv->entry,
2013                     "editing-done",
2014                     G_CALLBACK (gtk_cell_renderer_text_editing_done),
2015                     celltext);
2016   priv->focus_out_id = g_signal_connect_after (priv->entry, "focus-out-event",
2017                                                G_CALLBACK (gtk_cell_renderer_text_focus_out_event),
2018                                                celltext);
2019   priv->populate_popup_id =
2020     g_signal_connect (priv->entry, "populate-popup",
2021                       G_CALLBACK (gtk_cell_renderer_text_populate_popup),
2022                       celltext);
2023  
2024   gtk_widget_show (priv->entry);
2025
2026   return GTK_CELL_EDITABLE (priv->entry);
2027 }
2028
2029 /**
2030  * gtk_cell_renderer_text_set_fixed_height_from_font:
2031  * @renderer: A #GtkCellRendererText
2032  * @number_of_rows: Number of rows of text each cell renderer is allocated, or -1
2033  * 
2034  * Sets the height of a renderer to explicitly be determined by the "font" and
2035  * "y_pad" property set on it.  Further changes in these properties do not
2036  * affect the height, so they must be accompanied by a subsequent call to this
2037  * function.  Using this function is unflexible, and should really only be used
2038  * if calculating the size of a cell is too slow (ie, a massive number of cells
2039  * displayed).  If @number_of_rows is -1, then the fixed height is unset, and
2040  * the height is determined by the properties again.
2041  **/
2042 void
2043 gtk_cell_renderer_text_set_fixed_height_from_font (GtkCellRendererText *renderer,
2044                                                    gint                 number_of_rows)
2045 {
2046   GtkCellRendererTextPrivate *priv;
2047   GtkCellRenderer *cell;
2048
2049   g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
2050   g_return_if_fail (number_of_rows == -1 || number_of_rows > 0);
2051
2052   cell = GTK_CELL_RENDERER (renderer);
2053   priv = renderer->priv;
2054
2055   if (number_of_rows == -1)
2056     {
2057       gint width, height;
2058
2059       gtk_cell_renderer_get_fixed_size (cell, &width, &height);
2060       gtk_cell_renderer_set_fixed_size (cell, width, -1);
2061     }
2062   else
2063     {
2064       priv->fixed_height_rows = number_of_rows;
2065       priv->calc_fixed_height = TRUE;
2066     }
2067 }
2068
2069 static void
2070 gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell,
2071                                             GtkWidget       *widget,
2072                                             gint            *minimum_size,
2073                                             gint            *natural_size)
2074 {
2075   GtkCellRendererTextPrivate *priv;
2076   GtkCellRendererText        *celltext;
2077   GtkStyleContext            *style_context;
2078   const PangoFontDescription *font_desc;
2079   PangoLayout                *layout;
2080   PangoContext               *context;
2081   PangoFontMetrics           *metrics;
2082   PangoRectangle              rect;
2083   gint char_width, text_width, ellipsize_chars, xpad;
2084   gint min_width, nat_width;
2085
2086   /* "width-chars" Hard-coded minimum width:
2087    *    - minimum size should be MAX (width-chars, strlen ("..."));
2088    *    - natural size should be MAX (width-chars, strlen (label->text));
2089    *
2090    * "wrap-width" User specified natural wrap width
2091    *    - minimum size should be MAX (width-chars, 0)
2092    *    - natural size should be MIN (wrap-width, strlen (label->text))
2093    */
2094
2095   celltext = GTK_CELL_RENDERER_TEXT (cell);
2096   priv = celltext->priv;
2097
2098   style_context = gtk_widget_get_style_context (widget);
2099
2100   gtk_cell_renderer_get_padding (cell, &xpad, NULL);
2101
2102   layout = get_layout (celltext, widget, NULL, 0);
2103
2104   /* Fetch the length of the complete unwrapped text */
2105   pango_layout_set_width (layout, -1);
2106   pango_layout_get_extents (layout, NULL, &rect);
2107   text_width = rect.width;
2108
2109   /* Fetch the average size of a charachter */
2110   context = pango_layout_get_context (layout);
2111   font_desc = gtk_style_context_get_font (style_context, 0);
2112   metrics = pango_context_get_metrics (context, font_desc,
2113                                        pango_context_get_language (context));
2114
2115   char_width = pango_font_metrics_get_approximate_char_width (metrics);
2116
2117   pango_font_metrics_unref (metrics);
2118   g_object_unref (layout);
2119
2120   /* enforce minimum width for ellipsized labels at ~3 chars */
2121   if (priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE)
2122     ellipsize_chars = 3;
2123   else
2124     ellipsize_chars = 0;
2125
2126   if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->width_chars > 0)
2127     min_width = xpad * 2 +
2128       MIN (PANGO_PIXELS_CEIL (text_width),
2129            (PANGO_PIXELS (char_width) * MAX (priv->width_chars, ellipsize_chars)));
2130   /* If no width-chars set, minimum for wrapping text will be the wrap-width */
2131   else if (priv->wrap_width > -1)
2132     min_width = xpad * 2 + rect.x + MIN (PANGO_PIXELS_CEIL (text_width), priv->wrap_width);
2133   else
2134     min_width = xpad * 2 + rect.x + PANGO_PIXELS_CEIL (text_width);
2135
2136   if (priv->width_chars > 0)
2137     nat_width = xpad * 2 +
2138       MAX ((PANGO_PIXELS (char_width) * priv->width_chars), PANGO_PIXELS_CEIL (text_width));
2139   else
2140     nat_width = xpad * 2 + PANGO_PIXELS_CEIL (text_width);
2141
2142   nat_width = MAX (nat_width, min_width);
2143
2144   if (priv->max_width_chars > 0)
2145     {
2146       gint max_width = xpad * 2 + PANGO_PIXELS (char_width) * priv->max_width_chars;
2147       
2148       min_width = MIN (min_width, max_width);
2149       nat_width = MIN (nat_width, max_width);
2150     }
2151
2152   if (minimum_size)
2153     *minimum_size = min_width;
2154
2155   if (natural_size)
2156     *natural_size = nat_width;
2157 }
2158
2159 static void
2160 gtk_cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer *cell,
2161                                                        GtkWidget       *widget,
2162                                                        gint             width,
2163                                                        gint            *minimum_height,
2164                                                        gint            *natural_height)
2165 {
2166   GtkCellRendererText *celltext;
2167   PangoLayout         *layout;
2168   gint                 text_height, xpad, ypad;
2169
2170
2171   celltext = GTK_CELL_RENDERER_TEXT (cell);
2172
2173   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
2174
2175   layout = get_layout (celltext, widget, NULL, 0);
2176
2177   pango_layout_set_width (layout, (width - xpad * 2) * PANGO_SCALE);
2178   pango_layout_get_pixel_size (layout, NULL, &text_height);
2179
2180   if (minimum_height)
2181     *minimum_height = text_height + ypad * 2;
2182
2183   if (natural_height)
2184     *natural_height = text_height + ypad * 2;
2185
2186   g_object_unref (layout);
2187 }
2188
2189 static void
2190 gtk_cell_renderer_text_get_preferred_height (GtkCellRenderer *cell,
2191                                              GtkWidget       *widget,
2192                                              gint            *minimum_size,
2193                                              gint            *natural_size)
2194 {
2195   gint min_width;
2196
2197   /* Thankfully cell renderers dont rotate, so they only have to do
2198    * height-for-width and not the opposite. Here we have only to return
2199    * the height for the base minimum width of the renderer.
2200    *
2201    * Note this code path wont be followed by GtkTreeView which is
2202    * height-for-width specifically.
2203    */
2204   gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL);
2205   gtk_cell_renderer_text_get_preferred_height_for_width (cell, widget, min_width,
2206                                                          minimum_size, natural_size);
2207 }
2208
2209 static void
2210 gtk_cell_renderer_text_get_aligned_area (GtkCellRenderer       *cell,
2211                                          GtkWidget             *widget,
2212                                          GtkCellRendererState   flags,
2213                                          const GdkRectangle    *cell_area,
2214                                          GdkRectangle          *aligned_area)
2215 {
2216   GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
2217   PangoLayout *layout;
2218   gint x_offset = 0;
2219   gint y_offset = 0;
2220
2221   layout = get_layout (celltext, widget, cell_area, flags);
2222   get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, 
2223             &aligned_area->width, &aligned_area->height);
2224
2225   aligned_area->x = cell_area->x + x_offset;
2226   aligned_area->y = cell_area->y + y_offset;
2227
2228   g_object_unref (layout);
2229 }