📄 gtklabel.c
字号:
/* 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 * 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. * * This 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 details. * * You should have received a copy of the GNU Library General Public * 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"#include "gdk/gdki18n.h"enum { ARG_0, ARG_LABEL, ARG_PATTERN, ARG_JUSTIFY, ARG_WRAP};typedef struct _GtkLabelULine GtkLabelULine;struct _GtkLabelWord{ 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. * I haven't yet figured out how to do this without making the code * look ugly. */ gint space; gint width; gint x; gint y; GtkLabelWord *next; gint uline_y; GtkLabelULine *uline;};struct _GtkLabelULine{ gint x1; gint x2; gint y; GtkLabelULine *next;};static void gtk_label_class_init (GtkLabelClass *klass);static void gtk_label_init (GtkLabel *label);static void gtk_label_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);static void gtk_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);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 GtkMiscClass *parent_class = NULL;static GMemChunk *word_chunk = NULL;static GMemChunk *uline_chunk = NULL;GtkTypegtk_label_get_type (void){ static GtkType label_type = 0; if (!label_type) { static const GtkTypeInfo label_info = { "GtkLabel", sizeof (GtkLabel), sizeof (GtkLabelClass), (GtkClassInitFunc) gtk_label_class_init, (GtkObjectInitFunc) gtk_label_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; label_type = gtk_type_unique (GTK_TYPE_MISC, &label_info); gtk_type_set_chunk_alloc (label_type, 32); } return label_type;}static voidgtk_label_class_init (GtkLabelClass *class){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; 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;}static voidgtk_label_set_arg (GtkObject *object, GtkArg *arg, guint arg_id){ GtkLabel *label; label = GTK_LABEL (object); switch (arg_id) { case ARG_LABEL: gtk_label_set_text (label, GTK_VALUE_STRING (*arg)); break; case ARG_PATTERN: gtk_label_set_pattern (label, GTK_VALUE_STRING (*arg)); break; 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; }}static voidgtk_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id){ GtkLabel *label; label = GTK_LABEL (object); switch (arg_id) { case ARG_LABEL: GTK_VALUE_STRING (*arg) = g_strdup (label->label); break; case ARG_PATTERN: GTK_VALUE_STRING (*arg) = g_strdup (label->pattern); break; 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; }}static voidgtk_label_init (GtkLabel *label){ 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->wrap = FALSE; gtk_label_set_text (label, "");}GtkWidget*gtk_label_new (const gchar *str){ GtkLabel *label; label = gtk_type_new (GTK_TYPE_LABEL); if (str && *str) gtk_label_set_text (label, str); return GTK_WIDGET (label);}static inline voidgtk_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));}voidgtk_label_set_text (GtkLabel *label, const gchar *str){ GdkWChar *str_wc; gint len; gint wc_len; g_return_if_fail (GTK_IS_LABEL (label)); if (!str) str = ""; if (!label->label || strcmp (label->label, str)) { /* 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); }}voidgtk_label_set_pattern (GtkLabel *label, const gchar *pattern){ g_return_if_fail (GTK_IS_LABEL (label)); gtk_label_free_words (label); g_free (label->pattern); label->pattern = g_strdup (pattern); gtk_widget_queue_resize (GTK_WIDGET (label));}voidgtk_label_set_justify (GtkLabel *label, GtkJustification jtype){ 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) { gtk_label_free_words (label); label->jtype = jtype; gtk_widget_queue_resize (GTK_WIDGET (label)); }}voidgtk_label_set_line_wrap (GtkLabel *label, gboolean wrap){ g_return_if_fail (GTK_IS_LABEL (label)); wrap = wrap != FALSE; if (label->wrap != wrap) { gtk_label_free_words (label); label->wrap = wrap; gtk_widget_queue_resize (GTK_WIDGET (label)); }}voidgtk_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;}static voidgtk_label_finalize (GtkObject *object){ GtkLabel *label; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_LABEL (object)); label = GTK_LABEL (object); g_free (label->label); g_free (label->label_wc); g_free (label->pattern); gtk_label_free_words (label); GTK_OBJECT_CLASS (parent_class)->finalize (object);}static GtkLabelULine*gtk_label_uline_alloc (void){ GtkLabelULine *uline; if (!uline_chunk) uline_chunk = g_mem_chunk_create (GtkLabelWord, 32, G_ALLOC_AND_FREE); uline = g_chunk_new0 (GtkLabelULine, uline_chunk); uline->next = NULL; return uline;}static voidgtk_label_free_ulines (GtkLabelWord *word){ while (word->uline) { GtkLabelULine *uline = word->uline; word->uline = uline->next; g_chunk_free (uline, uline_chunk); }}static GtkLabelWord*gtk_label_word_alloc (void){ GtkLabelWord * word; 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 voidgtk_label_free_words (GtkLabel *label){ while (label->words) { GtkLabelWord *word = label->words; label->words = word->next; gtk_label_free_ulines (word); g_chunk_free (word, word_chunk); }}static gintgtk_label_split_text (GtkLabel *label){ GtkLabelWord *word, **tailp; gint space_width, line_width, max_line_width; GdkWChar *str, *p; gtk_label_free_words (label); if (label->label == NULL) return 0; /* 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') { /* Paragraph break */ word->space = 0; max_line_width = MAX (line_width, max_line_width); line_width = 0; } else if (str[0] == ' ') { while (str[0] == ' ') { str++; word->space += space_width; } } else { /* Regular inter-word space */ word->space = space_width; } word->beginning = str; word->length = 0; p = word->beginning; 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++; 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 gintgtk_label_split_text_wrapped (GtkLabel *label){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -