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