gtklabel.c 212 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
22
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 24
 */

25
#include "config.h"
26

27
#include <math.h>
Elliot Lee's avatar
Elliot Lee committed
28
#include <string.h>
29

Elliot Lee's avatar
Elliot Lee committed
30
#include "gtklabel.h"
31
#include "gtklabelprivate.h"
32
#include "gtkaccellabel.h"
33 34
#include "gtkbindings.h"
#include "gtkbuildable.h"
35
#include "gtkbuilderprivate.h"
36
#include "gtkclipboard.h"
37
#include "gtkcssshadowsvalueprivate.h"
38
#include "gtkcssstylepropertyprivate.h"
39
#include "gtkdnd.h"
40
#include "gtkimage.h"
41
#include "gtkintl.h"
42
#include "gtkmain.h"
43
#include "gtkmarshalers.h"
44
#include "gtkmenuitem.h"
45
#include "gtkmenushellprivate.h"
46
#include "gtknotebook.h"
47 48 49
#include "gtkpango.h"
#include "gtkprivate.h"
#include "gtkseparatormenuitem.h"
50
#include "gtkshow.h"
51
#include "gtkstylecontextprivate.h"
52
#include "gtktextutil.h"
53
#include "gtktooltip.h"
54
#include "gtktypebuiltins.h"
55 56
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
57
#include "gtkcssnodeprivate.h"
58
#include "gtkcsscustomgadgetprivate.h"
59
#include "gtkwidgetprivate.h"
60

61
#include "a11y/gtklabelaccessibleprivate.h"
62

Chun-wei Fan's avatar
Chun-wei Fan committed
63 64 65 66 67
/* this is in case rint() is not provided by the compiler, 
 * such as in the case of C89 compilers, like MSVC
 */
#include "fallback-c89.c"

68 69 70 71 72 73 74
/**
 * SECTION:gtklabel
 * @Short_description: A widget that displays a small to medium amount of text
 * @Title: GtkLabel
 *
 * The #GtkLabel widget displays a small amount of text. As the name
 * implies, most labels are used to label another widget such as a
75
 * #GtkButton, a #GtkMenuItem, or a #GtkComboBox.
76
 *
77 78
 * # CSS nodes
 *
79 80 81 82 83 84 85 86
 * |[<!-- language="plain" -->
 * label
 * ├── [selection]
 * ├── [link]
 * ┊
 * ╰── [link]
 * ]|
 *
87 88
 * GtkLabel has a single CSS node with the name label. A wide variety
 * of style classes may be applied to labels, such as .title, .subtitle,
89 90
 * .dim-label, etc. In the #GtkShortcutsWindow, labels are used wth the
 * .keycap style class.
91
 *
92 93 94 95 96 97
 * If the label has a selection, it gets a subnode with name selection.
 *
 * If the label has links, there is one subnode per link. These subnodes
 * carry the link or visited state depending on whether they have been
 * visited.
 *
98
 * # GtkLabel as GtkBuildable
99
 *
100
 * The GtkLabel implementation of the GtkBuildable interface supports a
101 102 103 104
 * custom <attributes> element, which supports any number of <attribute>
 * elements. The <attribute> element has attributes named “name“, “value“,
 * “start“ and “end“ and allows you to specify #PangoAttribute values for
 * this label.
105
 *
106
 * An example of a UI definition fragment specifying Pango attributes:
107
 * |[
108 109 110
 * <object class="GtkLabel">
 *   <attributes>
 *     <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
111
 *     <attribute name="background" value="red" start="5" end="10"/>
112 113
 *   </attributes>
 * </object>
114
 * ]|
115
 *
116 117 118 119 120
 * The start and end attributes specify the range of characters to which the
 * Pango attribute applies. If start and end are not specified, the attribute is
 * applied to the whole text. Note that specifying ranges does not make much
 * sense with translatable attributes. Use markup embedded in the translatable
 * content instead.
121
 *
122
 * # Mnemonics
123
 *
124
 * Labels may contain “mnemonics”. Mnemonics are
125 126
 * underlined characters in the label, used for keyboard navigation.
 * Mnemonics are created by providing a string with an underscore before
127
 * the mnemonic character, such as `"_File"`, to the
128 129 130 131 132
 * functions gtk_label_new_with_mnemonic() or
 * gtk_label_set_text_with_mnemonic().
 *
 * Mnemonics automatically activate any activatable widget the label is
 * inside, such as a #GtkButton; if the label is not inside the
133 134
 * mnemonic’s target widget, you have to tell the label about the target
 * using gtk_label_set_mnemonic_widget(). Here’s a simple example where
135 136
 * the label is inside a button:
 *
137
 * |[<!-- language="C" -->
138
 *   // Pressing Alt+H will activate this button
139 140
 *   GtkWidget *button = gtk_button_new ();
 *   GtkWidget *label = gtk_label_new_with_mnemonic ("_Hello");
141
 *   gtk_container_add (GTK_CONTAINER (button), label);
142
 * ]|
143
 *
144
 * There’s a convenience function to create buttons with a mnemonic label
145 146
 * already inside:
 *
147
 * |[<!-- language="C" -->
148
 *   // Pressing Alt+H will activate this button
149
 *   GtkWidget *button = gtk_button_new_with_mnemonic ("_Hello");
150
 * ]|
151 152 153 154 155
 *
 * To create a mnemonic for a widget alongside the label, such as a
 * #GtkEntry, you have to point the label at the entry with
 * gtk_label_set_mnemonic_widget():
 *
156
 * |[<!-- language="C" -->
157
 *   // Pressing Alt+H will focus the entry
158 159
 *   GtkWidget *entry = gtk_entry_new ();
 *   GtkWidget *label = gtk_label_new_with_mnemonic ("_Hello");
160
 *   gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
161
 * ]|
162
 *
163
 * # Markup (styled text)
164 165
 *
 * To make it easy to format text in a label (changing colors,
166 167
 * fonts, etc.), label text can be provided in a simple
 * [markup format][PangoMarkupFormat].
168
 *
169
 * Here’s how to create a label with a small font:
170
 * |[<!-- language="C" -->
171
 *   GtkWidget *label = gtk_label_new (NULL);
172
 *   gtk_label_set_markup (GTK_LABEL (label), "<small>Small text</small>");
173
 * ]|
174
 *
175
 * (See [complete documentation][PangoMarkupFormat] of available
176 177 178
 * tags in the Pango manual.)
 *
 * The markup passed to gtk_label_set_markup() must be valid; for example,
179 180 181
 * literal <, > and & characters must be escaped as &lt;, &gt;, and &amp;.
 * If you pass text obtained from the user, file, or a network to
 * gtk_label_set_markup(), you’ll want to escape it with
182 183 184 185 186
 * g_markup_escape_text() or g_markup_printf_escaped().
 *
 * Markup strings are just a convenient way to set the #PangoAttrList on
 * a label; gtk_label_set_attributes() may be a simpler way to set
 * attributes in some cases. Be careful though; #PangoAttrList tends to
187
 * cause internationalization problems, unless you’re applying attributes
188 189 190 191
 * to the entire string (i.e. unless you set the range of each attribute
 * to [0, %G_MAXINT)). The reason is that specifying the start_index and
 * end_index for a #PangoAttribute requires knowledge of the exact string
 * being displayed, so translations will cause problems.
192
 *
193
 * # Selectable labels
194
 *
195 196 197
 * Labels can be made selectable with gtk_label_set_selectable().
 * Selectable labels allow the user to copy the label contents to
 * the clipboard. Only labels that contain useful-to-copy information
198
 * — such as error messages — should be made selectable.
199
 *
200
 * # Text layout # {#label-text-layout}
201
 *
202 203 204 205 206 207 208 209 210 211
 * A label can contain any number of paragraphs, but will have
 * performance problems if it contains more than a small number.
 * Paragraphs are separated by newlines or other paragraph separators
 * understood by Pango.
 *
 * Labels can automatically wrap text if you call
 * gtk_label_set_line_wrap().
 *
 * gtk_label_set_justify() sets how the lines in a label align
 * with one another. If you want to set how the label as a whole
212
 * aligns in its available space, see the #GtkWidget:halign and
213
 * #GtkWidget:valign properties.
214 215 216 217 218 219 220 221 222 223 224 225
 *
 * The #GtkLabel:width-chars and #GtkLabel:max-width-chars properties
 * can be used to control the size allocation of ellipsized or wrapped
 * labels. For ellipsizing labels, if either is specified (and less
 * than the actual text size), it is used as the minimum width, and the actual
 * text size is used as the natural width of the label. For wrapping labels,
 * width-chars is used as the minimum width, if specified, and max-width-chars
 * is used as the natural width. Even if max-width-chars specified, wrapping
 * labels will be rewrapped to use all of the available width.
 *
 * Note that the interpretation of #GtkLabel:width-chars and
 * #GtkLabel:max-width-chars has changed a bit with the introduction of
226
 * [width-for-height geometry management.][geometry-management]
227
 *
228
 * # Links
229
 *
230
 * Since 2.18, GTK+ supports markup for clickable hyperlinks in addition
231
 * to regular Pango markup. The markup for links is borrowed from HTML,
232
 * using the `<a>` with “href“ and “title“ attributes. GTK+ renders links
233
 * similar to the way they appear in web browsers, with colored, underlined
234
 * text. The “title“ attribute is displayed as a tooltip on the link.
235
 *
236
 * An example looks like this:
237
 *
238
 * |[<!-- language="C" -->
239 240
 * const gchar *text =
 * "Go to the"
241
 * "<a href=\"http://www.gtk.org title=\"&lt;i&gt;Our&lt;/i&gt; website\">"
242
 * "GTK+ website</a> for more...";
243 244
 * GtkWidget *label = gtk_label_new (NULL);
 * gtk_label_set_markup (GTK_LABEL (label), text);
245
 * ]|
246 247 248 249 250
 *
 * It is possible to implement custom handling for links and their tooltips with
 * the #GtkLabel::activate-link signal and the gtk_label_get_current_uri() function.
 */

251
struct _GtkLabelPrivate
252
{
253 254 255
  GtkLabelSelectionInfo *select_info;
  GtkWidget *mnemonic_widget;
  GtkWindow *mnemonic_window;
256
  GtkCssGadget *gadget;
257 258

  PangoAttrList *attrs;
Benjamin Otte's avatar
Benjamin Otte committed
259
  PangoAttrList *markup_attrs;
260
  PangoLayout   *layout;
261

262 263 264
  gchar   *label;
  gchar   *text;

265
  gdouble  angle;
266 267
  gfloat   xalign;
  gfloat   yalign;
268

269
  guint    mnemonics_visible  : 1;
270 271 272 273 274 275 276 277 278 279 280
  guint    jtype              : 2;
  guint    wrap               : 1;
  guint    use_underline      : 1;
  guint    use_markup         : 1;
  guint    ellipsize          : 3;
  guint    single_line_mode   : 1;
  guint    have_transform     : 1;
  guint    in_click           : 1;
  guint    wrap_mode          : 3;
  guint    pattern_set        : 1;
  guint    track_links        : 1;
281 282 283 284 285

  guint    mnemonic_keyval;

  gint     width_chars;
  gint     max_width_chars;
286
  gint     lines;
287
};
288 289 290 291 292 293 294

/* Notes about the handling of links:
 *
 * Links share the GtkLabelSelectionInfo struct with selectable labels.
 * There are some new fields for links. The links field contains the list
 * of GtkLabelLink structs that describe the links which are embedded in
 * the label. The active_link field points to the link under the mouse
295
 * pointer. For keyboard navigation, the “focus” link is determined by
296 297 298 299 300
 * finding the link which contains the selection_anchor position.
 * The link_clicked field is used with button press and release events
 * to ensure that pressing inside a link and releasing outside of it
 * does not activate the link.
 *
301 302 303
 * Links are rendered with the #GTK_STATE_FLAG_LINK/#GTK_STATE_FLAG_VISITED
 * state flags. When the mouse pointer is over a link, the pointer is changed
 * to indicate the link.
304 305 306 307
 *
 * Labels with links accept keyboard focus, and it is possible to move
 * the focus between the embedded links using Tab/Shift-Tab. The focus
 * is indicated by a focus rectangle that is drawn around the link text.
Arnaud B.'s avatar
Arnaud B. committed
308
 * Pressing Enter activates the focused link, and there is a suitable
309 310 311 312 313 314 315 316 317 318
 * context menu for links that can be opened with the Menu key. Pressing
 * Control-C copies the link URI to the clipboard.
 *
 * In selectable labels with links, link functionality is only available
 * when the selection is empty.
 */
typedef struct
{
  gchar *uri;
  gchar *title;     /* the title attribute, used as tooltip */
319 320 321

  GtkCssNode *cssnode;

322 323 324 325 326 327
  gboolean visited; /* get set when the link is activated; this flag
                     * gets preserved over later set_markup() calls
                     */
  gint start;       /* position of the link in the PangoLayout */
  gint end;
} GtkLabelLink;
328

329 330 331 332 333
struct _GtkLabelSelectionInfo
{
  GdkWindow *window;
  gint selection_anchor;
  gint selection_end;
334
  GtkWidget *popup_menu;
335
  GtkCssNode *selection_node;
336 337 338 339

  GList *links;
  GtkLabelLink *active_link;

340 341 342
  GtkGesture *drag_gesture;
  GtkGesture *multipress_gesture;

343 344 345
  gint drag_start_x;
  gint drag_start_y;

346
  guint in_drag      : 1;
347
  guint select_words : 1;
348 349
  guint selectable   : 1;
  guint link_clicked : 1;
350
};
Elliot Lee's avatar
Elliot Lee committed
351

352 353 354 355
enum {
  MOVE_CURSOR,
  COPY_CLIPBOARD,
  POPULATE_POPUP,
356
  ACTIVATE_LINK,
357
  ACTIVATE_CURRENT_LINK,
358 359
  LAST_SIGNAL
};
360

361
enum {
362 363 364 365 366 367 368 369
  PROP_0,
  PROP_LABEL,
  PROP_ATTRIBUTES,
  PROP_USE_MARKUP,
  PROP_USE_UNDERLINE,
  PROP_JUSTIFY,
  PROP_PATTERN,
  PROP_WRAP,
370
  PROP_WRAP_MODE,
371
  PROP_SELECTABLE,
372
  PROP_MNEMONIC_KEYVAL,
373 374
  PROP_MNEMONIC_WIDGET,
  PROP_CURSOR_POSITION,
375
  PROP_SELECTION_BOUND,
376
  PROP_ELLIPSIZE,
377
  PROP_WIDTH_CHARS,
378
  PROP_SINGLE_LINE_MODE,
379
  PROP_ANGLE,
380
  PROP_MAX_WIDTH_CHARS,
381
  PROP_TRACK_VISITED_LINKS,
382 383
  PROP_LINES,
  PROP_XALIGN,
384 385
  PROP_YALIGN,
  NUM_PROPERTIES
386 387
};

388 389
static GParamSpec *label_props[NUM_PROPERTIES] = { NULL, };

390 391 392
/* When rotating ellipsizable text we want the natural size to request 
 * more to ensure the label wont ever ellipsize in an allocation of full natural size.
 * */
393
#define ROTATION_ELLIPSIZE_PADDING 2
394

395 396
static guint signals[LAST_SIGNAL] = { 0 };

397 398 399 400 401 402
static GQuark quark_shortcuts_connected;
static GQuark quark_mnemonic_menu;
static GQuark quark_mnemonics_visible_connected;
static GQuark quark_gtk_signal;
static GQuark quark_link;

403 404 405
static void gtk_label_set_property      (GObject          *object,
					 guint             prop_id,
					 const GValue     *value,
406
					 GParamSpec       *pspec);
407 408 409
static void gtk_label_get_property      (GObject          *object,
					 guint             prop_id,
					 GValue           *value,
410
					 GParamSpec       *pspec);
411
static void gtk_label_finalize          (GObject          *object);
412
static void gtk_label_destroy           (GtkWidget        *widget);
413 414
static void gtk_label_size_allocate     (GtkWidget        *widget,
                                         GtkAllocation    *allocation);
415 416
static void gtk_label_state_flags_changed   (GtkWidget        *widget,
                                             GtkStateFlags     prev_state);
417
static void gtk_label_style_updated     (GtkWidget        *widget);
418
static gboolean gtk_label_draw          (GtkWidget        *widget,
419
                                         cairo_t          *cr);
420 421
static gboolean gtk_label_focus         (GtkWidget         *widget,
                                         GtkDirectionType   direction);
Elliot Lee's avatar
Elliot Lee committed
422

423 424 425 426
static void gtk_label_realize           (GtkWidget        *widget);
static void gtk_label_unrealize         (GtkWidget        *widget);
static void gtk_label_map               (GtkWidget        *widget);
static void gtk_label_unmap             (GtkWidget        *widget);
Federico Mena Quintero's avatar
Federico Mena Quintero committed
427 428 429

static gboolean gtk_label_motion            (GtkWidget        *widget,
					     GdkEventMotion   *event);
430 431 432
static gboolean gtk_label_leave_notify      (GtkWidget        *widget,
                                             GdkEventCrossing *event);

433
static void     gtk_label_grab_focus        (GtkWidget        *widget);
434

435 436 437 438 439
static gboolean gtk_label_query_tooltip     (GtkWidget        *widget,
                                             gint              x,
                                             gint              y,
                                             gboolean          keyboard_tip,
                                             GtkTooltip       *tooltip);
440 441 442 443 444

static void gtk_label_set_text_internal          (GtkLabel      *label,
						  gchar         *str);
static void gtk_label_set_label_internal         (GtkLabel      *label,
						  gchar         *str);
445 446 447 448
static gboolean gtk_label_set_use_markup_internal    (GtkLabel  *label,
                                                      gboolean   val);
static gboolean gtk_label_set_use_underline_internal (GtkLabel  *label,
                                                      gboolean   val);
449 450 451
static void gtk_label_set_uline_text_internal    (GtkLabel      *label,
						  const gchar   *str);
static void gtk_label_set_pattern_internal       (GtkLabel      *label,
452 453
				                  const gchar   *pattern,
                                                  gboolean       is_mnemonic);
454
static void gtk_label_set_markup_internal        (GtkLabel      *label,
455 456 457
						  const gchar   *str,
						  gboolean       with_uline);
static void gtk_label_recalculate                (GtkLabel      *label);
458 459
static void gtk_label_hierarchy_changed          (GtkWidget     *widget,
						  GtkWidget     *old_toplevel);
460 461
static void gtk_label_screen_changed             (GtkWidget     *widget,
						  GdkScreen     *old_screen);
462
static gboolean gtk_label_popup_menu             (GtkWidget     *widget);
463

464 465
static void gtk_label_create_window       (GtkLabel *label);
static void gtk_label_destroy_window      (GtkLabel *label);
466 467 468
static void gtk_label_ensure_select_info  (GtkLabel *label);
static void gtk_label_clear_select_info   (GtkLabel *label);
static void gtk_label_update_cursor       (GtkLabel *label);
469
static void gtk_label_clear_layout        (GtkLabel *label);
470
static void gtk_label_ensure_layout       (GtkLabel *label);
471 472 473 474
static void gtk_label_select_region_index (GtkLabel *label,
                                           gint      anchor_index,
                                           gint      end_index);

475 476 477
static void gtk_label_update_active_link  (GtkWidget *widget,
                                           gdouble    x,
                                           gdouble    y);
478

479 480 481 482
static gboolean gtk_label_mnemonic_activate (GtkWidget         *widget,
					     gboolean           group_cycling);
static void     gtk_label_setup_mnemonic    (GtkLabel          *label,
					     guint              last_key);
483 484 485 486 487 488
static void     gtk_label_drag_data_get     (GtkWidget         *widget,
					     GdkDragContext    *context,
					     GtkSelectionData  *selection_data,
					     guint              info,
					     guint              time);

489 490 491 492 493 494 495 496 497 498 499 500 501 502
static void     gtk_label_buildable_interface_init     (GtkBuildableIface *iface);
static gboolean gtk_label_buildable_custom_tag_start   (GtkBuildable     *buildable,
							GtkBuilder       *builder,
							GObject          *child,
							const gchar      *tagname,
							GMarkupParser    *parser,
							gpointer         *data);

static void     gtk_label_buildable_custom_finished    (GtkBuildable     *buildable,
							GtkBuilder       *builder,
							GObject          *child,
							const gchar      *tagname,
							gpointer          user_data);

503

504
static void connect_mnemonics_visible_notify    (GtkLabel   *label);
505 506 507 508
static gboolean      separate_uline_pattern     (const gchar  *str,
                                                 guint        *accel_key,
                                                 gchar       **new_str,
                                                 gchar       **pattern);
509 510


511
/* For selectable labels: */
512 513 514 515 516 517 518
static void gtk_label_move_cursor        (GtkLabel        *label,
					  GtkMovementStep  step,
					  gint             count,
					  gboolean         extend_selection);
static void gtk_label_copy_clipboard     (GtkLabel        *label);
static void gtk_label_select_all         (GtkLabel        *label);
static void gtk_label_do_popup           (GtkLabel        *label,
519
					  const GdkEvent  *event);
520 521 522 523
static gint gtk_label_move_forward_word  (GtkLabel        *label,
					  gint             start);
static gint gtk_label_move_backward_word (GtkLabel        *label,
					  gint             start);
524

525 526
/* For links: */
static void          gtk_label_clear_links      (GtkLabel  *label);
527 528 529
static gboolean      gtk_label_activate_link    (GtkLabel    *label,
                                                 const gchar *uri);
static void          gtk_label_activate_current_link (GtkLabel *label);
530
static GtkLabelLink *gtk_label_get_current_link (GtkLabel  *label);
531 532
static void          emit_activate_link         (GtkLabel     *label,
                                                 GtkLabelLink *link);
533

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
/* Event controller callbacks */
static void   gtk_label_multipress_gesture_pressed  (GtkGestureMultiPress *gesture,
                                                     gint                  n_press,
                                                     gdouble               x,
                                                     gdouble               y,
                                                     GtkLabel             *label);
static void   gtk_label_multipress_gesture_released (GtkGestureMultiPress *gesture,
                                                     gint                  n_press,
                                                     gdouble               x,
                                                     gdouble               y,
                                                     GtkLabel             *label);
static void   gtk_label_drag_gesture_begin          (GtkGestureDrag *gesture,
                                                     gdouble         start_x,
                                                     gdouble         start_y,
                                                     GtkLabel       *label);
static void   gtk_label_drag_gesture_update         (GtkGestureDrag *gesture,
                                                     gdouble         offset_x,
                                                     gdouble         offset_y,
                                                     GtkLabel       *label);

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
static GtkSizeRequestMode gtk_label_get_request_mode                (GtkWidget           *widget);
static void               gtk_label_get_preferred_width             (GtkWidget           *widget,
                                                                     gint                *minimum_size,
                                                                     gint                *natural_size);
static void               gtk_label_get_preferred_height            (GtkWidget           *widget,
                                                                     gint                *minimum_size,
                                                                     gint                *natural_size);
static void               gtk_label_get_preferred_width_for_height  (GtkWidget           *widget,
                                                                     gint                 height,
                                                                     gint                *minimum_width,
                                                                     gint                *natural_width);
static void               gtk_label_get_preferred_height_for_width  (GtkWidget           *widget,
                                                                     gint                 width,
                                                                     gint                *minimum_height,
                                                                     gint                *natural_height);
569 570 571 572 573 574
static void    gtk_label_get_preferred_height_and_baseline_for_width (GtkWidget          *widget,
								      gint                width,
								      gint               *minimum_height,
								      gint               *natural_height,
								      gint               *minimum_baseline,
								      gint               *natural_baseline);
575

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
static void     gtk_label_measure (GtkCssGadget   *gadget,
                                   GtkOrientation  orientation,
                                   int             for_size,
                                   int            *minimum,
                                   int            *natural,
                                   int            *minimum_baseline,
                                   int            *natural_baseline,
                                   gpointer        unused);
static gboolean gtk_label_render  (GtkCssGadget   *gadget,
                                   cairo_t        *cr,
                                   int             x,
                                   int             y,
                                   int             width,
                                   int             height,
                                   gpointer        data);

592 593
static GtkBuildableIface *buildable_parent_iface = NULL;

Matthias Clasen's avatar
Matthias Clasen committed
594
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
595
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_MISC,
596
                         G_ADD_PRIVATE (GtkLabel)
Matthias Clasen's avatar
Matthias Clasen committed
597 598 599
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_label_buildable_interface_init))
G_GNUC_END_IGNORE_DEPRECATIONS
Elliot Lee's avatar
Elliot Lee committed
600

601 602 603 604 605 606 607 608 609 610
static void
add_move_binding (GtkBindingSet  *binding_set,
		  guint           keyval,
		  guint           modmask,
		  GtkMovementStep step,
		  gint            count)
{
  g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
  
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
611
				"move-cursor", 3,
Manish Singh's avatar
Manish Singh committed
612
				G_TYPE_ENUM, step,
613
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
614
				G_TYPE_BOOLEAN, FALSE);
615 616 617

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
618
				"move-cursor", 3,
Manish Singh's avatar
Manish Singh committed
619
				G_TYPE_ENUM, step,
620
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
621
				G_TYPE_BOOLEAN, TRUE);
622 623
}

624
static void
Elliot Lee's avatar
Elliot Lee committed
625 626
gtk_label_class_init (GtkLabelClass *class)
{
627
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
628
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
629
  GtkBindingSet *binding_set;
630

631 632
  gobject_class->set_property = gtk_label_set_property;
  gobject_class->get_property = gtk_label_get_property;
633
  gobject_class->finalize = gtk_label_finalize;
634

635
  widget_class->destroy = gtk_label_destroy;
636
  widget_class->size_allocate = gtk_label_size_allocate;
637
  widget_class->state_flags_changed = gtk_label_state_flags_changed;
638
  widget_class->style_updated = gtk_label_style_updated;
639
  widget_class->query_tooltip = gtk_label_query_tooltip;
640
  widget_class->draw = gtk_label_draw;
641 642 643 644 645
  widget_class->realize = gtk_label_realize;
  widget_class->unrealize = gtk_label_unrealize;
  widget_class->map = gtk_label_map;
  widget_class->unmap = gtk_label_unmap;
  widget_class->motion_notify_event = gtk_label_motion;
646
  widget_class->leave_notify_event = gtk_label_leave_notify;
647
  widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
648
  widget_class->screen_changed = gtk_label_screen_changed;
649
  widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
650
  widget_class->drag_data_get = gtk_label_drag_data_get;
651
  widget_class->grab_focus = gtk_label_grab_focus;
652 653
  widget_class->popup_menu = gtk_label_popup_menu;
  widget_class->focus = gtk_label_focus;
654 655 656 657 658
  widget_class->get_request_mode = gtk_label_get_request_mode;
  widget_class->get_preferred_width = gtk_label_get_preferred_width;
  widget_class->get_preferred_height = gtk_label_get_preferred_height;
  widget_class->get_preferred_width_for_height = gtk_label_get_preferred_width_for_height;
  widget_class->get_preferred_height_for_width = gtk_label_get_preferred_height_for_width;
659
  widget_class->get_preferred_height_and_baseline_for_width = gtk_label_get_preferred_height_and_baseline_for_width;
660 661 662

  class->move_cursor = gtk_label_move_cursor;
  class->copy_clipboard = gtk_label_copy_clipboard;
663 664
  class->activate_link = gtk_label_activate_link;

Matthias Clasen's avatar
Matthias Clasen committed
665 666 667 668 669 670 671 672
  /**
   * GtkLabel::move-cursor:
   * @entry: the object which received the signal
   * @step: the granularity of the move, as a #GtkMovementStep
   * @count: the number of @step units to move
   * @extend_selection: %TRUE if the move should extend the selection
   *
   * The ::move-cursor signal is a
673
   * [keybinding signal][GtkBindingSignal]
Matthias Clasen's avatar
Matthias Clasen committed
674 675 676 677 678
   * which gets emitted when the user initiates a cursor movement.
   * If the cursor is not visible in @entry, this signal causes
   * the viewport to be moved instead.
   *
   * Applications should not connect to it, but may emit it with
679
   * g_signal_emit_by_name() if they need to control the cursor
Matthias Clasen's avatar
Matthias Clasen committed
680 681 682 683 684 685
   * programmatically.
   *
   * The default bindings for this signal come in two variants,
   * the variant with the Shift modifier extends the selection,
   * the variant without the Shift modifer does not.
   * There are too many key combinations to list them all here.
686 687 688
   * - Arrow keys move by individual characters/lines
   * - Ctrl-arrow key combinations move by words/paragraphs
   * - Home/End keys move to the ends of the buffer
Matthias Clasen's avatar
Matthias Clasen committed
689
   */
690
  signals[MOVE_CURSOR] = 
691
    g_signal_new (I_("move-cursor"),
Manish Singh's avatar
Manish Singh committed
692 693 694 695 696 697 698 699 700
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkLabelClass, move_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
		  G_TYPE_NONE, 3,
		  GTK_TYPE_MOVEMENT_STEP,
		  G_TYPE_INT,
		  G_TYPE_BOOLEAN);
Matthias Clasen's avatar
Matthias Clasen committed
701 702 703 704 705 706

   /**
   * GtkLabel::copy-clipboard:
   * @label: the object which received the signal
   *
   * The ::copy-clipboard signal is a
707
   * [keybinding signal][GtkBindingSignal]
Matthias Clasen's avatar
Matthias Clasen committed
708 709 710 711
   * which gets emitted to copy the selection to the clipboard.
   *
   * The default binding for this signal is Ctrl-c.
   */ 
712
  signals[COPY_CLIPBOARD] =
713
    g_signal_new (I_("copy-clipboard"),
Manish Singh's avatar
Manish Singh committed
714 715 716 717
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkLabelClass, copy_clipboard),
		  NULL, NULL,
718
		  NULL,
Manish Singh's avatar
Manish Singh committed
719
		  G_TYPE_NONE, 0);
720
  
Matthias Clasen's avatar
Matthias Clasen committed
721 722 723 724 725 726 727 728 729 730 731 732
  /**
   * GtkLabel::populate-popup:
   * @label: The label on which the signal is emitted
   * @menu: the menu that is being populated
   *
   * The ::populate-popup signal gets emitted before showing the
   * context menu of the label. Note that only selectable labels
   * have context menus.
   *
   * If you need to add items to the context menu, connect
   * to this signal and append your menuitems to the @menu.
   */
733
  signals[POPULATE_POPUP] =
734
    g_signal_new (I_("populate-popup"),
Manish Singh's avatar
Manish Singh committed
735 736 737 738
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkLabelClass, populate_popup),
		  NULL, NULL,
739
		  NULL,
Manish Singh's avatar
Manish Singh committed
740 741 742
		  G_TYPE_NONE, 1,
		  GTK_TYPE_MENU);

743
    /**
744 745
     * GtkLabel::activate-current-link:
     * @label: The label on which the signal was emitted
746
     *
747
     * A [keybinding signal][GtkBindingSignal]
748 749 750 751 752 753 754
     * which gets emitted when the user activates a link in the label.
     *
     * Applications may also emit the signal with g_signal_emit_by_name()
     * if they need to control activation of URIs programmatically.
     *
     * The default bindings for this signal are all forms of the Enter key.
     *
755 756 757
     * Since: 2.18
     */
    signals[ACTIVATE_CURRENT_LINK] =
758
      g_signal_new_class_handler (I_("activate-current-link"),
759
                                  G_TYPE_FROM_CLASS (gobject_class),
760 761 762
                                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                  G_CALLBACK (gtk_label_activate_current_link),
                                  NULL, NULL,
763
                                  NULL,
764 765 766 767 768 769 770 771 772
                                  G_TYPE_NONE, 0);

    /**
     * GtkLabel::activate-link:
     * @label: The label on which the signal was emitted
     * @uri: the URI that is activated
     *
     * The signal which gets emitted to activate a URI.
     * Applications may connect to it to override the default behaviour,
773
     * which is to call gtk_show_uri_on_window().
774
     *
775 776 777 778 779
     * Returns: %TRUE if the link has been activated
     *
     * Since: 2.18
     */
    signals[ACTIVATE_LINK] =
780
      g_signal_new (I_("activate-link"),
781
                    G_TYPE_FROM_CLASS (gobject_class),
782
                    G_SIGNAL_RUN_LAST,
783 784
                    G_STRUCT_OFFSET (GtkLabelClass, activate_link),
                    _gtk_boolean_handled_accumulator, NULL,
785 786
                    _gtk_marshal_BOOLEAN__STRING,
                    G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
787

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
  /**
   * GtkLabel:label:
   *
   * The contents of the label.
   *
   * If the string contains [Pango XML markup][PangoMarkupFormat], you will
   * have to set the #GtkLabel:use-markup property to %TRUE in order for the
   * label to display the markup attributes. See also gtk_label_set_markup()
   * for a convenience function that sets both this property and the
   * #GtkLabel:use-markup property at the same time.
   *
   * If the string contains underlines acting as mnemonics, you will have to
   * set the #GtkLabel:use-underline property to %TRUE in order for the label
   * to display them.
   */
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
  label_props[PROP_LABEL] =
      g_param_spec_string ("label",
                           P_("Label"),
                           P_("The text of the label"),
                           "",
                           GTK_PARAM_READWRITE);

  label_props[PROP_ATTRIBUTES] =
      g_param_spec_boxed ("attributes",
                          P_("Attributes"),
                          P_("A list of style attributes to apply to the text of the label"),
                          PANGO_TYPE_ATTR_LIST,
                          GTK_PARAM_READWRITE);

  label_props[PROP_USE_MARKUP] =
      g_param_spec_boolean ("use-markup",
                            P_("Use markup"),
                            P_("The text of the label includes XML markup. See pango_parse_markup()"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  label_props[PROP_USE_UNDERLINE] =
      g_param_spec_boolean ("use-underline",
                            P_("Use underline"),
                            P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  label_props[PROP_JUSTIFY] =
      g_param_spec_enum ("justify",
                         P_("Justification"),
                         P_("The alignment of the lines in the text of the label relative to each other. This does NOT affect the alignment of the label within its allocation. See GtkLabel:xalign for that"),
                         GTK_TYPE_JUSTIFICATION,
                         GTK_JUSTIFY_LEFT,
                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
838

839 840 841 842 843 844 845 846 847 848
  /**
   * GtkLabel:xalign:
   *
   * The xalign property determines the horizontal aligment of the label text
   * inside the labels size allocation. Compare this to #GtkWidget:halign,
   * which determines how the labels size allocation is positioned in the
   * space available for the label.
   *
   * Since: 3.16
   */
849 850 851 852 853 854 855
  label_props[PROP_XALIGN] =
      g_param_spec_float ("xalign",
                          P_("X align"),
                          P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
                          0.0, 1.0,
                          0.5,
                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
856 857 858 859 860 861 862 863 864 865 866

  /**
   * GtkLabel:yalign:
   *
   * The yalign property determines the vertical aligment of the label text
   * inside the labels size allocation. Compare this to #GtkWidget:valign,
   * which determines how the labels size allocation is positioned in the
   * space available for the label.
   *
   * Since: 3.16
   */
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
  label_props[PROP_YALIGN] =
      g_param_spec_float ("yalign",
                          P_("Y align"),
                          P_("The vertical alignment, from 0 (top) to 1 (bottom)"),
                          0.0, 1.0,
                          0.5,
                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  label_props[PROP_PATTERN] =
      g_param_spec_string ("pattern",
                           P_("Pattern"),
                           P_("A string with _ characters in positions correspond to characters in the text to underline"),
                           NULL,
                           GTK_PARAM_WRITABLE);

  label_props[PROP_WRAP] =
      g_param_spec_boolean ("wrap",
                            P_("Line wrap"),
                            P_("If set, wrap lines if the text becomes too wide"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
888

889 890 891
  /**
   * GtkLabel:wrap-mode:
   *
892 893
   * If line wrapping is on (see the #GtkLabel:wrap property) this controls
   * how the line wrapping is done. The default is %PANGO_WRAP_WORD, which
894
   * means wrap on word boundaries.
895 896 897
   *
   * Since: 2.10
   */
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
  label_props[PROP_WRAP_MODE] =
      g_param_spec_enum ("wrap-mode",
                         P_("Line wrap mode"),
                         P_("If wrap is set, controls how linewrapping is done"),
                         PANGO_TYPE_WRAP_MODE,
                         PANGO_WRAP_WORD,
                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  label_props[PROP_SELECTABLE] =
      g_param_spec_boolean ("selectable",
                            P_("Selectable"),
                            P_("Whether the label text can be selected with the mouse"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  label_props[PROP_MNEMONIC_KEYVAL] =
      g_param_spec_uint ("mnemonic-keyval",
                         P_("Mnemonic key"),
                         P_("The mnemonic accelerator key for this label"),
                         0, G_MAXUINT,
                         GDK_KEY_VoidSymbol,
                         GTK_PARAM_READABLE);

  label_props[PROP_MNEMONIC_WIDGET] =
      g_param_spec_object ("mnemonic-widget",
                           P_("Mnemonic widget"),
                           P_("The widget to be activated when the label's mnemonic key is pressed"),
                           GTK_TYPE_WIDGET,
                           GTK_PARAM_READWRITE);

  label_props[PROP_CURSOR_POSITION] =
      g_param_spec_int ("cursor-position",
                        P_("Cursor Position"),
                        P_("The current position of the insertion cursor in chars"),
                        0, G_MAXINT,
                        0,
                        GTK_PARAM_READABLE);

  label_props[PROP_SELECTION_BOUND] =
      g_param_spec_int ("selection-bound",
                        P_("Selection Bound"),
                        P_("The position of the opposite end of the selection from the cursor in chars"),
                        0, G_MAXINT,
                        0,
                        GTK_PARAM_READABLE);

944 945 946
  /**
   * GtkLabel:ellipsize:
   *
947 948 949
   * The preferred place to ellipsize the string, if the label does
   * not have enough room to display the entire string, specified as a
   * #PangoEllipsizeMode.
950
   *
951 952 953 954
   * Note that setting this property to a value other than
   * %PANGO_ELLIPSIZE_NONE has the side-effect that the label requests
   * only enough space to display the ellipsis "...". In particular, this
   * means that ellipsizing labels do not work well in notebook tabs, unless
955
   * the #GtkNotebook tab-expand child property is set to %TRUE. Other ways
956 957
   * to set a label's width are gtk_widget_set_size_request() and
   * gtk_label_set_width_chars().
958 959 960
   *
   * Since: 2.6
   */
961 962 963 964 965 966 967
  label_props[PROP_ELLIPSIZE] =
      g_param_spec_enum ("ellipsize",
                         P_("Ellipsize"),
                         P_("The preferred place to ellipsize the string, if the label does not have enough room to display the entire string"),
                         PANGO_TYPE_ELLIPSIZE_MODE,
                         PANGO_ELLIPSIZE_NONE,
                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
968 969 970

  /**
   * GtkLabel:width-chars:
971
   *
972
   * The desired width of the label, in characters. If this property is set to
973 974
   * -1, the width will be calculated automatically.
   *
975
   * See the section on [text layout][label-text-layout]
976 977
   * for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
   * determine the width of ellipsized and wrapped labels.
978
   *
979 980
   * Since: 2.6
   **/
981 982 983 984 985 986 987 988
  label_props[PROP_WIDTH_CHARS] =
      g_param_spec_int ("width-chars",
                        P_("Width In Characters"),
                        P_("The desired width of the label, in characters"),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

989 990
  /**
   * GtkLabel:single-line-mode:
991
   *
992 993 994
   * Whether the label is in single line mode. In single line mode,
   * the height of the label does not depend on the actual text, it
   * is always set to ascent + descent of the font. This can be an
995
   * advantage in situations where resizing the label because of text
996 997 998 999
   * changes would be distracting, e.g. in a statusbar.
   *
   * Since: 2.6
   **/
1000 1001 1002 1003 1004 1005
  label_props[PROP_SINGLE_LINE_MODE] =
      g_param_spec_boolean ("single-line-mode",
                            P_("Single Line Mode"),
                            P_("Whether the label is in single line mode"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1006 1007 1008 1009 1010 1011 1012

  /**
   * GtkLabel:angle:
   * 
   * The angle that the baseline of the label makes with the horizontal,
   * in degrees, measured counterclockwise. An angle of 90 reads from
   * from bottom to top, an angle of 270, from top to bottom. Ignored
1013
   * if the label is selectable.
1014 1015 1016
   *
   * Since: 2.6
   **/
1017 1018 1019 1020 1021 1022 1023 1024
  label_props[PROP_ANGLE] =
      g_param_spec_double ("angle",
                           P_("Angle"),
                           P_("Angle at which the label is rotated"),
                           0.0, 360.0,
                           0.0,
                           GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

1025 1026
  /**
   * GtkLabel:max-width-chars:
1027 1028
   *
   * The desired maximum width of the label, in characters. If this property
1029 1030
   * is set to -1, the width will be calculated automatically.
   *
1031
   * See the section on [text layout][label-text-layout]
1032 1033 1034
   * for details of how #GtkLabel:width-chars and #GtkLabel:max-width-chars
   * determine the width of ellipsized and wrapped labels.
   *
1035 1036
   * Since: 2.6
   **/
1037 1038 1039 1040 1041 1042 1043
  label_props[PROP_MAX_WIDTH_CHARS] =
      g_param_spec_int ("max-width-chars",
                        P_("Maximum Width In Characters"),
                        P_("The desired maximum width of the label, in characters"),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1044 1045 1046 1047 1048

  /**
   * GtkLabel:track-visited-links:
   *
   * Set this property to %TRUE to make the label track which links
1049 1050
   * have been visited. It will then apply the #GTK_STATE_FLAG_VISITED
   * when rendering this link, in addition to #GTK_STATE_FLAG_LINK.
1051 1052 1053
   *
   * Since: 2.18
   */
1054 1055 1056 1057 1058 1059
  label_props[PROP_TRACK_VISITED_LINKS] =
      g_param_spec_boolean ("track-visited-links",
                            P_("Track visited links"),
                            P_("Whether visited links should be tracked"),
                            TRUE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070

  /**
   * GtkLabel:lines:
   *
   * The number of lines to which an ellipsized, wrapping label
   * should be limited. This property has no effect if the
   * label is not wrapping or ellipsized. Set this property to
   * -1 if you don't want to limit the number of lines.
   *
   * Since: 3.10
   */
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
  label_props[PROP_LINES] =
      g_param_spec_int ("lines",
                        P_("Number of lines"),
                        P_("The desired number of lines, when ellipsizing a wrapping label"),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);

1081 1082 1083 1084 1085 1086
  /*
   * Key bindings
   */
  binding_set = gtk_binding_set_by_class (class);

  /* Moving the insertion point */
1087
  add_move_binding (binding_set, GDK_KEY_Right, 0,
1088
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1089

1090
  add_move_binding (binding_set, GDK_KEY_Left, 0,
1091 1092
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);

1093
  add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
1094 1095
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
1096
  add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
1097 1098
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
1099
  add_move_binding (binding_set, GDK_KEY_f, GDK_CONTROL_MASK,
1100 1101
		    GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
  
1102
  add_move_binding (binding_set, GDK_KEY_b, GDK_CONTROL_MASK,
1103 1104
		    GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
  
1105
  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
1106 1107
		    GTK_MOVEMENT_WORDS, 1);

1108
  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
1109 1110
		    GTK_MOVEMENT_WORDS, -1);

1111
  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
1112 1113
		    GTK_MOVEMENT_WORDS, 1);

1114
  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
1115 1116
		    GTK_MOVEMENT_WORDS, -1);

1117
  /* select all */
1118
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1119
				"move-cursor", 3,
1120 1121 1122 1123
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, -1,
				G_TYPE_BOOLEAN, FALSE);

1124
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1125
				"move-cursor", 3,
1126 1127 1128 1129
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, 1,
				G_TYPE_BOOLEAN, TRUE);

1130
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1131
				"move-cursor", 3,
1132 1133 1134 1135
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, -1,
				G_TYPE_BOOLEAN, FALSE);

1136
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1137
				"move-cursor", 3,
1138 1139 1140 1141 1142
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, 1,
				G_TYPE_BOOLEAN, TRUE);

  /* unselect all */
1143
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
1144
				"move-cursor", 3,
1145 1146 1147 1148
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, 0,
				G_TYPE_BOOLEAN, FALSE);

1149
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
1150
				"move-cursor", 3,
1151 1152 1153
				G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
				G_TYPE_INT, 0,
				G_TYPE_BOOLEAN, FALSE);
1154

1155
  add_move_binding (binding_set, GDK_KEY_f, GDK_MOD1_MASK,
1156 1157
		    GTK_MOVEMENT_WORDS, 1);

1158
  add_move_binding (binding_set, GDK_KEY_b, GDK_MOD1_MASK,
1159 1160
		    GTK_MOVEMENT_WORDS, -1);

1161
  add_move_binding (binding_set, GDK_KEY_Home, 0,
1162 1163
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);

1164
  add_move_binding (binding_set, GDK_KEY_End, 0,
1165 1166
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);

1167
  add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
1168 1169
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);

1170
  add_move_binding (binding_set, GDK_KEY_KP_End, 0,
1171 1172
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
  
1173
  add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
1174 1175
		    GTK_MOVEMENT_BUFFER_ENDS, -1);

1176
  add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
1177 1178
		    GTK_MOVEMENT_BUFFER_ENDS, 1);

1179
  add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
1180 1181
		    GTK_MOVEMENT_BUFFER_ENDS, -1);

1182
  add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
1183 1184 1185
		    GTK_MOVEMENT_BUFFER_ENDS, 1);

  /* copy */
1186
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
1187
				"copy-clipboard", 0);
1188

1189
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1190
				"activate-current-link", 0);
1191
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1192
				"activate-current-link", 0);
1193
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1194
				"activate-current-link", 0);
1195

1196
  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LABEL_ACCESSIBLE);
1197

1198 1199
  gtk_widget_class_set_css_name (widget_class, "label");

1200 1201 1202 1203 1204
  quark_shortcuts_connected = g_quark_from_static_string ("gtk-label-shortcuts-connected");
  quark_mnemonic_menu = g_quark_from_static_string ("gtk-mnemonic-menu");
  quark_mnemonics_visible_connected = g_quark_from_static_string ("gtk-label-mnemonics-visible-connected");
  quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
  quark_link = g_quark_from_static_string ("link");
Elliot Lee's avatar
Elliot Lee committed
1205 1206
}

1207 1208 1209 1210
static void 
gtk_label_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
1211
			GParamSpec   *pspec)
1212
{
1213
  GtkLabel *label = GTK_LABEL (object);
1214

1215
  switch (prop_id)
1216
    {
1217
    case PROP_LABEL:
1218
      gtk_label_set_label (label, g_value_get_string (value));
1219 1220 1221 1222 1223
      break;
    case PROP_ATTRIBUTES:
      gtk_label_set_attributes (label, g_value_get_boxed (value));
      break;
    case PROP_USE_MARKUP:
1224
      gtk_label_set_use_markup (label, g_value_get_boolean (value));
1225
      break;
1226
    case PROP_USE_UNDERLINE:
1227
      gtk_label_set_use_underline (label, g_value_get_boolean (value));
1228
      break;
1229 1230
    case PROP_JUSTIFY:
      gtk_label_set_justify (label, g_value_get_enum (value));
1231
      break;
1232 1233 1234 1235 1236 1237
    case PROP_PATTERN:
      gtk_label_set_pattern (label, g_value_get_string (value));
      break;
    case PROP_WRAP:
      gtk_label_set_line_wrap (label, g_value_get_boolean (value));
      break;	  
1238 1239 1240
    case PROP_WRAP_MODE:
      gtk_label_set_line_wrap_mode (label, g_value_get_enum (value));
      break;	  
1241 1242
    case PROP_SELECTABLE:
      gtk_label_set_selectable (label, g_value_get_boolean (value));
1243
      break;	  
1244 1245 1246
    case PROP_MNEMONIC_WIDGET:
      gtk_label_set_mnemonic_widget (label, (GtkWidget*) g_value_get_object (value));
      break;
1247 1248 1249
    case PROP_ELLIPSIZE:
      gtk_label_set_ellipsize (label, g_value_get_enum (value));
      break;
1250 1251 1252
    case PROP_WIDTH_CHARS:
      gtk_label_set_width_chars (label, g_value_get_int (value));
      break;
1253 1254 1255
    case PROP_SINGLE_LINE_MODE:
      gtk_label_set_single_line_mode (label, g_value_get_boolean (value));
      break;	  
1256 1257
    case PROP_ANGLE:
      gtk_label_set_angle (label, g_value_get_double (value));
1258 1259 1260 1261
      break;
    case PROP_MAX_WIDTH_CHARS:
      gtk_label_set_max_width_chars (label, g_value_get_int (value));
      break;
1262 1263 1264
    case PROP_TRACK_VISITED_LINKS:
      gtk_label_set_track_visited_links (label, g_value_get_boolean (value));
      break;
1265 1266 1267
    case PROP_LINES:
      gtk_label_set_lines (label, g_value_get_int (value));
      break;
1268 1269 1270 1271 1272 1273
    case PROP_XALIGN:
      gtk_label_set_xalign (label, g_value_get_float (value));
      break;
    case PROP_YALIGN:
      gtk_label_set_yalign (label, g_value_get_float (value));
      break;
Tim Janik's avatar
Tim Janik committed
1274
    default:
1275
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Tim Janik's avatar
Tim Janik committed
1276
      break;
1277 1278 1279
    }
}

1280 1281 1282 1283
static void 
gtk_label_get_property (GObject     *object,
			guint        prop_id,
			GValue      *value,
1284
			GParamSpec  *pspec)
1285
{
1286
  GtkLabel *label = GTK_LABEL (object);
1287
  GtkLabelPrivate *priv = label->priv;
1288

1289
  switch (prop_id)
1290
    {
1291
    case PROP_LABEL:
1292
      g_value_set_string (value, priv->label);
1293 1294
      break;
    case PROP_ATTRIBUTES:
1295
      g_value_set_boxed (value, priv->attrs);
1296 1297
      break;
    case PROP_USE_MARKUP:
1298
      g_value_set_boolean (value, priv->use_markup);
1299 1300
      break;
    case PROP_USE_UNDERLINE:
1301
      g_value_set_boolean (value, priv->use_underline);
1302
      break;
1303
    case PROP_JUSTIFY:
1304
      g_value_set_enum (value, priv->jtype);
1305
      break;
1306
    case PROP_WRAP:
1307
      g_value_set_boolean (value, priv->wrap);
1308
      break;
1309
    case PROP_WRAP_MODE:
1310
      g_value_set_enum (value, priv->wrap_mode);
1311
      break;
1312 1313 1314
    case PROP_SELECTABLE:
      g_value_set_boolean (value, gtk_label_get_selectable (label));
      break;
1315
    case PROP_MNEMONIC_KEYVAL:
1316
      g_value_set_uint (value, priv->mnemonic_keyval);
1317
      break;
1318
    case PROP_MNEMONIC_WIDGET:
Javier Jardón's avatar