📄 gtklabel.c
字号:
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. (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; 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] == ' ') { 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; } else { /* Regular inter-word space */ word->space = space_width; } word->beginning = str; word->length = 0; p = word->beginning; 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++; line_width += word->space + word->width; *tailp = word; tailp = &word->next; } return MAX (line_width, max_line_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. * * Returns the length of the longest resulting line. * * (The reason we go to all this effort to pick a paragraph width is to * try to avoid the lame look of a short paragraph with a * short final line.) */static gintgtk_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) { if (word->space == 0 || (line_width && (line_width >= min_width || line_width + word->width + word->space > max_width))) { /* New line */ width = MAX (width, line_width); line_width = 0; } line_width += word->space + word->width; } return MAX (width, line_width);}/* Here, we finalize the lines. * This is only for non-wrap labels. Wrapped labels * use gtk_label_finalize_wrap instead. */static voidgtk_label_finalize_lines (GtkLabel *label, GtkRequisition *requisition, gint max_line_width){ 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); for (line = label->words; line; line = line->next) { if (label->jtype == GTK_JUSTIFY_CENTER) line->x = (max_line_width - line->width) / 2; else if (label->jtype == GTK_JUSTIFY_RIGHT) line->x = max_line_width - line->width; else 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') { for (i = 0; i < line->length; i++) { if (ptrn[i] == '\0') break; else if (ptrn[i] == '_') { gint descent; gint rbearing; gint lbearing; gint width; gint offset; GtkLabelULine *uline; 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. * let's measure it and record it. */ offset = gdk_text_width_wc (GTK_WIDGET (label)->style->font, line->beginning, i); gdk_text_extents_wc (GTK_WIDGET (label)->style->font, line->beginning+i, j-i, &lbearing, &rbearing, &width, NULL, &descent); y_max = MAX (descent + 2, y_max); uline = gtk_label_uline_alloc (); uline->x1 = offset + line->x + lbearing - 1; uline->x2 = offset + line->x + rbearing; uline->y = line->y + descent + 2; uline->next = line->uline; line->uline = uline; i = j - 1; } } if (strlen (ptrn) > line->length) /* the + 1 is for line breaks. */ ptrn += line->length + 1; else ptrn = NULL; } y += (baseline_skip + y_max); } 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 voidgtk_label_finalize_lines_wrap (GtkLabel *label, GtkRequisition *requisition, gint max_line_width){ GtkLabelWord *word, *line, *next_line; GtkWidget *widget; gchar *ptrn; 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); for (line = label->words; line != 0; line = next_line) { space = 0; 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 */ if (next_line->space + next_line->width > extra_width) 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) { /* Not last line of paragraph --- fill line if needed */ if (label->jtype == GTK_JUSTIFY_FILL) { add_space = (extra_width * word->space + space / 2) / space; extra_width -= add_space; space -= word->space; } } word->x = x + word->space + add_space; word->y = line->y; x = word->x + word->width; } y += (baseline_skip); } label->max_width = max_line_width; widget = GTK_WIDGET (label); requisition->width = max_line_width + 2 * label->misc.xpad; requisition->height = y + 2 * label->misc.ypad + 1;}static voidgtk_label_size_request (GtkWidget *widget, GtkRequisition *requisition){ GtkLabel *label; g_return_if_fail (GTK_IS_LABEL (widget)); g_return_if_fail (requisition != NULL); label = GTK_LABEL (widget); /* * There are a number of conditions which will necessitate re-filling * our text: * * 1. text changed. * 2. justification changed either from to to GTK_JUSTIFY_FILL. * 3. font changed. * * These have been detected elsewhere, and label->words will be zero, * if one of the above has occured. * * Additionally, though, if GTK_JUSTIFY_FILL, we need to re-fill if: * * 4. gtk_widget_set_usize has changed the requested width. * 5. gtk_misc_set_padding has changed xpad. * 6. maybe others?... * * 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; gint longest_paragraph; longest_paragraph = gtk_label_split_text_wrapped (label); 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); 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."); 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) { gint nlines, perfect_width; 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); } } gtk_label_finalize_lines_wrap (label, requisition, label->max_width); } else if (!label->words) { label->max_width = gtk_label_split_text (label); gtk_label_finalize_lines (label, requisition, label->max_width); }}static void gtk_label_style_set (GtkWidget *widget, GtkStyle *previous_style){ GtkLabel *label; 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 voidgtk_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); 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);}static gintgtk_label_expose (GtkWidget *widget, GdkEventExpose *event){ GtkLabel *label; GtkMisc *misc; GtkLabelWord *word; gint x, y; g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); label = GTK_LABEL (widget); if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) && label->label && (*label->label != '\0')) { misc = GTK_MISC (widget); /* * 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); for (word = label->words; word; word = word->next) { gchar save = word->beginning[word->length]; word->beginning[word->length] = '\0'; 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){ guint accel_key = GDK_VoidSymbol; GdkWChar *p, *q, *string_wc; gchar *r; gchar *pattern; 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'; pattern = g_new (gchar, length+1); underscore = FALSE; p = q = string_wc; r = pattern; while (*p) { if (underscore) { if (*p == '_') *r++ = ' '; else { *r++ = '_'; if (accel_key == GDK_VoidSymbol) accel_key = gdk_keyval_to_lower (*p); } *q++ = *p; underscore = FALSE; } else { if (*p == '_') underscore = TRUE; else { *q++ = *p; *r++ = ' '; } } p++; } *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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -