aboutsummaryrefslogtreecommitdiffstats
path: root/lib/widgets/ephy-ellipsizing-label.c
diff options
context:
space:
mode:
authorChristian Persch <chpe@cvs.gnome.org>2004-08-08 23:33:26 +0800
committerChristian Persch <chpe@src.gnome.org>2004-08-08 23:33:26 +0800
commit10256b2ff6a49d5283ca281ea0068e1acbe7686e (patch)
treed6738bead4c91e36a16a2a0e325749d216711cfe /lib/widgets/ephy-ellipsizing-label.c
parentd368e97a37dbd9ed2163f0a446fa3723ed57c732 (diff)
downloadgsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar.gz
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar.bz2
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar.lz
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar.xz
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.tar.zst
gsoc2013-epiphany-10256b2ff6a49d5283ca281ea0068e1acbe7686e.zip
R lib/widgets/ephy-ellipsizing-label.c: R
2004-08-08 Christian Persch <chpe@cvs.gnome.org> * lib/ephy-marshal.list: * lib/widgets/Makefile.am: R lib/widgets/ephy-ellipsizing-label.c: R lib/widgets/ephy-ellipsizing-label.h: A lib/widgets/ephy-label.c: A lib/widgets/ephy-label.h: * src/ephy-notebook.c: (sync_label), (build_tab_label): * src/pdm-dialog.c: (show_cookies_properties): * src/prefs-dialog.c: (create_download_path_label), (download_path_response_cb): Kill our ellipsizing label implementation, and import GtkLabel into our prefix. * configure.in: Depend on pango 1.5.1 for ellipsisation support.
Diffstat (limited to 'lib/widgets/ephy-ellipsizing-label.c')
-rw-r--r--lib/widgets/ephy-ellipsizing-label.c780
1 files changed, 0 insertions, 780 deletions
diff --git a/lib/widgets/ephy-ellipsizing-label.c b/lib/widgets/ephy-ellipsizing-label.c
deleted file mode 100644
index 151ff744d..000000000
--- a/lib/widgets/ephy-ellipsizing-label.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* eel-ellipsizing-label.c: Subclass of GtkLabel that ellipsizes the text.
-
- Copyright (C) 2001 Eazel, Inc.
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more priv.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: John Sullivan <sullivan@eazel.com>,
- Marco Pesenti Gritti <marco@it.gnome.org> Markup support
-
- $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ephy-ellipsizing-label.h"
-
-#include <string.h>
-
-struct EphyEllipsizingLabelPrivate
-{
- char *full_text;
-
- EphyEllipsizeMode mode;
-};
-
-static void ephy_ellipsizing_label_class_init (EphyEllipsizingLabelClass *class);
-static void ephy_ellipsizing_label_init (EphyEllipsizingLabel *label);
-
-static GObjectClass *parent_class = NULL;
-
-static int
-ephy_strcmp (const char *string_a, const char *string_b)
-{
- return strcmp (string_a == NULL ? "" : string_a,
- string_b == NULL ? "" : string_b);
-}
-
-static gboolean
-ephy_str_is_equal (const char *string_a, const char *string_b)
-{
- return ephy_strcmp (string_a, string_b) == 0;
-}
-
-#define ELLIPSIS "..."
-
-/* Caution: this is an _expensive_ function */
-static int
-measure_string_width (const char *string,
- PangoLayout *layout,
- gboolean markup)
-{
- int width;
-
- if (markup)
- {
- pango_layout_set_markup (layout, string, -1);
- }
- else
- {
- pango_layout_set_text (layout, string, -1);
- }
-
- pango_layout_get_pixel_size (layout, &width, NULL);
-
- return width;
-}
-
-/* this is also plenty slow */
-static void
-compute_character_widths (const char *string,
- PangoLayout *layout,
- int *char_len_return,
- int **widths_return,
- int **cuts_return,
- gboolean markup)
-{
- int *widths;
- int *offsets;
- int *cuts;
- int char_len;
- int byte_len;
- const char *p;
- const char *nm_string;
- int i;
- PangoLayoutIter *iter;
- PangoLogAttr *attrs;
-
-#define BEGINS_UTF8_CHAR(x) (((x) & 0xc0) != 0x80)
-
- if (markup)
- {
- pango_layout_set_markup (layout, string, -1);
- }
- else
- {
- pango_layout_set_text (layout, string, -1);
- }
-
- nm_string = pango_layout_get_text (layout);
-
- char_len = g_utf8_strlen (nm_string, -1);
- byte_len = strlen (nm_string);
-
- widths = g_new (int, char_len);
- offsets = g_new (int, byte_len);
-
- /* Create a translation table from byte index to char offset */
- p = nm_string;
- i = 0;
- while (*p) {
- int byte_index = p - nm_string;
-
- if (BEGINS_UTF8_CHAR (*p)) {
- offsets[byte_index] = i;
- ++i;
- } else {
- offsets[byte_index] = G_MAXINT; /* segv if we try to use this */
- }
-
- ++p;
- }
-
- /* Now fill in the widths array */
- iter = pango_layout_get_iter (layout);
-
- do {
- PangoRectangle extents;
- int byte_index;
-
- byte_index = pango_layout_iter_get_index (iter);
-
- if (byte_index < byte_len) {
- pango_layout_iter_get_char_extents (iter, &extents);
-
- g_assert (BEGINS_UTF8_CHAR (nm_string[byte_index]));
- g_assert (offsets[byte_index] < char_len);
-
- widths[offsets[byte_index]] = PANGO_PIXELS (extents.width);
- }
-
- } while (pango_layout_iter_next_char (iter));
-
- pango_layout_iter_free (iter);
-
- g_free (offsets);
-
- *widths_return = widths;
-
- /* Now compute character offsets that are legitimate places to
- * chop the string
- */
- attrs = g_new (PangoLogAttr, char_len + 1);
-
- pango_get_log_attrs (nm_string, byte_len, -1,
- pango_context_get_language (
- pango_layout_get_context (layout)),
- attrs,
- char_len + 1);
-
- cuts = g_new (int, char_len);
- i = 0;
- while (i < char_len) {
- cuts[i] = attrs[i].is_cursor_position;
-
- ++i;
- }
-
- g_free (attrs);
-
- *cuts_return = cuts;
-
- *char_len_return = char_len;
-}
-
-typedef struct
-{
- GString *string;
- int start_offset;
- int end_offset;
- int position;
-} EllipsizeStringData;
-
-static void
-start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- EllipsizeStringData *data = (EllipsizeStringData *)user_data;
- int i;
-
- g_string_append_c (data->string, '<');
- g_string_append (data->string, element_name);
-
- for (i = 0; attribute_names[i] != NULL; i++)
- {
- g_string_append_c (data->string, ' ');
- g_string_append (data->string, attribute_names[i]);
- g_string_append (data->string, "=\"");
- g_string_append (data->string, attribute_values[i]);
- g_string_append_c (data->string, '"');
- }
-
- g_string_append_c (data->string, '>');
-}
-
-static void
-end_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- EllipsizeStringData *data = (EllipsizeStringData *)user_data;
-
- g_string_append (data->string, "</");
- g_string_append (data->string, element_name);
- g_string_append_c (data->string, '>');
-}
-
-static void
-append_ellipsized_text (const char *text,
- EllipsizeStringData *data,
- int text_len)
-{
- int position;
- int new_position;
-
- position = data->position;
- new_position = data->position + text_len;
-
- if (position > data->start_offset &&
- new_position < data->end_offset)
- {
- return;
- }
- else if ((position < data->start_offset &&
- new_position < data->start_offset) ||
- (position > data->end_offset &&
- new_position > data->end_offset))
- {
- g_string_append (data->string,
- text);
- }
- else if (position <= data->start_offset &&
- new_position >= data->end_offset)
- {
- if (position < data->start_offset)
- {
- g_string_append_len (data->string,
- text,
- data->start_offset -
- position);
- }
-
- g_string_append (data->string,
- ELLIPSIS);
-
- if (new_position > data->end_offset)
- {
- g_string_append_len (data->string,
- text + data->end_offset -
- position,
- position + text_len -
- data->end_offset);
- }
- }
-
- data->position = new_position;
-}
-
-static void
-text_handler (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **error)
-{
- EllipsizeStringData *data = (EllipsizeStringData *)user_data;
-
- append_ellipsized_text (text, data, text_len);
-}
-
-static GMarkupParser pango_markup_parser = {
- start_element_handler,
- end_element_handler,
- text_handler,
- NULL,
- NULL
-};
-
-static char *
-ellipsize_string (const char *string,
- int start_offset,
- int end_offset,
- gboolean markup)
-{
- GString *str;
- EllipsizeStringData data;
- char *result;
- GMarkupParseContext *c;
-
- str = g_string_new (NULL);
- data.string = str;
- data.start_offset = start_offset;
- data.end_offset = end_offset;
- data.position = 0;
-
- if (markup)
- {
- c = g_markup_parse_context_new (&pango_markup_parser,
- 0, &data, NULL);
- g_markup_parse_context_parse (c, string, -1, NULL);
- g_markup_parse_context_free (c);
- }
- else
- {
- append_ellipsized_text (string, &data,
- g_utf8_strlen (string, -1));
- }
-
- result = g_string_free (str, FALSE);
-
- return result;
-}
-
-static char *
-ephy_string_ellipsize_start (const char *string, PangoLayout *layout, int width, gboolean markup)
-{
- int resulting_width;
- int *cuts;
- int *widths;
- int char_len;
- int truncate_offset;
- int bytes_end;
-
- /* Zero-length string can't get shorter - catch this here to
- * avoid expensive calculations
- */
- if (*string == '\0')
- return g_strdup ("");
-
- /* I'm not sure if this short-circuit is a net win; it might be better
- * to just dump this, and always do the compute_character_widths() etc.
- * down below.
- */
- resulting_width = measure_string_width (string, layout, markup);
-
- if (resulting_width <= width) {
- /* String is already short enough. */
- return g_strdup (string);
- }
-
- /* Remove width of an ellipsis */
- width -= measure_string_width (ELLIPSIS, layout, markup);
-
- if (width < 0) {
- /* No room even for an ellipsis. */
- return g_strdup ("");
- }
-
- /* Our algorithm involves removing enough chars from the string to bring
- * the width to the required small size. However, due to ligatures,
- * combining characters, etc., it's not guaranteed that the algorithm
- * always works 100%. It's sort of a heuristic thing. It should work
- * nearly all the time... but I wouldn't put in
- * g_assert (width of resulting string < width).
- *
- * Hmm, another thing that this breaks with is explicit line breaks
- * in "string"
- */
-
- compute_character_widths (string, layout, &char_len, &widths, &cuts, markup);
-
- for (truncate_offset = 1; truncate_offset < char_len; truncate_offset++) {
-
- resulting_width -= widths[truncate_offset];
-
- if (resulting_width <= width &&
- cuts[truncate_offset]) {
- break;
- }
- }
-
- g_free (cuts);
- g_free (widths);
-
- bytes_end = g_utf8_offset_to_pointer (string, truncate_offset) - string;
-
- return ellipsize_string (string, 0, bytes_end, markup);
-}
-
-static char *
-ephy_string_ellipsize_end (const char *string, PangoLayout *layout, int width, gboolean markup)
-{
- int resulting_width;
- int *cuts;
- int *widths;
- int char_len;
- int truncate_offset;
- int bytes_end;
-
- /* See explanatory comments in ellipsize_start */
-
- if (*string == '\0')
- return g_strdup ("");
-
- resulting_width = measure_string_width (string, layout, markup);
-
- if (resulting_width <= width) {
- return g_strdup (string);
- }
-
- width -= measure_string_width (ELLIPSIS, layout, markup);
-
- if (width < 0) {
- return g_strdup ("");
- }
-
- compute_character_widths (string, layout, &char_len, &widths, &cuts, markup);
-
- for (truncate_offset = char_len - 1; truncate_offset > 0; truncate_offset--) {
- resulting_width -= widths[truncate_offset];
- if (resulting_width <= width &&
- cuts[truncate_offset]) {
- break;
- }
- }
-
- g_free (cuts);
- g_free (widths);
-
- bytes_end = g_utf8_offset_to_pointer (string, truncate_offset) - string;
-
- return ellipsize_string (string, bytes_end,
- char_len, markup);
-}
-
-static char *
-ephy_string_ellipsize_middle (const char *string, PangoLayout *layout, int width, gboolean markup)
-{
- int resulting_width;
- int *cuts;
- int *widths;
- int char_len;
- int starting_fragment_length;
- int ending_fragment_offset;
- int bytes_start;
- int bytes_end;
-
- /* See explanatory comments in ellipsize_start */
-
- if (*string == '\0')
- return g_strdup ("");
-
- resulting_width = measure_string_width (string, layout, markup);
-
- if (resulting_width <= width) {
- return g_strdup (string);
- }
-
- width -= measure_string_width (ELLIPSIS, layout, markup);
-
- if (width < 0) {
- return g_strdup ("");
- }
-
- compute_character_widths (string, layout, &char_len, &widths, &cuts, markup);
-
- starting_fragment_length = char_len / 2;
- ending_fragment_offset = starting_fragment_length + 1;
-
- /* depending on whether the original string length is odd or even, start by
- * shaving off the characters from the starting or ending fragment
- */
- if (char_len % 2) {
- goto shave_end;
- }
-
- while (starting_fragment_length > 0 || ending_fragment_offset < char_len) {
- if (resulting_width <= width &&
- cuts[ending_fragment_offset] &&
- cuts[starting_fragment_length]) {
- break;
- }
-
- if (starting_fragment_length > 0) {
- resulting_width -= widths[starting_fragment_length];
- starting_fragment_length--;
- }
-
- shave_end:
- if (resulting_width <= width &&
- cuts[ending_fragment_offset] &&
- cuts[starting_fragment_length]) {
- break;
- }
-
- if (ending_fragment_offset < char_len) {
- resulting_width -= widths[ending_fragment_offset];
- ending_fragment_offset++;
- }
- }
-
- g_free (cuts);
- g_free (widths);
-
- bytes_start = g_utf8_offset_to_pointer (string, starting_fragment_length) - string;
- bytes_end = g_utf8_offset_to_pointer (string, ending_fragment_offset) - string;
-
- return ellipsize_string (string, bytes_start, bytes_end, markup);
-}
-
-
-/**
- * ephy_pango_layout_set_text_ellipsized
- *
- * @layout: a pango layout
- * @string: A a string to be ellipsized.
- * @width: Desired maximum width in points.
- * @mode: The desired ellipsizing mode.
- *
- * Truncates a string if required to fit in @width and sets it on the
- * layout. Truncation involves removing characters from the start, middle or end
- * respectively and replacing them with "...". Algorithm is a bit
- * fuzzy, won't work 100%.
- *
- */
-static void
-gul_pango_layout_set_text_ellipsized (PangoLayout *layout,
- const char *string,
- int width,
- EphyEllipsizeMode mode,
- gboolean markup)
-{
- char *s;
-
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- g_return_if_fail (string != NULL);
- g_return_if_fail (width >= 0);
-
- switch (mode) {
- case EPHY_ELLIPSIZE_START:
- s = ephy_string_ellipsize_start (string, layout, width, markup);
- break;
- case EPHY_ELLIPSIZE_MIDDLE:
- s = ephy_string_ellipsize_middle (string, layout, width, markup);
- break;
- case EPHY_ELLIPSIZE_END:
- s = ephy_string_ellipsize_end (string, layout, width, markup);
- break;
- default:
- g_return_if_reached ();
- s = NULL;
- }
-
- if (markup)
- {
- pango_layout_set_markup (layout, s, -1);
- }
- else
- {
- pango_layout_set_text (layout, s, -1);
- }
-
- g_free (s);
-}
-
-GType
-ephy_ellipsizing_label_get_type (void)
-{
- static GType ephy_ellipsizing_label_type = 0;
-
- if (ephy_ellipsizing_label_type == 0)
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyEllipsizingLabelClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_ellipsizing_label_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyEllipsizingLabel),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_ellipsizing_label_init
- };
-
- ephy_ellipsizing_label_type = g_type_register_static (GTK_TYPE_LABEL,
- "EphyEllipsizingLabel",
- &our_info, 0);
- }
-
- return ephy_ellipsizing_label_type;
-}
-
-static void
-ephy_ellipsizing_label_init (EphyEllipsizingLabel *label)
-{
- label->priv = g_new0 (EphyEllipsizingLabelPrivate, 1);
-
- label->priv->mode = EPHY_ELLIPSIZE_NONE;
-}
-
-static void
-real_finalize (GObject *object)
-{
- EphyEllipsizingLabel *label;
-
- label = EPHY_ELLIPSIZING_LABEL (object);
-
- g_free (label->priv->full_text);
- g_free (label->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-GtkWidget*
-ephy_ellipsizing_label_new (const char *string)
-{
- EphyEllipsizingLabel *label;
-
- label = g_object_new (EPHY_TYPE_ELLIPSIZING_LABEL, NULL);
- ephy_ellipsizing_label_set_text (label, string);
-
- return GTK_WIDGET (label);
-}
-
-void
-ephy_ellipsizing_label_set_text (EphyEllipsizingLabel *label,
- const char *string)
-{
- g_return_if_fail (EPHY_IS_ELLIPSIZING_LABEL (label));
-
- if (ephy_str_is_equal (string, label->priv->full_text)) {
- return;
- }
-
- g_free (label->priv->full_text);
- label->priv->full_text = g_strdup (string);
-
- /* Queues a resize as side effect */
- gtk_label_set_text (GTK_LABEL (label), label->priv->full_text);
-}
-
-void
-ephy_ellipsizing_label_set_markup (EphyEllipsizingLabel *label,
- const char *string)
-{
- g_return_if_fail (EPHY_IS_ELLIPSIZING_LABEL (label));
-
- if (ephy_str_is_equal (string, label->priv->full_text)) {
- return;
- }
-
- g_free (label->priv->full_text);
- label->priv->full_text = g_strdup (string);
-
- /* Queues a resize as side effect */
- gtk_label_set_markup (GTK_LABEL (label), label->priv->full_text);
-}
-
-void
-ephy_ellipsizing_label_set_mode (EphyEllipsizingLabel *label,
- EphyEllipsizeMode mode)
-{
- g_return_if_fail (EPHY_IS_ELLIPSIZING_LABEL (label));
-
- label->priv->mode = mode;
-}
-
-static void
-real_size_request (GtkWidget *widget, GtkRequisition *requisition)
-{
- GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
-
- /* Don't demand any particular width; will draw ellipsized into whatever size we're given */
- requisition->width = 0;
-}
-
-static void
-real_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- EphyEllipsizingLabel *label;
- gboolean markup;
-
- markup = gtk_label_get_use_markup (GTK_LABEL (widget));
-
- label = EPHY_ELLIPSIZING_LABEL (widget);
-
- /* This is the bad hack of the century, using private
- * GtkLabel layout object. If the layout is NULL
- * then it got blown away since size request,
- * we just punt in that case, I don't know what to do really.
- */
-
- if (GTK_LABEL (label)->layout != NULL) {
- if (label->priv->full_text == NULL) {
- pango_layout_set_text (GTK_LABEL (label)->layout, "", -1);
- } else {
- EphyEllipsizeMode mode;
-
- if (label->priv->mode != EPHY_ELLIPSIZE_NONE)
- mode = label->priv->mode;
-
- if (ABS (GTK_MISC (label)->xalign - 0.5) < 1e-12)
- mode = EPHY_ELLIPSIZE_MIDDLE;
- else if (GTK_MISC (label)->xalign < 0.5)
- mode = EPHY_ELLIPSIZE_END;
- else
- mode = EPHY_ELLIPSIZE_START;
-
- gul_pango_layout_set_text_ellipsized (GTK_LABEL (label)->layout,
- label->priv->full_text,
- allocation->width,
- mode,
- markup);
-
- gtk_widget_queue_draw (GTK_WIDGET (label));
- }
- }
-
- GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
-}
-
-static gboolean
-real_expose_event (GtkWidget *widget, GdkEventExpose *event)
-{
- EphyEllipsizingLabel *label;
- GtkRequisition req;
-
- label = EPHY_ELLIPSIZING_LABEL (widget);
-
- /* push/pop the actual size so expose draws in the right
- * place, yes this is bad hack central. Here we assume the
- * ellipsized text has been set on the layout in size_allocate
- */
- GTK_WIDGET_CLASS (parent_class)->size_request (widget, &req);
- widget->requisition.width = req.width;
- GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
- widget->requisition.width = 0;
-
- return FALSE;
-}
-
-
-static void
-ephy_ellipsizing_label_class_init (EphyEllipsizingLabelClass *klass)
-{
- GtkWidgetClass *widget_class;
-
- parent_class = g_type_class_peek_parent (klass);
-
- widget_class = GTK_WIDGET_CLASS (klass);
-
- G_OBJECT_CLASS (klass)->finalize = real_finalize;
-
- widget_class->size_request = real_size_request;
- widget_class->size_allocate = real_size_allocate;
- widget_class->expose_event = real_expose_event;
-}
-