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