static void text_input_preedit_styling(void *data, struct wl_text_input *text_input, uint32_t index, uint32_t length, uint32_t style) { struct text_entry *entry = data; PangoAttribute *attr1 = NULL; PangoAttribute *attr2 = NULL; if (!entry->preedit_info.attr_list) entry->preedit_info.attr_list = pango_attr_list_new(); switch (style) { case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT: case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); break; case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR); attr2 = pango_attr_underline_color_new(65535, 0, 0); break; case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION: attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535); attr2 = pango_attr_foreground_new(65535, 65535, 65535); break; case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT: case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD); break; case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535); break; } if (attr1) { attr1->start_index = entry->cursor + index; attr1->end_index = entry->cursor + index + length; pango_attr_list_insert(entry->preedit_info.attr_list, attr1); } if (attr2) { attr2->start_index = entry->cursor + index; attr2->end_index = entry->cursor + index + length; pango_attr_list_insert(entry->preedit_info.attr_list, attr2); } }
static gboolean vi_list_item_enter_notify_event(GtkWidget *widget, GdkEventCrossing *event, struct vi_list_item_t *item) { GdkColor color; PangoAttrList *attrs; PangoAttribute *underline_attr; GdkWindow *window; GdkCursor *cursor; GtkStyle *style; style = gtk_widget_get_style(item->label); item->label_color = style->fg[GTK_STATE_NORMAL]; gdk_color_parse("red", &color); gtk_widget_modify_fg(item->label, GTK_STATE_NORMAL, &color); attrs = gtk_label_get_attributes(GTK_LABEL(item->label)); underline_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_change(attrs, underline_attr); cursor = gdk_cursor_new(GDK_HAND1); window = gtk_widget_get_parent_window(widget); gdk_window_set_cursor(window, cursor); g_object_unref(cursor); return FALSE; }
static void check_replace_text (IdeEditorFrame *self) { GtkSourceSearchContext *search_context; GtkSourceSearchSettings *search_settings; g_autoptr(GError) error = NULL; PangoAttrList *attrs; g_assert (IDE_IS_EDITOR_FRAME (self)); search_context = ide_source_view_get_search_context (self->source_view); search_settings = gtk_source_search_context_get_settings (search_context); attrs = pango_attr_list_new (); /* * If the replace expression is invalid, add a white squiggly underline; * otherwise remove it. */ if (gtk_source_search_settings_get_regex_enabled (search_settings)) { const gchar *replace_text; replace_text = gtk_entry_get_text (GTK_ENTRY (self->replace_entry)); if (!g_regex_check_replacement (replace_text, NULL, &error)) { pango_attr_list_insert (attrs, pango_attr_underline_new (PANGO_UNDERLINE_ERROR)); pango_attr_list_insert (attrs, pango_attr_underline_color_new (65535, 65535, 65535)); } } gtk_entry_set_attributes (GTK_ENTRY (self->replace_entry), attrs); pango_attr_list_unref (attrs); }
static void on_regex_error_changed (IdeEditorFrame *self, GParamSpec *pspec, GtkSourceSearchContext *search_context) { g_autoptr(GError) error = NULL; PangoAttrList *attrs; g_assert (IDE_IS_EDITOR_FRAME (self)); g_assert (GTK_SOURCE_IS_SEARCH_CONTEXT (search_context)); /* * If the regular expression is invalid, add a white squiggly underline; * otherwise remove it. */ attrs = pango_attr_list_new (); error = gtk_source_search_context_get_regex_error (search_context); if (error != NULL) { pango_attr_list_insert (attrs, pango_attr_underline_new (PANGO_UNDERLINE_ERROR)); pango_attr_list_insert (attrs, pango_attr_underline_color_new (65535, 65535, 65535)); } gtk_entry_set_attributes (GTK_ENTRY (self->search_entry), attrs); pango_attr_list_unref (attrs); update_replace_actions_sensitivity (self); }
static void nimf_gtk_im_context_get_preedit_string (GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { g_debug (G_STRLOC ": %s", G_STRFUNC); PangoAttribute *attr; nimf_im_get_preedit_string (NIMF_GTK_IM_CONTEXT (context)->im, str, cursor_pos); if (attrs) { *attrs = pango_attr_list_new (); attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); if (str) { attr->start_index = 0; attr->end_index = strlen (*str); } pango_attr_list_change (*attrs, attr); } }
/** * thunar_pango_attr_list_underline_single: * * Returns a #PangoAttrList for underlining text using a single line. * The returned list is owned by the callee and must not be freed * or modified by the caller. * * Return value: a #PangoAttrList for underlining text using a single line. **/ PangoAttrList* thunar_pango_attr_list_underline_single (void) { static PangoAttrList *attr_list = NULL; if (G_UNLIKELY (attr_list == NULL)) attr_list = thunar_pango_attr_list_wrap (pango_attr_underline_new (PANGO_UNDERLINE_SINGLE), NULL); return attr_list; }
RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size, RrFontWeight weight, RrFontSlant slant) { RrFont *out; PangoWeight pweight; PangoStyle pstyle; PangoAttrList *attrlist; out = g_slice_new(RrFont); out->inst = inst; out->ref = 1; out->font_desc = pango_font_description_new(); out->layout = pango_layout_new(inst->pango); out->shortcut_underline = pango_attr_underline_new(PANGO_UNDERLINE_LOW); out->shortcut_underline->start_index = 0; out->shortcut_underline->end_index = 0; attrlist = pango_attr_list_new(); /* shortcut_underline is owned by the attrlist */ pango_attr_list_insert(attrlist, out->shortcut_underline); /* the attributes are owned by the layout */ pango_layout_set_attributes(out->layout, attrlist); pango_attr_list_unref(attrlist); switch (weight) { case RR_FONTWEIGHT_LIGHT: pweight = PANGO_WEIGHT_LIGHT; break; case RR_FONTWEIGHT_NORMAL: pweight = PANGO_WEIGHT_NORMAL; break; case RR_FONTWEIGHT_SEMIBOLD: pweight = PANGO_WEIGHT_SEMIBOLD; break; case RR_FONTWEIGHT_BOLD: pweight = PANGO_WEIGHT_BOLD; break; case RR_FONTWEIGHT_ULTRABOLD: pweight = PANGO_WEIGHT_ULTRABOLD; break; default: g_assert_not_reached(); } switch (slant) { case RR_FONTSLANT_NORMAL: pstyle = PANGO_STYLE_NORMAL; break; case RR_FONTSLANT_ITALIC: pstyle = PANGO_STYLE_ITALIC; break; case RR_FONTSLANT_OBLIQUE: pstyle = PANGO_STYLE_OBLIQUE; break; default: g_assert_not_reached(); } /* setup the font */ pango_font_description_set_family(out->font_desc, name); pango_font_description_set_weight(out->font_desc, pweight); pango_font_description_set_style(out->font_desc, pstyle); pango_font_description_set_size(out->font_desc, size * PANGO_SCALE); /* setup the layout */ pango_layout_set_font_description(out->layout, out->font_desc); pango_layout_set_wrap(out->layout, PANGO_WRAP_WORD_CHAR); /* get the ascent and descent */ measure_font(inst, out); return out; }
/** * _st_set_text_from_style: * @text: Target #ClutterText * @theme_node: Source #StThemeNode * * Set various GObject properties of the @text object using * CSS information from @theme_node. */ void _st_set_text_from_style (ClutterText *text, StThemeNode *theme_node) { ClutterColor color; StTextDecoration decoration; PangoAttrList *attribs = NULL; const PangoFontDescription *font; StTextAlign align; st_theme_node_get_foreground_color (theme_node, &color); clutter_text_set_color (text, &color); font = st_theme_node_get_font (theme_node); clutter_text_set_font_description (text, (PangoFontDescription *) font); decoration = st_theme_node_get_text_decoration (theme_node); if (decoration) { attribs = pango_attr_list_new (); if (decoration & ST_TEXT_DECORATION_UNDERLINE) { PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr_list_insert (attribs, underline); } if (decoration & ST_TEXT_DECORATION_LINE_THROUGH) { PangoAttribute *strikethrough = pango_attr_strikethrough_new (TRUE); pango_attr_list_insert (attribs, strikethrough); } /* Pango doesn't have an equivalent attribute for _OVERLINE, and we deliberately * skip BLINK (for now...) */ } clutter_text_set_attributes (text, attribs); if (attribs) pango_attr_list_unref (attribs); align = st_theme_node_get_text_align (theme_node); if (align == ST_TEXT_ALIGN_JUSTIFY) { clutter_text_set_justify (text, TRUE); clutter_text_set_line_alignment (text, PANGO_ALIGN_LEFT); } else { clutter_text_set_justify (text, FALSE); clutter_text_set_line_alignment (text, (PangoAlignment) align); } }
bool wxStaticText::SetFont( const wxFont &font ) { const bool wasUnderlined = GetFont().GetUnderlined(); const bool wasStrickenThrough = GetFont().GetStrikethrough(); bool ret = wxControl::SetFont(font); const bool isUnderlined = GetFont().GetUnderlined(); const bool isStrickenThrough = GetFont().GetStrikethrough(); if ( (isUnderlined != wasUnderlined) || (isStrickenThrough != wasStrickenThrough) ) { // We need to update the Pango attributes used for the text. if ( isUnderlined || isStrickenThrough ) { PangoAttrList* const attrs = pango_attr_list_new(); if ( isUnderlined ) { PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); a->start_index = 0; a->end_index = (guint)-1; pango_attr_list_insert(attrs, a); } if ( isStrickenThrough ) { PangoAttribute *a = pango_attr_strikethrough_new( TRUE ); a->start_index = 0; a->end_index = (guint) -1; pango_attr_list_insert(attrs, a); } gtk_label_set_attributes(GTK_LABEL(m_widget), attrs); pango_attr_list_unref(attrs); } else // No special attributes any more. { // Just remove any attributes we had set. gtk_label_set_attributes(GTK_LABEL(m_widget), NULL); } // The underlines for mnemonics are incompatible with using attributes // so turn them off when setting underlined font. gtk_label_set_use_underline(GTK_LABEL(m_widget), !isUnderlined); } // adjust the label size to the new label unless disabled if (!HasFlag(wxST_NO_AUTORESIZE)) { SetSize( GetBestSize() ); } return ret; }
static int cdfont(cdCtxCanvas *ctxcanvas, const char *typeface, int style, int size) { int is_italic = 0, is_bold = 0; /* default is CD_PLAIN */ int is_strikeout = 0, is_underline = 0; char font[256]; PangoAttrList *attrs; if (cdStrEqualNoCase(typeface, "Courier") || cdStrEqualNoCase(typeface, "Courier New")) typeface = "Monospace"; else if (cdStrEqualNoCase(typeface, "Times") || cdStrEqualNoCase(typeface, "Times New Roman")) typeface = "Serif"; else if (cdStrEqualNoCase(typeface, "Helvetica") || cdStrEqualNoCase(typeface, "Arial")) typeface = "Sans"; if (style & CD_BOLD) is_bold = 1; if (style & CD_ITALIC) is_italic = 1; if (style & CD_UNDERLINE) is_underline = 1; if (style & CD_STRIKEOUT) is_strikeout = 1; size = cdGetFontSizePoints(ctxcanvas->canvas, size); sprintf(font, "%s, %s%s%d", typeface, is_bold?"Bold ":"", is_italic?"Italic ":"", size); if (ctxcanvas->fontdesc) pango_font_description_free(ctxcanvas->fontdesc); ctxcanvas->fontdesc = pango_font_description_from_string(font); if (!ctxcanvas->fontdesc) return 0; if (ctxcanvas->fontlayout) g_object_unref(ctxcanvas->fontlayout); ctxcanvas->fontlayout = pango_layout_new(ctxcanvas->fontcontext); pango_layout_set_font_description(ctxcanvas->fontlayout, ctxcanvas->fontdesc); attrs = pango_attr_list_new(); pango_attr_list_insert(attrs, pango_attribute_copy(pango_attr_strikethrough_new(is_strikeout ? TRUE : FALSE))); pango_attr_list_insert(attrs, pango_attribute_copy(pango_attr_underline_new(is_underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE))); pango_layout_set_attributes(ctxcanvas->fontlayout, attrs); pango_attr_list_unref(attrs); return 1; }
static gboolean u_parse_func (MarkupData *md, OpenTag *tag, const gchar **names, const gchar **values, GMarkupParseContext *context, GError **error) { CHECK_NO_ATTRS("u"); add_attribute (tag, pango_attr_underline_new (PANGO_UNDERLINE_SINGLE)); return TRUE; }
static gboolean vi_list_item_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, struct vi_list_item_t *item) { PangoAttrList *attrs; PangoAttribute *underline_attr; GdkWindow *window; window = gtk_widget_get_parent_window(widget); gdk_window_set_cursor(window, NULL); attrs = gtk_label_get_attributes(GTK_LABEL(item->label)); underline_attr = pango_attr_underline_new(PANGO_UNDERLINE_NONE); pango_attr_list_change(attrs, underline_attr); gtk_widget_modify_fg(item->label, GTK_STATE_NORMAL, &item->label_color); return FALSE; }
static void vfunc_get_preedit_string (GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { gsize len_bytes = 0; gsize len_utf8_chars = 0; /* Show the user what character he will get if he accepts: */ if (str != NULL) { const gchar *match; match = GTK_IM_CONTEXT_MULTIPRESS (context)->tentative_match; if (match == NULL) match = ""; /* *str must not be NUL */ len_bytes = strlen (match); /* byte count */ len_utf8_chars = g_utf8_strlen (match, len_bytes); /* character count */ *str = g_strndup (match, len_bytes); } /* Underline it, to show the user that he is in compose mode: */ if (attrs != NULL) { *attrs = pango_attr_list_new (); if (len_bytes > 0) { PangoAttribute *attr; attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attr->start_index = 0; attr->end_index = len_bytes; pango_attr_list_insert (*attrs, attr); } } if (cursor_pos) *cursor_pos = len_utf8_chars; }
static void fcitx_im_context_get_preedit_string(ClutterIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (IsFcitxIMClientValid(fcitxcontext->client) && IsFcitxIMClientEnabled(fcitxcontext->client)) { if (str) { if (fcitxcontext->preedit_string) *str = strdup(fcitxcontext->preedit_string); else *str = strdup(""); } if (attrs) { *attrs = pango_attr_list_new(); if (str) { PangoAttribute *pango_attr; pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = 0; pango_attr->end_index = strlen(*str); pango_attr_list_insert(*attrs, pango_attr); } } if (cursor_pos) *cursor_pos = fcitxcontext->cursor_pos; } else { if (str) { *str = g_strdup(""); } if (attrs) { *attrs = pango_attr_list_new(); } if (cursor_pos) *cursor_pos = 0; } return ; }
static void gtk_im_context_wayland_get_preedit_string (GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { GtkIMContextWayland *context_wayland = GTK_IM_CONTEXT_WAYLAND (context); gchar *preedit_str; if (attrs) *attrs = NULL; GTK_IM_CONTEXT_CLASS (parent_class)->get_preedit_string (context, str, attrs, cursor_pos); /* If the parent implementation returns a len>0 string, go with it */ if (str && *str) { if (**str) return; g_free (*str); } preedit_str = context_wayland->preedit.text ? context_wayland->preedit.text : ""; if (str) *str = g_strdup (preedit_str); if (cursor_pos) *cursor_pos = context_wayland->preedit.cursor_idx; if (attrs) { if (!*attrs) *attrs = pango_attr_list_new (); pango_attr_list_insert (*attrs, pango_attr_underline_new (PANGO_UNDERLINE_SINGLE)); } }
static void fcitx_im_context_get_preedit_string(GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitx_client_is_valid(fcitxcontext->client)) { if (str) { if (fcitxcontext->preedit_string) *str = strdup(fcitxcontext->preedit_string); else *str = strdup(""); } if (attrs) { if (fcitxcontext->attrlist == NULL) { *attrs = pango_attr_list_new(); if (str) { PangoAttribute *pango_attr; pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = 0; pango_attr->end_index = strlen(*str); pango_attr_list_insert(*attrs, pango_attr); } } else { *attrs = pango_attr_list_ref (fcitxcontext->attrlist); } } if (cursor_pos) *cursor_pos = fcitxcontext->cursor_pos; } else gtk_im_context_get_preedit_string(fcitxcontext->slave, str, attrs, cursor_pos); return ; }
static void tamil99_get_preedit_string (GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { ComposeSequence *comp_seq; gchar *string; gint len; comp_seq = find_complete_compose_sequence (compose_buffer); if (comp_seq == NULL) string = ""; else string = comp_seq->string; *str = g_strdup (string); len = strlen (*str); if (attrs) { *attrs = pango_attr_list_new (); /* this can cause a pango crash pre-1.2.3 (so we require >= 1.2.3) * http://bugzilla.gnome.org/show_bug.cgi?id=104976 */ if (len != 0) { PangoAttribute *attr; attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attr->start_index = 0; attr->end_index = len; pango_attr_list_insert (*attrs, attr); } } if (cursor_pos) *cursor_pos = len; }
PangoAttrList *token_match_get_pango_attr ( GRegex **tokens, const char *input, PangoAttrList *retv ) { // Do a tokenized match. if ( tokens ) { for ( int j = 0; tokens[j]; j++ ) { GMatchInfo *gmi = NULL; g_regex_match ( (GRegex *) tokens[j], input, G_REGEX_MATCH_PARTIAL, &gmi ); while ( g_match_info_matches ( gmi ) ) { int start, end; g_match_info_fetch_pos ( gmi, 0, &start, &end ); PangoAttribute *pa = pango_attr_underline_new ( PANGO_UNDERLINE_SINGLE ); PangoAttribute *pa2 = pango_attr_weight_new ( PANGO_WEIGHT_BOLD ); pa2->start_index = pa->start_index = start; pa2->end_index = pa->end_index = end; pango_attr_list_insert ( retv, pa ); pango_attr_list_insert ( retv, pa2 ); g_match_info_next ( gmi, NULL ); } g_match_info_free ( gmi ); } } return retv; }
bool wxStaticText::SetFont( const wxFont &font ) { const bool wasUnderlined = GetFont().GetUnderlined(); bool ret = wxControl::SetFont(font); if ( font.GetUnderlined() != wasUnderlined ) { // the underlines for mnemonics are incompatible with using attributes // so turn them off when setting underlined font and restore them when // unsetting it gtk_label_set_use_underline(GTK_LABEL(m_widget), wasUnderlined); if ( wasUnderlined ) { // it's not underlined any more, remove the attributes we set gtk_label_set_attributes(GTK_LABEL(m_widget), NULL); } else // the text is underlined now { PangoAttrList *attrs = pango_attr_list_new(); PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); a->start_index = 0; a->end_index = (guint)-1; pango_attr_list_insert(attrs, a); gtk_label_set_attributes(GTK_LABEL(m_widget), attrs); pango_attr_list_unref(attrs); } } // adjust the label size to the new label unless disabled if (!HasFlag(wxST_NO_AUTORESIZE)) { SetSize( GetBestSize() ); } return ret; }
// Although we don't use this function yet, but we must create it here. // first, for the prepare the unicode drawing support in wxUniv/x11 port. // If we use pango to draw the text, then we must set some attributes // for pango layout, such as "strikethrough" and "underline". bool wxFont::SetPangoAttrs(PangoLayout* layout) const { if ( !IsOk() || !(GetUnderlined() || GetStrikethrough()) ) return false; PangoAttrList* attrs = pango_attr_list_new(); PangoAttribute* a; if ( GetUnderlined() ) { a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_insert(attrs, a); } if ( GetStrikethrough() ) { a = pango_attr_strikethrough_new(true); pango_attr_list_insert(attrs, a); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); return true; }
/* This function is used by gtk_text_cell_accessible_get_offset_at_point() * and gtk_text_cell_accessible_get_character_extents(). There is no * cached PangoLayout so we must create a temporary one using this function. */ static PangoLayout * create_pango_layout (GtkTextCellAccessible *text) { GdkRGBA *foreground_rgba; PangoAttrList *attr_list, *attributes; PangoLayout *layout; PangoUnderline uline, underline; PangoFontMask mask; PangoFontDescription *font_desc; gboolean foreground_set, strikethrough_set, strikethrough; gboolean scale_set, underline_set, rise_set; gchar *renderer_text; gdouble scale; gint rise; GtkRendererCellAccessible *gail_renderer; GtkCellRendererText *gtk_renderer; gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); g_object_get (gtk_renderer, "text", &renderer_text, "attributes", &attributes, "foreground-set", &foreground_set, "foreground-rgba", &foreground_rgba, "strikethrough-set", &strikethrough_set, "strikethrough", &strikethrough, "font-desc", &font_desc, "scale-set", &scale_set, "scale", &scale, "underline-set", &underline_set, "underline", &underline, "rise-set", &rise_set, "rise", &rise, NULL); layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text); if (attributes) attr_list = pango_attr_list_copy (attributes); else attr_list = pango_attr_list_new (); if (foreground_set) { add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535, foreground_rgba->green * 65535, foreground_rgba->blue * 65535)); } if (strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (strikethrough)); mask = pango_font_description_get_set_fields (font_desc); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (font_desc))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc))); if (scale_set && scale != 1.0) add_attr (attr_list, pango_attr_scale_new (scale)); if (underline_set) uline = underline; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (underline)); if (rise_set) add_attr (attr_list, pango_attr_rise_new (rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); pango_font_description_free (font_desc); pango_attr_list_unref (attributes); g_free (renderer_text); gdk_rgba_free (foreground_rgba); return layout; }
/** * gimp_label_set_attributes: * @label: a #GtkLabel * @...: a list of PangoAttrType and value pairs terminated by -1. * * Sets Pango attributes on a #GtkLabel in a more convenient way than * gtk_label_set_attributes(). * * This function is useful if you want to change the font attributes * of a #GtkLabel. This is an alternative to using PangoMarkup which * is slow to parse and akward to handle in an i18n-friendly way. * * The attributes are set on the complete label, from start to end. If * you need to set attributes on part of the label, you will have to * use the PangoAttributes API directly. * * Since: 2.2 **/ void gimp_label_set_attributes (GtkLabel *label, ...) { PangoAttribute *attr = NULL; PangoAttrList *attrs; va_list args; g_return_if_fail (GTK_IS_LABEL (label)); attrs = pango_attr_list_new (); va_start (args, label); do { PangoAttrType attr_type = va_arg (args, PangoAttrType); if (attr_type == -1) attr_type = PANGO_ATTR_INVALID; switch (attr_type) { case PANGO_ATTR_LANGUAGE: attr = pango_attr_language_new (va_arg (args, PangoLanguage *)); break; case PANGO_ATTR_FAMILY: attr = pango_attr_family_new (va_arg (args, const gchar *)); break; case PANGO_ATTR_STYLE: attr = pango_attr_style_new (va_arg (args, PangoStyle)); break; case PANGO_ATTR_WEIGHT: attr = pango_attr_weight_new (va_arg (args, PangoWeight)); break; case PANGO_ATTR_VARIANT: attr = pango_attr_variant_new (va_arg (args, PangoVariant)); break; case PANGO_ATTR_STRETCH: attr = pango_attr_stretch_new (va_arg (args, PangoStretch)); break; case PANGO_ATTR_SIZE: attr = pango_attr_size_new (va_arg (args, gint)); break; case PANGO_ATTR_FONT_DESC: attr = pango_attr_font_desc_new (va_arg (args, const PangoFontDescription *)); break; case PANGO_ATTR_FOREGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_foreground_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_BACKGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_background_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_UNDERLINE: attr = pango_attr_underline_new (va_arg (args, PangoUnderline)); break; case PANGO_ATTR_STRIKETHROUGH: attr = pango_attr_strikethrough_new (va_arg (args, gboolean)); break; case PANGO_ATTR_RISE: attr = pango_attr_rise_new (va_arg (args, gint)); break; case PANGO_ATTR_SCALE: attr = pango_attr_scale_new (va_arg (args, gdouble)); break; default: g_warning ("%s: invalid PangoAttribute type %d", G_STRFUNC, attr_type); case PANGO_ATTR_INVALID: attr = NULL; break; } if (attr) { attr->start_index = 0; attr->end_index = -1; pango_attr_list_insert (attrs, attr); } } while (attr); va_end (args); gtk_label_set_attributes (label, attrs); pango_attr_list_unref (attrs); }
static gboolean gimp_tag_popup_list_expose (GtkWidget *widget, GdkEventExpose *event, GimpTagPopup *popup) { GdkWindow *window = gtk_widget_get_window (widget); GtkStyle *style = gtk_widget_get_style (widget); cairo_t *cr; PangoAttribute *attribute; PangoAttrList *attributes; gint i; cr = gdk_cairo_create (event->window); gdk_cairo_region (cr, event->region); cairo_clip (cr); cairo_set_line_width (cr, 1.0); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); for (i = 0; i < popup->tag_count; i++) { PopupTagData *tag_data = &popup->tag_data[i]; pango_layout_set_text (popup->layout, gimp_tag_get_name (tag_data->tag), -1); switch (tag_data->state) { case GTK_STATE_SELECTED: attributes = pango_attr_list_copy (popup->combo_entry->selected_item_attr); break; case GTK_STATE_INSENSITIVE: attributes = pango_attr_list_copy (popup->combo_entry->insensitive_item_attr); break; default: attributes = pango_attr_list_copy (popup->combo_entry->normal_item_attr); break; } if (tag_data == popup->prelight && tag_data->state != GTK_STATE_INSENSITIVE) { attribute = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr_list_insert (attributes, attribute); } pango_layout_set_attributes (popup->layout, attributes); pango_attr_list_unref (attributes); if (tag_data->state == GTK_STATE_SELECTED) { gdk_cairo_set_source_color (cr, &popup->combo_entry->selected_item_color); cairo_rectangle (cr, tag_data->bounds.x - 1, tag_data->bounds.y - popup->scroll_y, tag_data->bounds.width + 2, tag_data->bounds.height); cairo_fill (cr); cairo_translate (cr, 0.5, 0.5); cairo_move_to (cr, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y - 1); cairo_line_to (cr, tag_data->bounds.x + tag_data->bounds.width - 1, tag_data->bounds.y - popup->scroll_y - 1); cairo_move_to (cr, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height); cairo_line_to (cr, tag_data->bounds.x + tag_data->bounds.width - 1, tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height); cairo_stroke (cr); cairo_translate (cr, -0.5, -0.5); } cairo_move_to (cr, (tag_data->bounds.x + GIMP_TAG_POPUP_PADDING), (tag_data->bounds.y - popup->scroll_y + GIMP_TAG_POPUP_PADDING)); pango_cairo_show_layout (cr, popup->layout); if (tag_data == popup->prelight && tag_data->state != GTK_STATE_INSENSITIVE && ! popup->single_select_disabled) { gtk_paint_focus (style, window, tag_data->state, &event->area, widget, NULL, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y, tag_data->bounds.width, tag_data->bounds.height); } } cairo_destroy (cr); return FALSE; }
static PangoLayout * rsvg_text_create_layout (RsvgDrawingCtx * ctx, RsvgState * state, const char *text, PangoContext * context) { PangoFontDescription *font_desc; PangoLayout *layout; PangoAttrList *attr_list; PangoAttribute *attribute; if (state->lang) pango_context_set_language (context, pango_language_from_string (state->lang)); if (state->unicode_bidi == UNICODE_BIDI_OVERRIDE || state->unicode_bidi == UNICODE_BIDI_EMBED) pango_context_set_base_dir (context, state->text_dir); font_desc = pango_font_description_copy (pango_context_get_font_description (context)); if (state->font_family) pango_font_description_set_family_static (font_desc, state->font_family); pango_font_description_set_style (font_desc, state->font_style); pango_font_description_set_variant (font_desc, state->font_variant); pango_font_description_set_weight (font_desc, state->font_weight); pango_font_description_set_stretch (font_desc, state->font_stretch); pango_font_description_set_size (font_desc, _rsvg_css_normalize_font_size (state, ctx) * PANGO_SCALE / ctx->dpi_y * 72); layout = pango_layout_new (context); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); attr_list = pango_attr_list_new (); attribute = pango_attr_letter_spacing_new (_rsvg_css_normalize_length (&state->letter_spacing, ctx, 'h') * PANGO_SCALE); attribute->start_index = 0; attribute->end_index = G_MAXINT; pango_attr_list_insert (attr_list, attribute); if (state->has_font_decor && text) { if (state->font_decor & TEXT_UNDERLINE) { attribute = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attribute->start_index = 0; attribute->end_index = -1; pango_attr_list_insert (attr_list, attribute); } if (state->font_decor & TEXT_STRIKE) { attribute = pango_attr_strikethrough_new (TRUE); attribute->start_index = 0; attribute->end_index = -1; pango_attr_list_insert (attr_list, attribute); } } pango_layout_set_attributes (layout, attr_list); pango_attr_list_unref (attr_list); if (text) pango_layout_set_text (layout, text, -1); else pango_layout_set_text (layout, NULL, 0); pango_layout_set_alignment (layout, (state->text_dir == PANGO_DIRECTION_LTR || state->text_dir == PANGO_DIRECTION_TTB_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); return layout; }
/* * This function is used by gail_text_cell_get_offset_at_point() * and gail_text_cell_get_character_extents(). There is no * cached PangoLayout for gailtextcell so we must create a temporary * one using this function. */ static PangoLayout* create_pango_layout(GtkCellRendererText *gtk_renderer, GtkWidget *widget) { PangoAttrList *attr_list; PangoLayout *layout; PangoUnderline uline; PangoFontMask mask; layout = gtk_widget_create_pango_layout (widget, gtk_renderer->text); if (gtk_renderer->extra_attrs) attr_list = pango_attr_list_copy (gtk_renderer->extra_attrs); else attr_list = pango_attr_list_new (); if (gtk_renderer->foreground_set) { PangoColor color; color = gtk_renderer->foreground; add_attr (attr_list, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (gtk_renderer->strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (gtk_renderer->strikethrough)); mask = pango_font_description_get_set_fields (gtk_renderer->font); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (gtk_renderer->font))); if (gtk_renderer->scale_set && gtk_renderer->font_scale != 1.0) add_attr (attr_list, pango_attr_scale_new (gtk_renderer->font_scale)); if (gtk_renderer->underline_set) uline = gtk_renderer->underline_style; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (gtk_renderer->underline_style)); if (gtk_renderer->rise_set) add_attr (attr_list, pango_attr_rise_new (gtk_renderer->rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); return layout; }
void GuiSolidLabelElementRenderer::OnElementStateChanged() { FontProperties font = element->GetFont(); Color color = element->GetColor(); int layoutWidth, layoutHeight; AString family = wtoa(font.fontFamily); pango_font_description_set_family(pangoFontDesc, family.Buffer()); pango_font_description_set_absolute_size(pangoFontDesc, font.size * PANGO_SCALE); if(font.italic) pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_ITALIC); else pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_NORMAL); if(attrList) { pango_attr_list_unref(attrList); } attrList = pango_attr_list_new(); pango_attr_list_insert(attrList, pango_attr_underline_new( font.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE) ); pango_attr_list_insert(attrList, pango_attr_strikethrough_new ( font.strikeline ? TRUE : FALSE ) ); pango_attr_list_insert(attrList, pango_attr_weight_new ( font.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_MEDIUM ) ); if(layout) { g_object_unref(layout); layout = NULL; } if(cairoContext) { layout = pango_cairo_create_layout(cairoContext); WString wtext = (font.fontFamily == L"Webdings") ? helpers::WebdingsMap(element->GetText()) : element->GetText(); AString text = wtoa(wtext); pango_layout_set_font_description(layout, pangoFontDesc); pango_layout_set_attributes(layout, attrList); pango_layout_set_text(layout, text.Buffer(), text.Length()); pango_layout_set_alignment(layout, element->GetHorizontalAlignment() == Alignment::Left ? PANGO_ALIGN_LEFT : element->GetHorizontalAlignment() == Alignment::Center ? PANGO_ALIGN_CENTER : element->GetHorizontalAlignment() == Alignment::Right ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT ); pango_cairo_update_layout(cairoContext, layout); pango_layout_get_pixel_size( layout, &layoutWidth, &layoutHeight); minSize.x = layoutWidth; minSize.y = layoutHeight; } }
void ttext::recalculate(const bool force) const { if(calculation_dirty_ || force) { assert(layout_); calculation_dirty_ = false; surface_dirty_ = true; tfont font(get_font_families(font_class_), font_size_, font_style_); pango_layout_set_font_description(layout_, font.get()); if(font_style_ & ttext::STYLE_UNDERLINE) { PangoAttrList *attribute_list = pango_attr_list_new(); pango_attr_list_insert(attribute_list , pango_attr_underline_new(PANGO_UNDERLINE_SINGLE)); pango_layout_set_attributes (layout_, attribute_list); pango_attr_list_unref(attribute_list); } int maximum_width = 0; if(characters_per_line_ != 0) { PangoFont* f = pango_font_map_load_font( pango_cairo_font_map_get_default() , context_ , font.get()); PangoFontMetrics* m = pango_font_get_metrics(f, nullptr); int w = pango_font_metrics_get_approximate_char_width(m); w *= characters_per_line_; maximum_width = ceil(pango_units_to_double(w)); } else { maximum_width = maximum_width_; } if(maximum_width_ != -1) { maximum_width = std::min(maximum_width, maximum_width_); } /* * See set_maximum_width for some more background info as well. * In order to fix the problem first set a width which seems to render * correctly then lower it to fit. For the campaigns the 4 does "the * right thing" for the terrain labels it should use the value 0 to set * the ellipse properly. Need to see whether this is a bug in pango or * a bug in my understanding of the pango api. */ int hack = 4; do { pango_layout_set_width(layout_, maximum_width == -1 ? -1 : (maximum_width + hack) * PANGO_SCALE); pango_layout_get_pixel_extents(layout_, nullptr, &rect_); DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << "' maximum_width " << maximum_width << " hack " << hack << " width " << rect_.x + rect_.width << ".\n"; --hack; } while(maximum_width != -1 && hack >= 0 && rect_.x + rect_.width > maximum_width); DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << "' font_size " << font_size_ << " markedup_text " << markedup_text_ << " font_style " << std::hex << font_style_ << std::dec << " maximum_width " << maximum_width << " maximum_height " << maximum_height_ << " result " << rect_ << ".\n"; if(maximum_width != -1 && rect_.x + rect_.width > maximum_width) { DBG_GUI_L << "ttext::" << __func__ << " text '" << gui2::debug_truncate(text_) << " ' width " << rect_.x + rect_.width << " greater as the wanted maximum of " << maximum_width << ".\n"; } } }
void scim_bridge_client_imcontext_set_preedit_attributes (ScimBridgeClientIMContext *imcontext, ScimBridgeAttribute** const preedit_attributes, int attribute_count) { if (imcontext->preedit_attributes != NULL) pango_attr_list_unref (imcontext->preedit_attributes); imcontext->preedit_attributes = pango_attr_list_new (); int preedit_string_length = 0; int preedit_wstring_length = 0; if (imcontext->preedit_string != NULL) { preedit_string_length = strlen (imcontext->preedit_string); preedit_wstring_length = g_utf8_strlen (imcontext->preedit_string, -1); } boolean *has_attribute = alloca (sizeof (boolean) * preedit_string_length); int i; for (i = 0; i < preedit_string_length; ++i) { has_attribute[i] = FALSE; } for (i = 0; i < attribute_count; ++i) { const ScimBridgeAttribute *attr = preedit_attributes[i]; const int begin_pos = scim_bridge_attribute_get_begin (attr); const int end_pos = scim_bridge_attribute_get_end (attr); if (begin_pos <= end_pos && 0 <= begin_pos && end_pos <= preedit_wstring_length) { const int start_index = g_utf8_offset_to_pointer (imcontext->preedit_string, begin_pos) - imcontext->preedit_string; const int end_index = g_utf8_offset_to_pointer (imcontext->preedit_string, end_pos) - imcontext->preedit_string; const scim_bridge_attribute_type_t attr_type = scim_bridge_attribute_get_type (attr); const scim_bridge_attribute_value_t attr_value = scim_bridge_attribute_get_value (attr); boolean valid_attribute = FALSE; if (attr_type == ATTRIBUTE_DECORATE) { if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_UNDERLINE) { valid_attribute = TRUE; PangoAttribute *pango_attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } else if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_REVERSE) { valid_attribute = TRUE; PangoAttribute *pango_attr0 = pango_attr_foreground_new (preedit_normal_background.red, preedit_normal_background.green, preedit_normal_background.blue); pango_attr0->start_index = start_index; pango_attr0->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr0); PangoAttribute *pango_attr1 = pango_attr_background_new (preedit_normal_foreground.red, preedit_normal_foreground.green, preedit_normal_foreground.blue); pango_attr1->start_index = start_index; pango_attr1->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr1); } else if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_HIGHLIGHT) { valid_attribute = TRUE; PangoAttribute *pango_attr0 = pango_attr_foreground_new (preedit_active_foreground.red, preedit_active_foreground.green, preedit_active_foreground.blue); pango_attr0->start_index = start_index; pango_attr0->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr0); PangoAttribute *pango_attr1 = pango_attr_background_new (preedit_active_background.red, preedit_active_background.green, preedit_active_background.blue); pango_attr1->start_index = start_index; pango_attr1->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr1); } else { scim_bridge_perrorln ("Unknown preedit decoration!"); } } else if (attr_type == ATTRIBUTE_FOREGROUND) { valid_attribute = TRUE; const unsigned int red = scim_bridge_attribute_get_red (attr) * 256; const unsigned int green = scim_bridge_attribute_get_green (attr) * 256; const unsigned int blue = scim_bridge_attribute_get_blue (attr) * 256; PangoAttribute *pango_attr = pango_attr_foreground_new (red, green, blue); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } else if (attr_type == ATTRIBUTE_BACKGROUND) { valid_attribute = TRUE; const unsigned int red = scim_bridge_attribute_get_red (attr) * 256; const unsigned int green = scim_bridge_attribute_get_green (attr) * 256; const unsigned int blue = scim_bridge_attribute_get_blue (attr) * 256; PangoAttribute *pango_attr = pango_attr_background_new (red, green, blue); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } if (valid_attribute) { int j; for (j = start_index; j < end_index; ++j) { has_attribute[j] = TRUE; } } } } // Add underlines for the all characters without attributes. for (i = 0; i < preedit_string_length; ++i) { if (has_attribute[i] == FALSE) { PangoAttribute *pango_attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr->start_index = i; for (; i < preedit_string_length && has_attribute[i] == FALSE; ++i); pango_attr->end_index = i; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } } }
bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const { if (!IsOk() || !(GetUnderlined() || GetStrikethrough())) return false; PangoAttrList* attrs = pango_attr_list_new(); PangoAttribute* a; if (wx_pango_version_check(1,16,0)) { // a PangoLayout which has leading/trailing spaces with underlined font // is not correctly drawn by this pango version: Pango won't underline the spaces. // This can be a problem; e.g. wxHTML rendering of underlined text relies on // this behaviour. To workaround this problem, we use a special hack here // suggested by pango maintainer Behdad Esfahbod: we prepend and append two // empty space characters and give them a dummy colour attribute. // This will force Pango to underline the leading/trailing spaces, too. const char* text = pango_layout_get_text(layout); const size_t n = strlen(text); if ((n > 0 && text[0] == ' ') || (n > 1 && text[n - 1] == ' ')) { wxCharBuffer buf(n + 6); // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data(), "\342\200\214", 3); // copy the user string memcpy(buf.data() + 3, text, n); // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data() + 3 + n, "\342\200\214", 3); pango_layout_set_text(layout, buf, n + 6); // Add dummy attributes (use colour as it's invisible anyhow for 0 // width spaces) to ensure that the spaces in the beginning/end of the // string are underlined too. a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = 0; a->end_index = 3; pango_attr_list_insert(attrs, a); a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = n + 3; a->end_index = n + 6; pango_attr_list_insert(attrs, a); } } if (GetUnderlined()) { a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_insert(attrs, a); } if (GetStrikethrough()) { a = pango_attr_strikethrough_new(true); pango_attr_list_insert(attrs, a); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); return true; }
static void text_entry_update_layout(struct text_entry *entry) { char *text; PangoAttrList *attr_list; assert(entry->cursor <= (strlen(entry->text) + (entry->preedit.text ? strlen(entry->preedit.text) : 0))); if (entry->preedit.text) { text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1); strncpy(text, entry->text, entry->cursor); strcpy(text + entry->cursor, entry->preedit.text); strcpy(text + entry->cursor + strlen(entry->preedit.text), entry->text + entry->cursor); } else { text = strdup(entry->text); } if (entry->cursor != entry->anchor) { int start_index = MIN(entry->cursor, entry->anchor); int end_index = MAX(entry->cursor, entry->anchor); PangoAttribute *attr; attr_list = pango_attr_list_copy(entry->preedit.attr_list); if (!attr_list) attr_list = pango_attr_list_new(); attr = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_insert(attr_list, attr); attr = pango_attr_foreground_new(65535, 65535, 65535); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_insert(attr_list, attr); } else { attr_list = pango_attr_list_ref(entry->preedit.attr_list); } if (entry->preedit.text && !entry->preedit.attr_list) { PangoAttribute *attr; if (!attr_list) attr_list = pango_attr_list_new(); attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr->start_index = entry->cursor; attr->end_index = entry->cursor + strlen(entry->preedit.text); pango_attr_list_insert(attr_list, attr); } if (entry->layout) { pango_layout_set_text(entry->layout, text, -1); pango_layout_set_attributes(entry->layout, attr_list); } free(text); pango_attr_list_unref(attr_list); }