- /* GTK - The GIMP Toolkit
+/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <math.h>
#include <string.h>
#include "gtklabel.h"
#include "gdk/gdkkeysyms.h"
ARG_0,
ARG_LABEL,
ARG_PATTERN,
- ARG_JUSTIFY
+ ARG_JUSTIFY,
+ ARG_WRAP
};
typedef struct _GtkLabelULine GtkLabelULine;
{
GdkWChar *beginning;
gint length;
-
+
/* FIXME:
* We need (space,width) only before we've set (x,y), so to save
* memory, these pairs should really be wrapped in a union.
static void gtk_label_finalize (GtkObject *object);
static void gtk_label_size_request (GtkWidget *widget,
GtkRequisition *requisition);
+static void gtk_label_style_set (GtkWidget *widget,
+ GtkStyle *previous_style);
static gint gtk_label_expose (GtkWidget *widget,
GdkEventExpose *event);
-static GtkLabelWord * gtk_label_word_alloc (void);
-static GtkLabelULine * gtk_label_uline_alloc (void);
-static void gtk_label_free_words (GtkLabel *label);
-static void gtk_label_free_ulines (GtkLabelWord *word);
-static gint gtk_label_split_text (GtkLabel * label);
-static void gtk_label_finalize_lines (GtkLabel * label, gint line_width);
-static void gtk_label_finalize_lines_wrap(GtkLabel * label, gint line_width);
+static GtkLabelWord* gtk_label_word_alloc (void);
+static GtkLabelULine* gtk_label_uline_alloc (void);
+static void gtk_label_free_words (GtkLabel *label);
+static void gtk_label_free_ulines (GtkLabelWord *word);
+static gint gtk_label_split_text (GtkLabel *label);
static GtkMiscClass *parent_class = NULL;
-static GMemChunk *word_chunk = 0;
-static GtkLabelWord *free_words = 0;
-static GMemChunk *uline_chunk = 0;
-static GtkLabelULine *free_ulines = 0;
+static GMemChunk *word_chunk = NULL;
+static GMemChunk *uline_chunk = NULL;
GtkType
gtk_label_get_type (void)
(GtkClassInitFunc) NULL,
};
- label_type = gtk_type_unique (gtk_misc_get_type (), &label_info);
+ label_type = gtk_type_unique (GTK_TYPE_MISC, &label_info);
gtk_type_set_chunk_alloc (label_type, 32);
}
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
- parent_class = gtk_type_class (gtk_misc_get_type ());
+ parent_class = gtk_type_class (GTK_TYPE_MISC);
gtk_object_add_arg_type ("GtkLabel::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
gtk_object_add_arg_type ("GtkLabel::pattern", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_PATTERN);
gtk_object_add_arg_type ("GtkLabel::justify", GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFY);
-
+ gtk_object_add_arg_type ("GtkLabel::wrap", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_WRAP);
+
object_class->set_arg = gtk_label_set_arg;
object_class->get_arg = gtk_label_get_arg;
object_class->finalize = gtk_label_finalize;
widget_class->size_request = gtk_label_size_request;
+ widget_class->style_set = gtk_label_style_set;
widget_class->expose_event = gtk_label_expose;
}
guint arg_id)
{
GtkLabel *label;
-
+
label = GTK_LABEL (object);
-
+
switch (arg_id)
{
case ARG_LABEL:
- gtk_label_set_text (label, GTK_VALUE_STRING (*arg) ? GTK_VALUE_STRING (*arg) : "");
+ gtk_label_set_text (label, GTK_VALUE_STRING (*arg));
break;
case ARG_PATTERN:
gtk_label_set_pattern (label, GTK_VALUE_STRING (*arg));
case ARG_JUSTIFY:
gtk_label_set_justify (label, GTK_VALUE_ENUM (*arg));
break;
+ case ARG_WRAP:
+ gtk_label_set_line_wrap (label, GTK_VALUE_BOOL (*arg));
+ break;
default:
break;
}
guint arg_id)
{
GtkLabel *label;
-
+
label = GTK_LABEL (object);
-
+
switch (arg_id)
{
case ARG_LABEL:
case ARG_JUSTIFY:
GTK_VALUE_ENUM (*arg) = label->jtype;
break;
+ case ARG_WRAP:
+ GTK_VALUE_BOOL (*arg) = label->wrap;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
label->label = NULL;
+ label->label_wc = NULL;
+ label->pattern = NULL;
+
label->words = NULL;
+
label->max_width = 0;
label->jtype = GTK_JUSTIFY_CENTER;
- label->pattern = NULL;
label->wrap = FALSE;
-
+
gtk_label_set_text (label, "");
}
GtkWidget*
-gtk_label_new (const char *str)
+gtk_label_new (const gchar *str)
{
GtkLabel *label;
+
+ label = gtk_type_new (GTK_TYPE_LABEL);
- g_return_val_if_fail (str != NULL, NULL);
-
- label = gtk_type_new (gtk_label_get_type ());
-
- gtk_label_set_text (label, str);
-
+ if (str && *str)
+ gtk_label_set_text (label, str);
+
return GTK_WIDGET (label);
}
+static inline void
+gtk_label_set_text_internal (GtkLabel *label,
+ gchar *str,
+ GdkWChar *str_wc)
+{
+ gtk_label_free_words (label);
+
+ g_free (label->label);
+ g_free (label->label_wc);
+
+ label->label = str;
+ label->label_wc = str_wc;
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
+}
+
void
-gtk_label_set_text (GtkLabel *label,
- const char *str)
+gtk_label_set_text (GtkLabel *label,
+ const gchar *str)
{
- guint len;
- guint wc_len;
+ GdkWChar *str_wc;
+ gint len;
+ gint wc_len;
- g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
- g_return_if_fail (str != NULL);
-
- if (label->label)
- g_free (label->label);
- label->label = g_strdup (str);
-
- /* Convert text to wide characters */
- len = strlen (str);
- label->label_wc = g_new (GdkWChar, len + 1);
- wc_len = gdk_mbstowcs (label->label_wc, str, len + 1);
- label->label_wc[wc_len] = '\0';
-
- gtk_label_free_words (label);
+ if (!str)
+ str = "";
- if (GTK_WIDGET_VISIBLE (label))
+ if (!label->label || strcmp (label->label, str))
{
- if (GTK_WIDGET_MAPPED (label))
- gtk_widget_queue_clear (GTK_WIDGET (label));
-
- gtk_widget_queue_resize (GTK_WIDGET (label));
+ /* Convert text to wide characters */
+ len = strlen (str);
+ str_wc = g_new (GdkWChar, len + 1);
+ wc_len = gdk_mbstowcs (str_wc, str, len + 1);
+ if (wc_len >= 0)
+ {
+ str_wc[wc_len] = '\0';
+ gtk_label_set_text_internal (label, g_strdup (str), str_wc);
+ }
+ else
+ g_free (str_wc);
}
}
gtk_label_set_pattern (GtkLabel *label,
const gchar *pattern)
{
- g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
- if (label->pattern)
- g_free (label->pattern);
- label->pattern = g_strdup (pattern);
+ gtk_label_free_words (label);
- if (GTK_WIDGET_VISIBLE (label))
- {
- if (GTK_WIDGET_MAPPED (label))
- gtk_widget_queue_clear (GTK_WIDGET (label));
-
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
+ g_free (label->pattern);
+ label->pattern = g_strdup (pattern);
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
}
void
-gtk_label_set_justify (GtkLabel *label, GtkJustification jtype)
+gtk_label_set_justify (GtkLabel *label,
+ GtkJustification jtype)
{
- g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
-
+ g_return_if_fail (jtype >= GTK_JUSTIFY_LEFT && jtype <= GTK_JUSTIFY_FILL);
+
if ((GtkJustification) label->jtype != jtype)
{
- if ((label->jtype == GTK_JUSTIFY_FILL) ||
- (jtype == GTK_JUSTIFY_FILL))
- /* FIXME: think about this a little */
- gtk_label_free_words (label);
-
- label->jtype = jtype;
+ gtk_label_free_words (label);
- if (GTK_WIDGET_VISIBLE (label))
- {
- if (GTK_WIDGET_MAPPED (label))
- gtk_widget_queue_clear (GTK_WIDGET (label));
-
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
+ label->jtype = jtype;
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
}
}
void
-gtk_label_set_line_wrap (GtkLabel *label, gboolean wrap)
+gtk_label_set_line_wrap (GtkLabel *label,
+ gboolean wrap)
{
- g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
+
+ wrap = wrap != FALSE;
+
+ if (label->wrap != wrap)
+ {
+ gtk_label_free_words (label);
- if (label->wrap != wrap) {
- if (GTK_WIDGET_VISIBLE (label))
- {
- if (GTK_WIDGET_MAPPED (label))
- gtk_widget_queue_clear (GTK_WIDGET (label));
-
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
- label->wrap = wrap;
- }
+ label->wrap = wrap;
+
+ gtk_widget_queue_resize (GTK_WIDGET (label));
+ }
}
void
-gtk_label_get (GtkLabel *label,
- char **str)
+gtk_label_get (GtkLabel *label,
+ gchar **str)
{
g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
g_return_if_fail (str != NULL);
-
+
*str = label->label;
}
label = GTK_LABEL (object);
g_free (label->label);
- if (label->pattern)
- g_free (label->pattern);
+ g_free (label->label_wc);
+ g_free (label->pattern);
+
gtk_label_free_words (label);
- (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
+
+ GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
-static GtkLabelWord *
-gtk_label_word_alloc ()
+static GtkLabelULine*
+gtk_label_uline_alloc (void)
{
- GtkLabelWord * word;
+ GtkLabelULine *uline;
+
+ if (!uline_chunk)
+ uline_chunk = g_mem_chunk_create (GtkLabelWord, 32, G_ALLOC_AND_FREE);
- if (!word_chunk)
- {
- word_chunk = g_mem_chunk_new ("GtkLabelWord chunk",
- sizeof (GtkLabelWord),
- 32 * sizeof (GtkLabelWord),
- G_ALLOC_ONLY);
- }
+ uline = g_chunk_new0 (GtkLabelULine, uline_chunk);
- if (free_words)
- {
- word = free_words;
- free_words = word->next;
- }
- else
- {
- word = g_mem_chunk_alloc (word_chunk);
- }
-
- word->next = 0;
- word->uline = 0;
- return word;
+ uline->next = NULL;
+
+ return uline;
}
static void
-gtk_label_free_words (GtkLabel * label)
+gtk_label_free_ulines (GtkLabelWord *word)
{
- GtkLabelWord * last;
-
- if (label->words)
+ while (word->uline)
{
- for (last = label->words; last->next != 0; last = last->next)
- gtk_label_free_ulines (label->words);
- last->next = free_words;
- free_words = label->words;
- label->words = 0;
+ GtkLabelULine *uline = word->uline;
+
+ word->uline = uline->next;
+ g_chunk_free (uline, uline_chunk);
}
}
-static GtkLabelULine *
-gtk_label_uline_alloc ()
-{
- GtkLabelULine * uline;
- if (!uline_chunk)
- {
- uline_chunk = g_mem_chunk_new ("GtkLabelWord chunk",
- sizeof (GtkLabelULine),
- 32 * sizeof (GtkLabelULine),
- G_ALLOC_ONLY);
- }
+static GtkLabelWord*
+gtk_label_word_alloc (void)
+{
+ GtkLabelWord * word;
- if (free_ulines)
- {
- uline = free_ulines;
- free_ulines = uline->next;
- }
- else
- {
- uline = g_mem_chunk_alloc (uline_chunk);
- }
-
- uline->next = 0;
- return uline;
+ if (!word_chunk)
+ word_chunk = g_mem_chunk_create (GtkLabelWord, 32, G_ALLOC_AND_FREE);
+
+ word = g_chunk_new0 (GtkLabelWord, word_chunk);
+
+ word->beginning = NULL;
+ word->next = NULL;
+ word->uline = NULL;
+
+ return word;
}
static void
-gtk_label_free_ulines (GtkLabelWord *word)
+gtk_label_free_words (GtkLabel *label)
{
- GtkLabelULine *last;
- if (word->uline)
+ while (label->words)
{
- for (last = word->uline; last->next != 0; last = last->next)
- ;
- last->next = free_ulines;
- free_ulines = word->uline;
- word->uline = 0;
+ GtkLabelWord *word = label->words;
+
+ label->words = word->next;
+
+ gtk_label_free_ulines (word);
+
+ g_chunk_free (word, word_chunk);
}
}
-
+
static gint
-gtk_label_split_text (GtkLabel * label)
+gtk_label_split_text (GtkLabel *label)
{
GtkLabelWord *word, **tailp;
gint space_width, line_width, max_line_width;
GdkWChar *str, *p;
- g_return_val_if_fail (GTK_WIDGET (label)->style->font != 0, 0);
-
gtk_label_free_words (label);
- if (label->label == 0)
- return 0;
+ if (label->label == NULL)
+ return 0;
- /*
- * Split text at new-lines.
- */
+ /* Split text at new-lines. */
space_width = gdk_string_width (GTK_WIDGET (label)->style->font, " ");
-
+
line_width = 0;
max_line_width = 0;
tailp = &label->words;
str = label->label_wc;
+
while (*str)
{
word = gtk_label_word_alloc ();
-
- if ((str == label->label_wc) || (str[-1] == '\n'))
+
+ if (str == label->label_wc || str[-1] == '\n')
{
/* Paragraph break */
word->space = 0;
-
+
max_line_width = MAX (line_width, max_line_width);
line_width = 0;
}
/* Regular inter-word space */
word->space = space_width;
}
-
+
word->beginning = str;
word->length = 0;
p = word->beginning;
- while (*p && (*p != '\n'))
+ while (*p && *p != '\n')
{
word->length++;
p++;
}
-
+
word->width = gdk_text_width_wc (GTK_WIDGET (label)->style->font, str, word->length);
-
+
str += word->length;
if (*str)
- str++;
+ str++;
line_width += word->space + word->width;
-
+
*tailp = word;
tailp = &word->next;
}
-
+
+ /* Add an empty word to represent an empty line
+ */
+ if (str == label->label_wc || str[-1] == '\n')
+ {
+ word = gtk_label_word_alloc ();
+
+ word->space = 0;
+ word->beginning = str;
+ word->length = 0;
+ word->width = 0;
+
+ *tailp = word;
+ tailp = &word->next;
+ }
+
return MAX (line_width, max_line_width);
}
+/* this needs to handle white space better. */
static gint
-gtk_label_split_text_wrapped (GtkLabel * label)
+gtk_label_split_text_wrapped (GtkLabel *label)
{
- /* this needs to handle white space better. */
GtkLabelWord *word, **tailp;
gint space_width, line_width, max_line_width;
GdkWChar *str, *p;
- g_return_val_if_fail (GTK_WIDGET (label)->style->font != 0, 0);
-
gtk_label_free_words (label);
- if (label->label == 0)
- return 0;
+ if (label->label == NULL)
+ return 0;
- /*
- * Split text at new-lines. (Or at spaces in the case of paragraphs).
- */
+ /* Split text at new-lines. (Or at spaces in the case of paragraphs). */
space_width = gdk_string_width (GTK_WIDGET (label)->style->font, " ");
-
+
line_width = 0;
max_line_width = 0;
tailp = &label->words;
while (*str)
{
word = gtk_label_word_alloc ();
-
+
if (str == label->label_wc || str[-1] == '\n')
{
/* Paragraph break */
word->space = 0;
-
+
max_line_width = MAX (line_width, max_line_width);
line_width = 0;
}
else if (str[0] == ' ')
{
gint nspaces = 0;
-
+
while (str[0] == ' ')
{
nspaces++;
str++;
}
-
+
if (label->jtype == GTK_JUSTIFY_FILL)
word->space = (space_width * 3 + 1) / 2;
else
- word->space += space_width * nspaces;
+ word->space = space_width * nspaces;
}
else
{
/* Regular inter-word space */
word->space = space_width;
}
-
+
word->beginning = str;
word->length = 0;
p = word->beginning;
- while (*p && (!gdk_iswspace (*p)))
+ while (*p && !gdk_iswspace (*p))
{
word->length++;
p++;
}
word->width = gdk_text_width_wc (GTK_WIDGET (label)->style->font, str, word->length);
-
+
str += word->length;
if (*str)
- str++;
+ str++;
line_width += word->space + word->width;
-
+
*tailp = word;
tailp = &word->next;
}
-
+
return MAX (line_width, max_line_width);
}
-/*
- * gtk_label_pick_width
+/* gtk_label_pick_width
*
* Split paragraphs, trying to make each line at least min_width,
* and trying even harder to make each line no longer than max_width.
* short final line.)
*/
static gint
-gtk_label_pick_width (GtkLabel * label, gint min_width, gint max_width)
+gtk_label_pick_width (GtkLabel *label,
+ gint min_width,
+ gint max_width)
{
GtkLabelWord *word;
gint width, line_width;
g_return_val_if_fail (label->wrap, min_width);
-
+
line_width = 0;
width = 0;
for (word = label->words; word; word = word->next)
}
line_width += word->space + word->width;
}
-
+
return MAX (width, line_width);
}
-/*
- * Here, we finalize the lines.
+/* Here, we finalize the lines.
* This is only for non-wrap labels. Wrapped labels
* use gtk_label_finalize_wrap instead.
*/
static void
-gtk_label_finalize_lines (GtkLabel * label, gint line_width)
+gtk_label_finalize_lines (GtkLabel *label,
+ GtkRequisition *requisition,
+ gint max_line_width)
{
- GtkLabelWord * line;
+ GtkLabelWord *line;
gint y, baseline_skip, y_max;
gint i, j;
gchar *ptrn;
g_return_if_fail (!label->wrap);
ptrn = label->pattern;
-
+
y = 0;
- baseline_skip = GTK_WIDGET (label)->style->font->ascent + GTK_WIDGET (label)->style->font->descent + 2;
+ baseline_skip = (GTK_WIDGET (label)->style->font->ascent +
+ GTK_WIDGET (label)->style->font->descent + 2);
for (line = label->words; line; line = line->next)
{
if (label->jtype == GTK_JUSTIFY_CENTER)
- line->x = (line_width - line->width) / 2;
+ line->x = (max_line_width - line->width) / 2;
else if (label->jtype == GTK_JUSTIFY_RIGHT)
- line->x = line_width - line->width;
+ line->x = max_line_width - line->width;
else
- line->x = 0;
-
+ line->x = 0;
+
line->y = y + GTK_WIDGET (label)->style->font->ascent + 1;
y_max = 0;
-
+
/* now we deal with the underline stuff; */
- if (ptrn && (ptrn[0] != '\0'))
+ if (ptrn && ptrn[0] != '\0')
{
- for (i=0;i<line->length;i++)
+ for (i = 0; i < line->length; i++)
{
if (ptrn[i] == '\0')
break;
gint width;
gint offset;
GtkLabelULine *uline;
-
- for (j=i+1;j<line->length;j++)
+
+ for (j = i + 1; j < line->length; j++)
{
if (ptrn[j] == '\0')
break;
else if (ptrn[j] == ' ')
break;
}
- /*
- * good. Now we have an underlined segment.
+
+ /* good. Now we have an underlined segment.
* let's measure it and record it.
*/
offset = gdk_text_width_wc (GTK_WIDGET (label)->style->font,
y += (baseline_skip + y_max);
}
- label->max_width = line_width;
- GTK_WIDGET (label)->requisition.width = line_width + 2 * label->misc.xpad;
- GTK_WIDGET (label)->requisition.height = y + 2 * label->misc.ypad;
+ label->max_width = max_line_width;
+ requisition->width = max_line_width + 2 * label->misc.xpad;
+ requisition->height = y + 2 * label->misc.ypad;
}
/* this finalizes word-wrapped words */
static void
-gtk_label_finalize_lines_wrap (GtkLabel * label, gint line_width)
+gtk_label_finalize_lines_wrap (GtkLabel *label,
+ GtkRequisition *requisition,
+ gint max_line_width)
{
GtkLabelWord *word, *line, *next_line;
GtkWidget *widget;
gint x, y, space, extra_width, add_space, baseline_skip;
g_return_if_fail (label->wrap);
-
+
ptrn = label->pattern;
y = 0;
- baseline_skip = GTK_WIDGET (label)->style->font->ascent + GTK_WIDGET (label)->style->font->descent + 1;
+ baseline_skip = (GTK_WIDGET (label)->style->font->ascent +
+ GTK_WIDGET (label)->style->font->descent + 1);
for (line = label->words; line != 0; line = next_line)
{
space = 0;
- extra_width = line_width - line->width;
+ extra_width = max_line_width - line->width;
for (next_line = line->next; next_line; next_line = next_line->next)
{
if (next_line->space == 0)
- break; /* New paragraph */
+ break; /* New paragraph */
if (next_line->space + next_line->width > extra_width)
- break;
+ break;
extra_width -= next_line->space + next_line->width;
space += next_line->space;
}
-
+
line->x = 0;
line->y = y + GTK_WIDGET (label)->style->font->ascent + 1;
x = line->width;
add_space = 0;
-
+
for (word = line->next; word != next_line; word = word->next)
{
if (next_line && next_line->space)
word->y = line->y;
x = word->x + word->width;
}
-
+
y += (baseline_skip);
}
-
- label->max_width = line_width;
+
+ label->max_width = max_line_width;
widget = GTK_WIDGET (label);
- widget->requisition.width = line_width + 2 * label->misc.xpad;
- widget->requisition.height = y + 2 * label->misc.ypad + 1;
+ requisition->width = max_line_width + 2 * label->misc.xpad;
+ requisition->height = y + 2 * label->misc.ypad + 1;
}
-
+
static void
gtk_label_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkLabel *label;
- g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_LABEL (widget));
g_return_if_fail (requisition != NULL);
-
+
label = GTK_LABEL (widget);
/*
* Too much of a pain to detect all these case, so always re-fill. I
* don't think it's really that slow.
*/
-
+
if (label->wrap)
{
GtkWidgetAuxInfo *aux_info;
aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
if (aux_info && aux_info->width > 0)
{
- label->max_width = MAX(aux_info->width - 2 * label->misc.xpad, 1);
+ label->max_width = MAX (aux_info->width - 2 * label->misc.xpad, 1);
gtk_label_split_text_wrapped (label);
}
else
{
label->max_width = gdk_string_width (GTK_WIDGET (label)->style->font,
- "This is a good enough length for any line to have.");
+ "This is a good enough length for any line to have.");
label->max_width = MIN (label->max_width, (gdk_screen_width () + 1) / 2);
label->max_width = MIN (label->max_width, longest_paragraph);
if (longest_paragraph > 0)
nlines = (longest_paragraph + label->max_width - 1) / label->max_width;
perfect_width = (longest_paragraph + nlines - 1) / nlines;
label->max_width = gtk_label_pick_width (label,
- perfect_width,
- label->max_width);
+ perfect_width,
+ label->max_width);
}
}
- gtk_label_finalize_lines_wrap (label, label->max_width);
+ gtk_label_finalize_lines_wrap (label, requisition, label->max_width);
}
- else if (label->words == 0)
+ else if (!label->words)
{
label->max_width = gtk_label_split_text (label);
- gtk_label_finalize_lines (label, label->max_width);
-
+ gtk_label_finalize_lines (label, requisition, label->max_width);
}
+}
+
+static void
+gtk_label_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ GtkLabel *label;
- if (requisition != &widget->requisition)
- *requisition = widget->requisition;
+ g_return_if_fail (GTK_IS_LABEL (widget));
+
+ label = GTK_LABEL (widget);
+
+ /* Clear the list of words so that they are recomputed on
+ * size_request
+ */
+ if (previous_style && label->words)
+ gtk_label_free_words (label);
}
+
static void
-gtk_label_paint_word (GtkLabel *label,
- gint x,
- gint y,
+gtk_label_paint_word (GtkLabel *label,
+ gint x,
+ gint y,
GtkLabelWord *word,
GdkRectangle *area)
{
GtkWidget *widget = GTK_WIDGET (label);
GtkLabelULine *uline;
gchar *tmp_str;
-
+
tmp_str = gdk_wcstombs (word->beginning);
- gtk_paint_string (widget->style, widget->window, widget->state,
- area, widget, "label",
- x + word->x,
- y + word->y,
- tmp_str);
- g_free (tmp_str);
-
- for (uline = word->uline;uline;uline = uline->next)
+ if (tmp_str)
+ {
+ gtk_paint_string (widget->style, widget->window, widget->state,
+ area, widget, "label",
+ x + word->x,
+ y + word->y,
+ tmp_str);
+ g_free (tmp_str);
+ }
+
+ for (uline = word->uline; uline; uline = uline->next)
gtk_paint_hline (widget->style, widget->window,
widget->state, area,
widget, "label",
- x + uline->x1, x +uline->x2, y + uline->y);
-
-
+ x + uline->x1, x + uline->x2, y + uline->y);
}
+
static gint
gtk_label_expose (GtkWidget *widget,
GdkEventExpose *event)
GtkMisc *misc;
GtkLabelWord *word;
gint x, y;
-
- g_return_val_if_fail (widget != NULL, FALSE);
+
g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
-
- if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
+ label = GTK_LABEL (widget);
+
+ if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
+ label->label && (*label->label != '\0'))
{
- label = GTK_LABEL (widget);
misc = GTK_MISC (widget);
-
- g_return_val_if_fail (label->words != 0 || label->label == 0, FALSE);
-
-
+
/*
* GC Clipping
*/
gdk_gc_set_clip_rectangle (widget->style->white_gc, &event->area);
gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state], &event->area);
+
+ x = floor (widget->allocation.x + (gint)misc->xpad
+ + (((gint)widget->allocation.width -
+ (gint)label->max_width - 2 * (gint)misc->xpad)
+ * misc->xalign) + 0.5);
+
+ y = floor (widget->allocation.y + (gint)misc->ypad
+ + (((gint)widget->allocation.height
+ - (gint)widget->requisition.height)
+ * misc->yalign) + 0.5);
- x = widget->allocation.x + misc->xpad +
- (widget->allocation.width - label->max_width)
- * misc->xalign + 0.5;
-
- y = (widget->allocation.y
- + (widget->allocation.height
- - widget->requisition.height) * misc->yalign
- + misc->ypad + 0.5);
for (word = label->words; word; word = word->next)
{
gchar save = word->beginning[word->length];
gtk_label_paint_word (label, x, y, word, &event->area);
word->beginning[word->length] = save;
}
-
+
gdk_gc_set_clip_mask (widget->style->white_gc, NULL);
gdk_gc_set_clip_mask (widget->style->fg_gc[widget->state], NULL);
}
+
return TRUE;
}
+
guint
-gtk_label_parse_uline (GtkLabel *label,
- const gchar *string)
+gtk_label_parse_uline (GtkLabel *label,
+ const gchar *string)
{
guint accel_key = GDK_VoidSymbol;
- GdkWChar *p, *q;
+ GdkWChar *p, *q, *string_wc;
gchar *r;
gchar *pattern;
-
- gint length;
+ gint length, wc_length;
gboolean underscore;
+
+ g_return_val_if_fail (GTK_IS_LABEL (label), GDK_VoidSymbol);
+ g_return_val_if_fail (string != NULL, GDK_VoidSymbol);
+ /* Convert text to wide characters */
length = strlen (string);
+ string_wc = g_new (GdkWChar, length + 1);
+ wc_length = gdk_mbstowcs (string_wc, string, length + 1);
+ if (wc_length < 0)
+ {
+ g_free (string_wc);
+ return GDK_VoidSymbol;
+ }
+
+ string_wc[wc_length] = '\0';
- gtk_label_set_text (label, string);
pattern = g_new (gchar, length+1);
-
+
underscore = FALSE;
-
- p = q = label->label_wc;
+
+ p = q = string_wc;
r = pattern;
-
+
while (*p)
{
if (underscore)
if (accel_key == GDK_VoidSymbol)
accel_key = gdk_keyval_to_lower (*p);
}
-
+
*q++ = *p;
underscore = FALSE;
}
}
*q = 0;
*r = 0;
-
+
+ gtk_label_set_text_internal (label, gdk_wcstombs (string_wc), string_wc);
gtk_label_set_pattern (label, pattern);
g_free (pattern);
-
+
return accel_key;
}