gtktexttag.c 69.7 KB
Newer Older
1
/* gtktexttag.c - text tag object
2
 *
3 4 5 6 7 8 9 10 11
 * Copyright (c) 1992-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 2000      Red Hat, Inc.
 * Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
 *
 * This software is copyrighted by the Regents of the University of
 * California, Sun Microsystems, Inc., and other parties.  The
 * following terms apply to all files associated with the software
 * unless explicitly disclaimed in individual files.
12
 *
13 14 15 16 17 18 19 20 21
 * The authors hereby grant permission to use, copy, modify,
 * distribute, and license this software and its documentation for any
 * purpose, provided that existing copyright notices are retained in
 * all copies and that this notice is included verbatim in any
 * distributions. No written agreement, license, or royalty fee is
 * required for any of the authorized uses.  Modifications to this
 * software may be copyrighted by their authors and need not follow
 * the licensing terms described here, provided that the new terms are
 * clearly indicated on the first page of each file where they apply.
22
 *
23 24 25 26 27
 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
 * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
 * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
 * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
 * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * GOVERNMENT USE: If you are acquiring this software on behalf of the
 * U.S. government, the Government shall have only "Restricted Rights"
 * in the software and related documentation as defined in the Federal
 * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
 * are acquiring the software on behalf of the Department of Defense,
 * the software shall be classified as "Commercial Computer Software"
 * and the Government shall have only "Restricted Rights" as defined
 * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
 * foregoing, the authors grant the U.S. Government and others acting
 * in its behalf permission to use and distribute the software in
 * accordance with the terms specified in this license.
47
 *
48 49
 */

50
#include <config.h>
51
#include "gtkmain.h"
52 53 54
#include "gtktexttag.h"
#include "gtktexttypes.h"
#include "gtktexttagtable.h"
55
#include "gtkmain.h"
56
#include "gtkintl.h"
57
#include "gtkmarshalers.h"
58 59

#include <stdlib.h>
60
#include <string.h>
61 62 63 64 65 66 67

enum {
  EVENT,
  LAST_SIGNAL
};

enum {
68
  PROP_0,
69
  /* Construct args */
70
  PROP_NAME,
71 72

  /* Style args */
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
  PROP_BACKGROUND,
  PROP_FOREGROUND,
  PROP_BACKGROUND_GDK,
  PROP_FOREGROUND_GDK,
  PROP_BACKGROUND_STIPPLE,
  PROP_FOREGROUND_STIPPLE,
  PROP_FONT,
  PROP_FONT_DESC,
  PROP_FAMILY,
  PROP_STYLE,
  PROP_VARIANT,
  PROP_WEIGHT,
  PROP_STRETCH,
  PROP_SIZE,
  PROP_SIZE_POINTS,
Havoc Pennington's avatar
Havoc Pennington committed
88
  PROP_SCALE,
89 90 91 92 93
  PROP_PIXELS_ABOVE_LINES,
  PROP_PIXELS_BELOW_LINES,
  PROP_PIXELS_INSIDE_WRAP,
  PROP_EDITABLE,
  PROP_WRAP_MODE,
94
  PROP_JUSTIFICATION,
95 96 97 98 99 100 101 102 103 104 105
  PROP_DIRECTION,
  PROP_LEFT_MARGIN,
  PROP_INDENT,
  PROP_STRIKETHROUGH,
  PROP_RIGHT_MARGIN,
  PROP_UNDERLINE,
  PROP_RISE,
  PROP_BG_FULL_HEIGHT,
  PROP_LANGUAGE,
  PROP_TABS,
  PROP_INVISIBLE,
106
  
107
  /* Whether-a-style-arg-is-set args */
108 109 110 111 112 113 114 115 116 117
  PROP_BACKGROUND_SET,
  PROP_FOREGROUND_SET,
  PROP_BACKGROUND_STIPPLE_SET,
  PROP_FOREGROUND_STIPPLE_SET,
  PROP_FAMILY_SET,
  PROP_STYLE_SET,
  PROP_VARIANT_SET,
  PROP_WEIGHT_SET,
  PROP_STRETCH_SET,
  PROP_SIZE_SET,
Havoc Pennington's avatar
Havoc Pennington committed
118
  PROP_SCALE_SET,
119 120 121 122 123
  PROP_PIXELS_ABOVE_LINES_SET,
  PROP_PIXELS_BELOW_LINES_SET,
  PROP_PIXELS_INSIDE_WRAP_SET,
  PROP_EDITABLE_SET,
  PROP_WRAP_MODE_SET,
124
  PROP_JUSTIFICATION_SET,
125 126 127 128 129 130 131 132 133 134
  PROP_LEFT_MARGIN_SET,
  PROP_INDENT_SET,
  PROP_STRIKETHROUGH_SET,
  PROP_RIGHT_MARGIN_SET,
  PROP_UNDERLINE_SET,
  PROP_RISE_SET,
  PROP_BG_FULL_HEIGHT_SET,
  PROP_LANGUAGE_SET,
  PROP_TABS_SET,
  PROP_INVISIBLE_SET,
135

136 137
  LAST_ARG
};
138 139 140 141 142 143
static void gtk_text_tag_init         (GtkTextTag      *text_tag);
static void gtk_text_tag_class_init   (GtkTextTagClass *klass);
static void gtk_text_tag_finalize     (GObject         *object);
static void gtk_text_tag_set_property (GObject         *object,
                                       guint            prop_id,
                                       const GValue    *value,
Tim Janik's avatar
Tim Janik committed
144
                                       GParamSpec      *pspec);
145 146 147
static void gtk_text_tag_get_property (GObject         *object,
                                       guint            prop_id,
                                       GValue          *value,
Tim Janik's avatar
Tim Janik committed
148
                                       GParamSpec      *pspec);
149 150

static GObjectClass *parent_class = NULL;
151 152
static guint signals[LAST_SIGNAL] = { 0 };

153
GType
154 155
gtk_text_tag_get_type (void)
{
156
  static GType our_type = 0;
157 158 159

  if (our_type == 0)
    {
160
      static const GTypeInfo our_info =
161 162
      {
        sizeof (GtkTextTagClass),
163 164 165 166 167 168 169 170
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gtk_text_tag_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GtkTextTag),
        0,              /* n_preallocs */
        (GInstanceInitFunc) gtk_text_tag_init
171 172
      };

Manish Singh's avatar
Manish Singh committed
173 174
      our_type = g_type_register_static (G_TYPE_OBJECT, "GtkTextTag",
                                         &our_info, 0);
175
    }
176 177 178 179 180 181 182

  return our_type;
}

static void
gtk_text_tag_class_init (GtkTextTagClass *klass)
{
183
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
184

185
  parent_class = g_type_class_peek_parent (klass);
186

187 188 189 190
  object_class->set_property = gtk_text_tag_set_property;
  object_class->get_property = gtk_text_tag_get_property;
  
  object_class->finalize = gtk_text_tag_finalize;
191

192
  /* Construct */
193 194 195
  g_object_class_install_property (object_class,
                                   PROP_NAME,
                                   g_param_spec_string ("name",
196 197
                                                        P_("Tag name"),
                                                        P_("Name used to refer to the text tag. NULL for anonymous tags"),
198 199
                                                        NULL,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
200 201

  /* Style args */
202 203 204 205

  g_object_class_install_property (object_class,
                                   PROP_BACKGROUND,
                                   g_param_spec_string ("background",
206 207
                                                        P_("Background color name"),
                                                        P_("Background color as a string"),
208 209 210 211 212 213
                                                        NULL,
                                                        G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_BACKGROUND_GDK,
                                   g_param_spec_boxed ("background_gdk",
214 215
                                                       P_("Background color"),
                                                       P_("Background color as a (possibly unallocated) GdkColor"),
216
                                                       GDK_TYPE_COLOR,
217 218 219 220 221
                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_BG_FULL_HEIGHT,
                                   g_param_spec_boolean ("background_full_height",
222 223
                                                         P_("Background full height"),
                                                         P_("Whether the background color fills the entire line height or only the height of the tagged characters"),
224 225 226
                                                         FALSE,
                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));

227
  
228 229 230
  g_object_class_install_property (object_class,
                                   PROP_BACKGROUND_STIPPLE,
                                   g_param_spec_object ("background_stipple",
231 232
                                                        P_("Background stipple mask"),
                                                        P_("Bitmap to use as a mask when drawing the text background"),
233 234 235 236 237 238 239
                                                        GDK_TYPE_PIXMAP,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));  


  g_object_class_install_property (object_class,
                                   PROP_FOREGROUND,
                                   g_param_spec_string ("foreground",
240 241
                                                        P_("Foreground color name"),
                                                        P_("Foreground color as a string"),
242 243 244 245 246 247
                                                        NULL,
                                                        G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_FOREGROUND_GDK,
                                   g_param_spec_boxed ("foreground_gdk",
248 249
                                                       P_("Foreground color"),
                                                       P_("Foreground color as a (possibly unallocated) GdkColor"),
250
                                                       GDK_TYPE_COLOR,
251 252
                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));

253
  
254 255 256
  g_object_class_install_property (object_class,
                                   PROP_FOREGROUND_STIPPLE,
                                   g_param_spec_object ("foreground_stipple",
257 258
                                                        P_("Foreground stipple mask"),
                                                        P_("Bitmap to use as a mask when drawing the text foreground"),
259 260 261 262 263 264
                                                        GDK_TYPE_PIXMAP,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));  
  
  g_object_class_install_property (object_class,
                                   PROP_DIRECTION,
                                   g_param_spec_enum ("direction",
265 266
                                                      P_("Text direction"),
                                                      P_("Text direction, e.g. right-to-left or left-to-right"),
267 268 269 270 271 272 273
                                                      GTK_TYPE_TEXT_DIRECTION,
                                                      GTK_TEXT_DIR_LTR,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
274 275
                                                         P_("Editable"),
                                                         P_("Whether the text can be modified by the user"),
276 277 278 279 280 281
                                                         TRUE,
                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_FONT,
                                   g_param_spec_string ("font",
282 283
                                                        P_("Font"),
                                                        P_("Font description as a string, e.g. \"Sans Italic 12\""),
284 285 286 287 288 289
                                                        NULL,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_FONT_DESC,
                                   g_param_spec_boxed ("font_desc",
290 291
                                                       P_("Font"),
                                                       P_("Font description as a PangoFontDescription struct"),
292
                                                       PANGO_TYPE_FONT_DESCRIPTION,
293 294 295 296 297 298
                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));

  
  g_object_class_install_property (object_class,
                                   PROP_FAMILY,
                                   g_param_spec_string ("family",
299 300
                                                        P_("Font family"),
                                                        P_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
301 302 303 304 305 306
                                                        NULL,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_STYLE,
                                   g_param_spec_enum ("style",
307 308
                                                      P_("Font style"),
                                                      P_("Font style as a PangoStyle, e.g. PANGO_STYLE_ITALIC"),
309 310 311 312 313 314 315
                                                      PANGO_TYPE_STYLE,
                                                      PANGO_STYLE_NORMAL,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_VARIANT,
                                   g_param_spec_enum ("variant",
316 317
                                                     P_("Font variant"),
                                                     P_("Font variant as a PangoVariant, e.g. PANGO_VARIANT_SMALL_CAPS"),
318 319 320 321 322 323 324
                                                      PANGO_TYPE_VARIANT,
                                                      PANGO_VARIANT_NORMAL,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_WEIGHT,
                                   g_param_spec_int ("weight",
325 326
                                                     P_("Font weight"),
                                                     P_("Font weight as an integer, see predefined values in PangoWeight; for example, PANGO_WEIGHT_BOLD"),
327 328 329 330 331 332 333 334 335
                                                     0,
                                                     G_MAXINT,
                                                     PANGO_WEIGHT_NORMAL,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  

  g_object_class_install_property (object_class,
                                   PROP_STRETCH,
                                   g_param_spec_enum ("stretch",
336 337
                                                      P_("Font stretch"),
                                                      P_("Font stretch as a PangoStretch, e.g. PANGO_STRETCH_CONDENSED"),
338 339 340 341 342 343 344
                                                      PANGO_TYPE_STRETCH,
                                                      PANGO_STRETCH_NORMAL,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_SIZE,
                                   g_param_spec_int ("size",
345 346
                                                     P_("Font size"),
                                                     P_("Font size in Pango units"),
347 348 349 350 351
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

Havoc Pennington's avatar
Havoc Pennington committed
352 353 354
  g_object_class_install_property (object_class,
                                   PROP_SCALE,
                                   g_param_spec_double ("scale",
355 356
                                                        P_("Font scale"),
                                                        P_("Font size as a scale factor relative to the default font size. This properly adapts to theme changes etc. so is recommended. Pango predefines some scales such as PANGO_SCALE_X_LARGE"),
Havoc Pennington's avatar
Havoc Pennington committed
357 358 359 360 361
                                                        0.0,
                                                        G_MAXDOUBLE,
                                                        1.0,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
  
362 363 364
  g_object_class_install_property (object_class,
                                   PROP_SIZE_POINTS,
                                   g_param_spec_double ("size_points",
365 366
                                                        P_("Font points"),
                                                        P_("Font size in points"),
367 368 369 370 371 372
                                                        0.0,
                                                        G_MAXDOUBLE,
                                                        0.0,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));  

  g_object_class_install_property (object_class,
373 374
                                   PROP_JUSTIFICATION,
                                   g_param_spec_enum ("justification",
375 376
                                                      P_("Justification"),
                                                      P_("Left, right, or center justification"),
377 378 379 380 381 382 383
                                                      GTK_TYPE_JUSTIFICATION,
                                                      GTK_JUSTIFY_LEFT,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_LANGUAGE,
                                   g_param_spec_string ("language",
384 385
                                                        P_("Language"),
                                                        P_("The language this text is in, as an ISO code. Pango can use this as a hint when rendering the text. If you don't understand this parameter, you probably don't need it"),
386 387 388 389 390 391
                                                        NULL,
                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));  

  g_object_class_install_property (object_class,
                                   PROP_LEFT_MARGIN,
                                   g_param_spec_int ("left_margin",
392 393
                                                     P_("Left margin"),
                                                     P_("Width of the left margin in pixels"),
394 395 396 397 398 399 400 401
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_RIGHT_MARGIN,
                                   g_param_spec_int ("right_margin",
402 403
                                                     P_("Right margin"),
                                                     P_("Width of the right margin in pixels"),
404 405 406 407 408 409 410 411 412
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  
  g_object_class_install_property (object_class,
                                   PROP_INDENT,
                                   g_param_spec_int ("indent",
413 414
                                                     P_("Indent"),
                                                     P_("Amount to indent the paragraph, in pixels"),
415
                                                     G_MININT,
416 417 418 419 420 421 422 423
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  
  g_object_class_install_property (object_class,
                                   PROP_RISE,
                                   g_param_spec_int ("rise",
424 425
                                                     P_("Rise"),
                                                     P_("Offset of text above the baseline (below the baseline if rise is negative) in pixels"),
426
						     G_MININT,
427 428 429 430 431 432 433
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_PIXELS_ABOVE_LINES,
                                   g_param_spec_int ("pixels_above_lines",
434 435
                                                     P_("Pixels above lines"),
                                                     P_("Pixels of blank space above paragraphs"),
436 437 438 439 440 441 442 443
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_PIXELS_BELOW_LINES,
                                   g_param_spec_int ("pixels_below_lines",
444 445
                                                     P_("Pixels below lines"),
                                                     P_("Pixels of blank space below paragraphs"),
446 447 448 449 450 451 452 453
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_PIXELS_INSIDE_WRAP,
                                   g_param_spec_int ("pixels_inside_wrap",
454 455
                                                     P_("Pixels inside wrap"),
                                                     P_("Pixels of blank space between wrapped lines in a paragraph"),
456 457 458 459 460 461 462 463
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));

  g_object_class_install_property (object_class,
                                   PROP_STRIKETHROUGH,
                                   g_param_spec_boolean ("strikethrough",
464 465
                                                         P_("Strikethrough"),
                                                         P_("Whether to strike through the text"),
466 467 468 469 470 471
                                                         FALSE,
                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_UNDERLINE,
                                   g_param_spec_enum ("underline",
472 473
                                                      P_("Underline"),
                                                      P_("Style of underline for this text"),
474 475 476 477 478 479 480
                                                      PANGO_TYPE_UNDERLINE,
                                                      PANGO_UNDERLINE_NONE,
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_WRAP_MODE,
                                   g_param_spec_enum ("wrap_mode",
481 482
                                                     P_("Wrap mode"),
                                                     P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
483
                                                      GTK_TYPE_WRAP_MODE,
484
                                                      GTK_WRAP_NONE,
485 486 487 488 489 490
                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
  

  g_object_class_install_property (object_class,
                                   PROP_TABS,
                                   g_param_spec_boxed ("tabs",
491 492
                                                       P_("Tabs"),
                                                       P_("Custom tabs for this text"),
493
                                                       PANGO_TYPE_TAB_ARRAY,
494 495 496 497 498
                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
                                   PROP_INVISIBLE,
                                   g_param_spec_boolean ("invisible",
499 500
                                                         P_("Invisible"),
                                                         P_("Whether this text is hidden. Not implemented in GTK 2.0"),
501 502 503 504 505 506 507 508
                                                         FALSE,
                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));

  /* Style props are set or not */

#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))

  ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
509 510
                P_("Background set"),
                P_("Whether this tag affects the background color"));
511 512
  
  ADD_SET_PROP ("background_full_height_set", PROP_BG_FULL_HEIGHT_SET,
513 514
                P_("Background full height set"),
                P_("Whether this tag affects background height"));
515 516

  ADD_SET_PROP ("background_stipple_set", PROP_BACKGROUND_STIPPLE_SET,
517 518
                P_("Background stipple set"),
                P_("Whether this tag affects the background stipple"));  
519 520

  ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET,
521 522
                P_("Foreground set"),
                P_("Whether this tag affects the foreground color"));
523 524

  ADD_SET_PROP ("foreground_stipple_set", PROP_FOREGROUND_STIPPLE_SET,
525 526
                P_("Foreground stipple set"),
                P_("Whether this tag affects the foreground stipple"));
527 528
  
  ADD_SET_PROP ("editable_set", PROP_EDITABLE_SET,
529 530
                P_("Editability set"),
                P_("Whether this tag affects text editability"));
531 532

  ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
533 534
                P_("Font family set"),
                P_("Whether this tag affects the font family"));  
535 536

  ADD_SET_PROP ("style_set", PROP_STYLE_SET,
537 538
                P_("Font style set"),
                P_("Whether this tag affects the font style"));
539 540

  ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
541 542
                P_("Font variant set"),
                P_("Whether this tag affects the font variant"));
543 544

  ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
545 546
                P_("Font weight set"),
                P_("Whether this tag affects the font weight"));
547 548

  ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
549 550
                P_("Font stretch set"),
                P_("Whether this tag affects the font stretch"));
551 552

  ADD_SET_PROP ("size_set", PROP_SIZE_SET,
553 554
                P_("Font size set"),
                P_("Whether this tag affects the font size"));
555

Havoc Pennington's avatar
Havoc Pennington committed
556
  ADD_SET_PROP ("scale_set", PROP_SCALE_SET,
557 558
                P_("Font scale set"),
                P_("Whether this tag scales the font size by a factor"));
Havoc Pennington's avatar
Havoc Pennington committed
559
  
560
  ADD_SET_PROP ("justification_set", PROP_JUSTIFICATION_SET,
561 562
                P_("Justification set"),
                P_("Whether this tag affects paragraph justification"));
Havoc Pennington's avatar
Havoc Pennington committed
563
  
564
  ADD_SET_PROP ("language_set", PROP_LANGUAGE_SET,
565 566
                P_("Language set"),
                P_("Whether this tag affects the language the text is rendered as"));
567 568

  ADD_SET_PROP ("left_margin_set", PROP_LEFT_MARGIN_SET,
569 570
                P_("Left margin set"),
                P_("Whether this tag affects the left margin"));
571 572

  ADD_SET_PROP ("indent_set", PROP_INDENT_SET,
573 574
                P_("Indent set"),
                P_("Whether this tag affects indentation"));
575 576

  ADD_SET_PROP ("rise_set", PROP_RISE_SET,
577 578
                P_("Rise set"),
                P_("Whether this tag affects the rise"));
579 580

  ADD_SET_PROP ("pixels_above_lines_set", PROP_PIXELS_ABOVE_LINES_SET,
581 582
                P_("Pixels above lines set"),
                P_("Whether this tag affects the number of pixels above lines"));
583 584

  ADD_SET_PROP ("pixels_below_lines_set", PROP_PIXELS_BELOW_LINES_SET,
585 586
                P_("Pixels below lines set"),
                P_("Whether this tag affects the number of pixels above lines"));
587 588

  ADD_SET_PROP ("pixels_inside_wrap_set", PROP_PIXELS_INSIDE_WRAP_SET,
589 590
                P_("Pixels inside wrap set"),
                P_("Whether this tag affects the number of pixels between wrapped lines"));
591 592

  ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
593 594
                P_("Strikethrough set"),
                P_("Whether this tag affects strikethrough"));
595 596
  
  ADD_SET_PROP ("right_margin_set", PROP_RIGHT_MARGIN_SET,
597 598
                P_("Right margin set"),
                P_("Whether this tag affects the right margin"));
599 600

  ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
601 602
                P_("Underline set"),
                P_("Whether this tag affects underlining"));
603 604

  ADD_SET_PROP ("wrap_mode_set", PROP_WRAP_MODE_SET,
605 606
                P_("Wrap mode set"),
                P_("Whether this tag affects line wrap mode"));
607 608

  ADD_SET_PROP ("tabs_set", PROP_TABS_SET,
609 610
                P_("Tabs set"),
                P_("Whether this tag affects tabs"));
611 612

  ADD_SET_PROP ("invisible_set", PROP_INVISIBLE_SET,
613 614
                P_("Invisible set"),
                P_("Whether this tag affects text visibility"));
615

616
  signals[EVENT] =
617 618 619
    g_signal_new ("event",
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_LAST,
Manish Singh's avatar
Manish Singh committed
620
                  G_STRUCT_OFFSET (GtkTextTagClass, event),
621
                  _gtk_boolean_handled_accumulator, NULL,
622
                  _gtk_marshal_BOOLEAN__OBJECT_BOXED_BOXED,
623 624 625
                  G_TYPE_BOOLEAN,
                  3,
                  G_TYPE_OBJECT,
Hans Breuer's avatar
Hans Breuer committed
626
                  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
627
                  GTK_TYPE_TEXT_ITER);
628 629
}

630
static void
631
gtk_text_tag_init (GtkTextTag *text_tag)
632 633 634
{
  /* 0 is basically a fine way to initialize everything in the
     entire struct */
635 636
  
  text_tag->values = gtk_text_attributes_new ();
637 638
}

639 640 641 642 643 644 645 646 647
/**
 * gtk_text_tag_new:
 * @name: tag name, or %NULL
 * 
 * Creates a #GtkTextTag. Configure the tag using object arguments,
 * i.e. using g_object_set().
 * 
 * Return value: a new #GtkTextTag
 **/
648 649 650 651 652
GtkTextTag*
gtk_text_tag_new (const gchar *name)
{
  GtkTextTag *tag;

Manish Singh's avatar
Manish Singh committed
653
  tag = g_object_new (GTK_TYPE_TEXT_TAG, "name", name, NULL);
654 655 656 657 658

  return tag;
}

static void
659
gtk_text_tag_finalize (GObject *object)
660
{
661
  GtkTextTag *text_tag;
662

663
  text_tag = GTK_TEXT_TAG (object);
664

665
  g_assert (!text_tag->values->realized);
666

667 668
  if (text_tag->table)
    gtk_text_tag_table_remove (text_tag->table, text_tag);
669

670
  g_assert (text_tag->table == NULL);
671

672 673
  gtk_text_attributes_unref (text_tag->values);
  text_tag->values = NULL;
674
  
675 676
  g_free (text_tag->name);
  text_tag->name = NULL;
677

678
  (* G_OBJECT_CLASS (parent_class)->finalize) (object);
679 680 681
}

static void
682
set_bg_color (GtkTextTag *tag, GdkColor *color)
683 684 685
{
  if (color)
    {
Havoc Pennington's avatar
Havoc Pennington committed
686 687 688
      if (!tag->bg_color_set)
        {
          tag->bg_color_set = TRUE;
689
          g_object_notify (G_OBJECT (tag), "background_set");
Havoc Pennington's avatar
Havoc Pennington committed
690 691
        }
      
692 693 694 695
      tag->values->appearance.bg_color = *color;
    }
  else
    {
Havoc Pennington's avatar
Havoc Pennington committed
696 697 698
      if (tag->bg_color_set)
        {
          tag->bg_color_set = FALSE;
699
          g_object_notify (G_OBJECT (tag), "background_set");
Havoc Pennington's avatar
Havoc Pennington committed
700
        }
701 702 703 704
    }
}

static void
705
set_fg_color (GtkTextTag *tag, GdkColor *color)
706 707 708
{
  if (color)
    {
Havoc Pennington's avatar
Havoc Pennington committed
709 710 711
      if (!tag->fg_color_set)
        {
          tag->fg_color_set = TRUE;
712
          g_object_notify (G_OBJECT (tag), "foreground_set");
Havoc Pennington's avatar
Havoc Pennington committed
713
        }
714 715 716 717
      tag->values->appearance.fg_color = *color;
    }
  else
    {
Havoc Pennington's avatar
Havoc Pennington committed
718 719 720
      if (tag->fg_color_set)
        {
          tag->fg_color_set = FALSE;
721
          g_object_notify (G_OBJECT (tag), "foreground_set");
Havoc Pennington's avatar
Havoc Pennington committed
722
        }
723 724 725
    }
}

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
static PangoFontMask
get_property_font_set_mask (guint prop_id)
{
  switch (prop_id)
    {
    case PROP_FAMILY_SET:
      return PANGO_FONT_MASK_FAMILY;
    case PROP_STYLE_SET:
      return PANGO_FONT_MASK_STYLE;
    case PROP_VARIANT_SET:
      return PANGO_FONT_MASK_VARIANT;
    case PROP_WEIGHT_SET:
      return PANGO_FONT_MASK_WEIGHT;
    case PROP_STRETCH_SET:
      return PANGO_FONT_MASK_STRETCH;
    case PROP_SIZE_SET:
      return PANGO_FONT_MASK_SIZE;
    }

  return 0;
}

748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
static PangoFontMask
set_font_desc_fields (PangoFontDescription *desc,
		      PangoFontMask         to_set)
{
  PangoFontMask changed_mask = 0;
  
  if (to_set & PANGO_FONT_MASK_FAMILY)
    {
      const char *family = pango_font_description_get_family (desc);
      if (!family)
	{
	  family = "sans";
	  changed_mask |= PANGO_FONT_MASK_FAMILY;
	}

      pango_font_description_set_family (desc, family);
    }
  if (to_set & PANGO_FONT_MASK_STYLE)
    pango_font_description_set_style (desc, pango_font_description_get_style (desc));
  if (to_set & PANGO_FONT_MASK_VARIANT)
    pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
  if (to_set & PANGO_FONT_MASK_WEIGHT)
    pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
  if (to_set & PANGO_FONT_MASK_STRETCH)
    pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
  if (to_set & PANGO_FONT_MASK_SIZE)
    {
      gint size = pango_font_description_get_size (desc);
      if (size <= 0)
	{
	  size = 10 * PANGO_SCALE;
	  changed_mask |= PANGO_FONT_MASK_SIZE;
	}
      
      pango_font_description_set_size (desc, size);
    }

  return changed_mask;
}

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
static void
notify_set_changed (GObject       *object,
		    PangoFontMask  changed_mask)
{
  if (changed_mask & PANGO_FONT_MASK_FAMILY)
    g_object_notify (object, "family_set");
  if (changed_mask & PANGO_FONT_MASK_STYLE)
    g_object_notify (object, "style_set");
  if (changed_mask & PANGO_FONT_MASK_VARIANT)
    g_object_notify (object, "variant_set");
  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
    g_object_notify (object, "weight_set");
  if (changed_mask & PANGO_FONT_MASK_STRETCH)
    g_object_notify (object, "stretch_set");
  if (changed_mask & PANGO_FONT_MASK_SIZE)
    g_object_notify (object, "size_set");
}

806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
static void
notify_fields_changed (GObject       *object,
		       PangoFontMask  changed_mask)
{
  if (changed_mask & PANGO_FONT_MASK_FAMILY)
    g_object_notify (object, "family");
  if (changed_mask & PANGO_FONT_MASK_STYLE)
    g_object_notify (object, "style");
  if (changed_mask & PANGO_FONT_MASK_VARIANT)
    g_object_notify (object, "variant");
  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
    g_object_notify (object, "weight");
  if (changed_mask & PANGO_FONT_MASK_STRETCH)
    g_object_notify (object, "stretch");
  if (changed_mask & PANGO_FONT_MASK_SIZE)
    g_object_notify (object, "size");
}

824 825 826 827
static void
set_font_description (GtkTextTag           *text_tag,
                      PangoFontDescription *font_desc)
{
828 829 830 831 832 833 834 835 836 837 838
  GObject *object = G_OBJECT (text_tag);
  PangoFontDescription *new_font_desc;
  PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
  
  if (font_desc)
    new_font_desc = pango_font_description_copy (font_desc);
  else
    new_font_desc = pango_font_description_new ();

  if (text_tag->values->font)
    old_mask = pango_font_description_get_set_fields (text_tag->values->font);
839
  else
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
    old_mask = 0;
  
  new_mask = pango_font_description_get_set_fields (new_font_desc);

  changed_mask = old_mask | new_mask;
  set_changed_mask = old_mask ^ new_mask;

  if (text_tag->values->font)
    pango_font_description_free (text_tag->values->font);
  text_tag->values->font = new_font_desc;
  
  g_object_freeze_notify (object);

  g_object_notify (object, "font_desc");
  g_object_notify (object, "font");
  
  if (changed_mask & PANGO_FONT_MASK_FAMILY)
    g_object_notify (object, "family");
  if (changed_mask & PANGO_FONT_MASK_STYLE)
    g_object_notify (object, "style");
  if (changed_mask & PANGO_FONT_MASK_VARIANT)
    g_object_notify (object, "variant");
  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
    g_object_notify (object, "weight");
  if (changed_mask & PANGO_FONT_MASK_STRETCH)
    g_object_notify (object, "stretch");
  if (changed_mask & PANGO_FONT_MASK_SIZE)
Havoc Pennington's avatar
Havoc Pennington committed
867
    {
868 869
      g_object_notify (object, "size");
      g_object_notify (object, "size_points");
870
    }
871 872 873 874 875 876 877 878 879 880 881

  notify_set_changed (object, set_changed_mask);
  
  g_object_thaw_notify (object);
}

static void
gtk_text_tag_ensure_font (GtkTextTag *text_tag)
{
  if (!text_tag->values->font)
    text_tag->values->font = pango_font_description_new ();
882 883
}

884
static void
885 886 887
gtk_text_tag_set_property (GObject      *object,
                           guint         prop_id,
                           const GValue *value,
Tim Janik's avatar
Tim Janik committed
888
                           GParamSpec   *pspec)
889
{
890
  GtkTextTag *text_tag;
891
  gboolean size_changed = FALSE;
892

893
  text_tag = GTK_TEXT_TAG (object);
894

895
  g_return_if_fail (!text_tag->values->realized);
896

897
  switch (prop_id)
898
    {
899
    case PROP_NAME:
900
      g_return_if_fail (text_tag->name == NULL);
901
      text_tag->name = g_strdup (g_value_get_string (value));
902 903
      break;

904
    case PROP_BACKGROUND:
905 906 907
      {
        GdkColor color;

908
        if (gdk_color_parse (g_value_get_string (value), &color))
909
          set_bg_color (text_tag, &color);
910
        else
911
          g_warning ("Don't know color `%s'", g_value_get_string (value));
Havoc Pennington's avatar
Havoc Pennington committed
912

913
        g_object_notify (object, "background_gdk");
914 915 916
      }
      break;

917
    case PROP_FOREGROUND:
918 919 920
      {
        GdkColor color;

921
        if (gdk_color_parse (g_value_get_string (value), &color))
922
          set_fg_color (text_tag, &color);
923
        else
924
          g_warning ("Don't know color `%s'", g_value_get_string (value));
Havoc Pennington's avatar
Havoc Pennington committed
925

926
        g_object_notify (object, "foreground_gdk");
927 928
      }
      break;
929

930
    case PROP_BACKGROUND_GDK:
931
      {
Tim Janik's avatar
Tim Janik committed
932 933
        GdkColor *color = g_value_get_boxed (value);

934
        set_bg_color (text_tag, color);
935 936 937
      }
      break;

938
    case PROP_FOREGROUND_GDK:
939
      {
Tim Janik's avatar
Tim Janik committed
940 941
        GdkColor *color = g_value_get_boxed (value);

942
        set_fg_color (text_tag, color);
943 944 945
      }
      break;

946
    case PROP_BACKGROUND_STIPPLE:
947
      {
948
        GdkBitmap *bitmap = g_value_get_object (value);
949

950
        text_tag->bg_stipple_set = TRUE;
951
        g_object_notify (object, "background_stipple_set");
Havoc Pennington's avatar
Havoc Pennington committed
952
        
953
        if (text_tag->values->appearance.bg_stipple != bitmap)
954 955
          {
            if (bitmap != NULL)
Manish Singh's avatar
Manish Singh committed
956
              g_object_ref (bitmap);
957

958
            if (text_tag->values->appearance.bg_stipple)
Manish Singh's avatar
Manish Singh committed
959
              g_object_unref (text_tag->values->appearance.bg_stipple);
960

961
            text_tag->values->appearance.bg_stipple = bitmap;
962 963 964 965
          }
      }
      break;

966
    case PROP_FOREGROUND_STIPPLE:
967
      {
968
        GdkBitmap *bitmap = g_value_get_object (value);
969

970
        text_tag->fg_stipple_set = TRUE;
971
        g_object_notify (object, "foreground_stipple_set");
972

973
        if (text_tag->values->appearance.fg_stipple != bitmap)
974 975
          {
            if (bitmap != NULL)
Manish Singh's avatar
Manish Singh committed
976
              g_object_ref (bitmap);
977

978
            if (text_tag->values->appearance.fg_stipple)
Manish Singh's avatar
Manish Singh committed
979
              g_object_unref (text_tag->values->appearance.fg_stipple);
980

981
            text_tag->values->appearance.fg_stipple = bitmap;
982 983 984 985
          }
      }
      break;

986
    case PROP_FONT:
987 988 989 990
      {
        PangoFontDescription *font_desc = NULL;
        const gchar *name;

991
        name = g_value_get_string (value);
992 993

        if (name)
994 995
          font_desc = pango_font_description_from_string (name);

996
        set_font_description (text_tag, font_desc);
997 998
	if (font_desc)
	  pango_font_description_free (font_desc);
999
        
1000 1001 1002 1003
        size_changed = TRUE;
      }
      break;

1004
    case PROP_FONT_DESC:
1005 1006 1007
      {
        PangoFontDescription *font_desc;

Tim Janik's avatar
Tim Janik committed
1008
        font_desc = g_value_get_boxed (value);
1009

1010
        set_font_description (text_tag, font_desc);
1011 1012 1013 1014 1015

        size_changed = TRUE;
      }
      break;

1016 1017 1018 1019 1020 1021
    case PROP_FAMILY:
    case PROP_STYLE:
    case PROP_VARIANT:
    case PROP_WEIGHT:
    case PROP_STRETCH:
    case PROP_SIZE:
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
    case PROP_SIZE_POINTS:
      {
	PangoFontMask old_set_mask;

	gtk_text_tag_ensure_font (text_tag);
	old_set_mask = pango_font_description_get_set_fields (text_tag->values->font);
 
	switch (prop_id)
	  {
	  case PROP_FAMILY:
	    pango_font_description_set_family (text_tag->values->font,
					       g_value_get_string (value));
	    break;
	  case PROP_STYLE:
	    pango_font_description_set_style (text_tag->values->font,
					      g_value_get_enum (value));
	    break;
	  case PROP_VARIANT:
	    pango_font_description_set_variant (text_tag->values->font,
						g_value_get_enum (value));
	    break;
	  case PROP_WEIGHT:
	    pango_font_description_set_weight (text_tag->values->font,
1045
					       g_value_get_int (value));
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
	    break;
	  case PROP_STRETCH:
	    pango_font_description_set_stretch (text_tag->values->font,
						g_value_get_enum (value));
	    break;
	  case PROP_SIZE:
	    pango_font_description_set_size (text_tag->values->font,
					     g_value_get_int (value));
	    g_object_notify (object, "size_points");
	    break;
	  case PROP_SIZE_POINTS:
	    pango_font_description_set_size (text_tag->values->font,
					     g_value_get_double (value) * PANGO_SCALE);
	    g_object_notify (object, "size");
	    break;
	  }

	size_changed = TRUE;
	notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (text_tag->values->font));
	g_object_notify (object, "font_desc");
	g_object_notify (object, "font");
1067 1068

	break;
1069 1070
      }
      
Havoc Pennington's avatar
Havoc Pennington committed
1071 1072 1073
    case PROP_SCALE:
      text_tag->values->font_scale = g_value_get_double (value);
      text_tag->scale_set = TRUE;
1074
      g_object_notify (object, "scale_set");
1075 1076 1077
      size_changed = TRUE;
      break;
      
1078
    case PROP_PIXELS_ABOVE_LINES:
1079
      text_tag->pixels_above_lines_set = TRUE;
1080
      text_tag->values->pixels_above_lines = g_value_get_int (value);
1081
      g_object_notify (object, "pixels_above_lines_set");
1082 1083 1084
      size_changed = TRUE;
      break;

1085
    case PROP_PIXELS_BELOW_LINES:
1086
      text_tag->pixels_below_lines_set = TRUE;
1087
      text_tag->values->pixels_below_lines = g_value_get_int (value);
1088
      g_object_notify (object, "pixels_below_lines_set");
1089 1090 1091
      size_changed = TRUE;
      break;

1092
    case PROP_PIXELS_INSIDE_WRAP:
1093
      text_tag->pixels_inside_wrap_set = TRUE;
1094
      text_tag->values->pixels_inside_wrap = g_value_get_int (value);
1095
      g_object_notify (object, "pixels_inside_wrap_set");
1096 1097 1098
      size_changed = TRUE;
      break;

1099
    case PROP_EDITABLE:
1100
      text_tag->editable_set = TRUE;
1101
      text_tag->values->editable = g_value_get_boolean (value);
1102
      g_object_notify (object, "editable_set");
1103 1104
      break;

1105
    case PROP_WRAP_MODE:
1106
      text_tag->wrap_mode_set = TRUE;
1107
      text_tag->values->wrap_mode = g_value_get_enum (value);
1108
      g_object_notify (object, "wrap_mode_set");
1109 1110 1111
      size_changed = TRUE;
      break;

1112 1113 1114
    case PROP_JUSTIFICATION:
      text_tag->justification_set = TRUE;
      text_tag->values->justification = g_value_get_enum (value);
1115
      g_object_notify (object, "justification_set");
1116 1117 1118
      size_changed = TRUE;
      break;

1119 1120
    case PROP_DIRECTION:
      text_tag->values->direction = g_value_get_enum (value);
1121 1122
      break;

1123
    case PROP_LEFT_MARGIN:
1124
      text_tag->left_margin_set = TRUE;
1125
      text_tag->values->left_margin = g_value_get_int (value);
1126
      g_object_notify (object, "left_margin_set");
1127 1128 1129
      size_changed = TRUE;
      break;

1130
    case PROP_INDENT:
1131
      text_tag->indent_set = TRUE;
1132
      text_tag->values->indent = g_value_get_int (value);
1133
      g_object_notify (object, "indent_set");
1134 1135 1136
      size_changed = TRUE;
      break;

1137
    case PROP_STRIKETHROUGH:
1138
      text_tag->strikethrough_set = TRUE;
1139
      text_tag->values->appearance.strikethrough = g_value_get_boolean (value);
1140
      g_object_notify (object, "strikethrough_set");
1141
      break;
1142

1143
    case PROP_RIGHT_MARGIN:
1144
      text_tag->right_margin_set = TRUE;
1145
      text_tag->values->right_margin = g_value_get_int (value);
1146
      g_object_notify (object, "right_margin_set");
1147 1148
      size_changed = TRUE;
      break;
1149

1150
    case PROP_UNDERLINE:
1151
      text_tag->underline_set = TRUE;
1152
      text_tag->values->appearance.underline = g_value_get_enum (value);
1153
      g_object_notify (object, "underline_set");
1154
      break;
1155

1156
    case PROP_RISE:
1157
      text_tag->rise_set = TRUE;
1158
      text_tag->values->appearance.rise = g_value_get_int (value);
1159
      g_object_notify (object, "rise_set");
Havoc Pennington's avatar
Havoc Pennington committed
1160
      size_changed = TRUE;      
1161 1162
      break;

1163
    case PROP_BG_FULL_HEIGHT:
1164
      text_tag->bg_full_height_set = TRUE;
1165
      text_tag->values->bg_full_height = g_value_get_boolean (value);
1166
      g_object_notify (object, "background_full_height_set");
1167 1168
      break;

1169
    case PROP_LANGUAGE: