Esempio n. 1
0
/* Set the colour of the "valid from" and "valid until" elements on the
 * Certificate page to red if they are incorrectly in the future or
 * past. */
static void show_date_state(char* label, void* data, int length) {
	gchar* labelname = g_strndup(label, strstr(label, ":") - label);
	GtkLabel* l = GTK_LABEL(gtk_builder_get_object(builder, labelname));
	PangoAttrList *attrs = pango_attr_list_new();
	PangoAttribute *attr;
	gboolean* is_invalid = (gboolean*)data;

	g_free(labelname);
	if(*is_invalid) {
		attr = pango_attr_foreground_new(G_MAXUINT16, 0, 0);
	} else {
#if HAVE_GTK == 3
		GdkRGBA color;
		GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(l));

		gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
		attr = pango_attr_foreground_new(color.red * G_MAXUINT16, color.green * G_MAXUINT16, color.blue * G_MAXUINT16);
#else
#if HAVE_GTK == 2
		/* In GTK+ 2, there is no GtkStyleContext yet. It
		 * should, in theory, be possible to figure out what the
		 * default foreground color is by using a GTK+
		 * 2-specific API, but that's too much work and GTK+ 2
		 * is a minority now anyway, so... */
		attr = pango_attr_foreground_new(0, 0, 0);
#else
		/* The configure script only allows GTK+2 or GTK+3. */
#error should not happen
#endif
#endif
	}
	pango_attr_list_insert(attrs, attr);
	gtk_label_set_attributes(l, attrs);
}
Esempio n. 2
0
static void
gimp_combo_tag_entry_style_set (GtkWidget *widget,
                                GtkStyle  *previous_style)
{
  GimpComboTagEntry *entry = GIMP_COMBO_TAG_ENTRY (widget);
  GtkStyle          *style = gtk_widget_get_style (widget);
  GdkColor           color;
  PangoAttribute    *attribute;

  if (GTK_WIDGET_CLASS (parent_class)->style_set)
    GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);

  if (entry->normal_item_attr)
    pango_attr_list_unref (entry->normal_item_attr);
  entry->normal_item_attr = pango_attr_list_new ();

  if (style->font_desc)
    {
      attribute = pango_attr_font_desc_new (style->font_desc);
      pango_attr_list_insert (entry->normal_item_attr, attribute);
    }
  color = style->text[GTK_STATE_NORMAL];
  attribute = pango_attr_foreground_new (color.red, color.green, color.blue);
  pango_attr_list_insert (entry->normal_item_attr, attribute);

  if (entry->selected_item_attr)
    pango_attr_list_unref (entry->selected_item_attr);
  entry->selected_item_attr = pango_attr_list_copy (entry->normal_item_attr);

  color = style->text[GTK_STATE_SELECTED];
  attribute = pango_attr_foreground_new (color.red, color.green, color.blue);
  pango_attr_list_insert (entry->selected_item_attr, attribute);
  color = style->base[GTK_STATE_SELECTED];
  attribute = pango_attr_background_new (color.red, color.green, color.blue);
  pango_attr_list_insert (entry->selected_item_attr, attribute);

  if (entry->insensitive_item_attr)
    pango_attr_list_unref (entry->insensitive_item_attr);
  entry->insensitive_item_attr = pango_attr_list_copy (entry->normal_item_attr);

  color = style->text[GTK_STATE_INSENSITIVE];
  attribute = pango_attr_foreground_new (color.red, color.green, color.blue);
  pango_attr_list_insert (entry->insensitive_item_attr, attribute);
  color = style->base[GTK_STATE_INSENSITIVE];
  attribute = pango_attr_background_new (color.red, color.green, color.blue);
  pango_attr_list_insert (entry->insensitive_item_attr, attribute);

  entry->selected_item_color = style->base[GTK_STATE_SELECTED];

  if (entry->arrow_pixbuf)
    {
      g_object_unref (entry->arrow_pixbuf);
      entry->arrow_pixbuf = NULL;
    }
}
Esempio n. 3
0
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 void
create_layout (GtkSourceGutterRendererText *renderer,
               GtkWidget                   *widget)
{
	PangoLayout *layout;
	PangoAttribute *attr;
	GtkStyleContext *context;
	GdkRGBA color;
	PangoAttrList *attr_list;

	layout = gtk_widget_create_pango_layout (widget, NULL);

	context = gtk_widget_get_style_context (widget);
	gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);

	attr = pango_attr_foreground_new (color.red * 65535,
	                                  color.green * 65535,
	                                  color.blue * 65535);

	attr->start_index = 0;
	attr->end_index = G_MAXINT;

	attr_list = pango_attr_list_new ();
	pango_attr_list_insert (attr_list, attr);

	renderer->priv->fg_attr = attr;
	renderer->priv->cached_layout = layout;
	renderer->priv->cached_attr_list = attr_list;
}
Esempio n. 5
0
static void create_cursor_attr()
{
    if (attr_list)
        pango_attr_list_unref(attr_list);

    GdkColor color_bg, color_fg;
    if (hime_win_color_use)
        gdk_color_parse(tsin_cursor_color, &color_bg);
    else
        gdk_color_parse(TSIN_CURSOR_COLOR_DEFAULT, &color_bg);
    gdk_color_parse("white", &color_fg);

    attr_list = pango_attr_list_new ();
    attr_list_blank = pango_attr_list_new ();

    PangoAttribute *blue_bg = pango_attr_background_new(
                                  color_bg.red, color_bg.green, color_bg.blue);
    blue_bg->start_index = 0;
    blue_bg->end_index = 128;
    pango_attr_list_insert (attr_list, blue_bg);

    PangoAttribute *white_fg = pango_attr_foreground_new(
                                   color_fg.red, color_fg.green, color_fg.blue);
    white_fg->start_index = 0;
    white_fg->end_index = 128;
    pango_attr_list_insert (attr_list, white_fg);
}
Esempio n. 6
0
void LeftMargin::setupMargin(GtkTextView *textView)
    {
    if(!mMarginLayout)
        {
        GtkWidget *widget = GTK_WIDGET(textView);

        mMarginLayout = gtk_widget_create_pango_layout(widget, "");
        updateTextInfo(textView);

        pango_layout_set_width(mMarginLayout, mTextWidth);
        pango_layout_set_alignment(mMarginLayout, PANGO_ALIGN_RIGHT);

        GtkStyleContext *widgetStyle = gtk_widget_get_style_context(widget);
        GdkRGBA color;
        gtk_style_context_get_color(widgetStyle, GTK_STATE_FLAG_NORMAL, &color);
        mMarginAttr = pango_attr_foreground_new(convertGdkColorToPango(color.red),
                convertGdkColorToPango(color.green), convertGdkColorToPango(color.blue));
        mMarginAttrList = pango_attr_list_new();

        mMarginAttr->start_index = 0;
        mMarginAttr->end_index = G_MAXUINT;
        pango_attr_list_insert(mMarginAttrList, mMarginAttr);
        pango_layout_set_attributes(mMarginLayout, mMarginAttrList);
        }
    }
static void
match_label_color (GstyleColorWidget *self,
                   GstyleColor       *color)
{
  PangoLayout *layout;
  PangoAttrList *attr_list;
  PangoAttribute *attr;
  GdkRGBA rgba;
  GdkRGBA dst_rgba;

  g_assert (GSTYLE_IS_COLOR_WIDGET (self));
  g_assert (GSTYLE_IS_COLOR (color));

  layout = gtk_label_get_layout (self->label);
  attr_list = pango_layout_get_attributes (layout);
  if (attr_list == NULL)
    {
      attr_list = pango_attr_list_new ();
      gtk_label_set_attributes (self->label, attr_list);
      pango_attr_list_unref (attr_list);
    }

  gstyle_color_fill_rgba (color, &rgba);
  gstyle_utils_get_contrasted_rgba (rgba, &dst_rgba);
  attr = pango_attr_foreground_new (dst_rgba.red * 0xffff, dst_rgba.green * 0xffff, dst_rgba.blue * 0xffff);
  pango_attr_list_change (attr_list, attr);
  attr = pango_attr_background_new (rgba.red * 0xffff, rgba.green * 0xffff, rgba.blue * 0xffff);
  pango_attr_list_change (attr_list, attr);
}
Esempio n. 8
0
bool
OxLabel_SetTextColor(OxLabelObject* ox, int iRed, int iGreen, int iBlue)
{
	PangoAttrList* pAL = pango_attr_list_new();
	pango_attr_list_insert(pAL, pango_attr_foreground_new(iRed, iGreen, iBlue));
	gtk_label_set_attributes(GTK_LABEL(ox->pGtk), pAL);
	return TRUE;
}
Esempio n. 9
0
static void
set_fade (AboutRenderer *r, AboutState *state, double f)
{
	GtkStyleContext *ctxt = gtk_widget_get_style_context (state->anim_area);
	PangoAttrList *attrlist = pango_layout_get_attributes (r->layout);
	GdkRGBA col, bg, fg;
	PangoAttribute *attr;

	gtk_style_context_get_color (ctxt, GTK_STATE_FLAG_NORMAL, &fg);
	gtk_style_context_get_background_color (ctxt, GTK_STATE_FLAG_NORMAL, &bg);
	col = blend_colors (&bg, &fg, f);
	attr = pango_attr_foreground_new
		(col.red * 65535., col.green * 65535., col.blue * 65535.);
	pango_attr_list_change (attrlist, attr);
	pango_layout_set_attributes (r->layout, attrlist);
}
Esempio n. 10
0
static void _mt_draw_string(MT_WINDOW *win, MT_STRING *str, int x_offset, int y_offset, MT_COLOR *color)
{
   MT_GTK_STRING *s = str;
   PangoLayout *layout = s->layout;
   int state_type = s->state_type;

   if (!color && s->color) color = s->color;
   if (color && !pango_layout_get_text(layout)) color = NULL;

   if (color) {
      PangoAttrList *attrlist;
      PangoAttribute *attr;

      layout = pango_layout_copy(layout);

      attrlist = pango_layout_get_attributes(layout);
      if (attrlist) {
         pango_attr_list_ref(attrlist);
      }
      else {
         attrlist = pango_attr_list_new();
      }

      if (color) {
         attr = pango_attr_foreground_new(color->r << 8, color->g << 8, color->b << 8);
         attr->start_index = 0;
         attr->end_index = strlen(pango_layout_get_text(layout));
         pango_attr_list_insert_before(attrlist, attr);
      }
      
      pango_layout_set_attributes(layout, attrlist);
      pango_attr_list_unref(attrlist);

      state_type = GTK_STATE_NORMAL;
   }

   s->parent_class->draw_layout(s->style, (GdkWindow *)win, state_type, s->use_text,
                                s->area, s->widget, s->detail, s->x + x_offset, s->y + y_offset, layout);

   if (color) {
      g_object_unref(layout);
   }
}
Esempio n. 11
0
/* 
 * 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;
}
Esempio n. 12
0
static gint
line_numbers_expose (GtkWidget      *widget,
                     GdkEventExpose *event)
{
	GtkTextView *text_view;
	GdkWindow *win;
//	GtkStyle *style;
	PangoLayout *layout;
	PangoAttrList *alist;
	PangoAttribute *attr;
	GArray *numbers;
	GArray *pixels;
	gint y1, y2;
	gint count;
	gint layout_width;
	gint justify_width = 0;
	gint i;
//	gchar *str;
	gchar str [8];  /* we don't expect more than ten million lines */
	GdkGC *gc;
	gint height;
	
	if (line_number_visible){{{{{	// omit calculation
	
	text_view = GTK_TEXT_VIEW (widget);
	
	/* See if this expose is on the line numbers window */
/*	left_win = gtk_text_view_get_window (text_view,
	                                     GTK_TEXT_WINDOW_LEFT);
	right_win = gtk_text_view_get_window (text_view,
	                                      GTK_TEXT_WINDOW_RIGHT);
	
	if (event->window == left_win)
	{
		type = GTK_TEXT_WINDOW_LEFT;
		target = event->window;
	}
	else if (event->window == right_win)
	{
		type = GTK_TEXT_WINDOW_RIGHT;
		target = right_win;
	}
	else
		return FALSE;
*/	
	win = gtk_text_view_get_window (text_view,
	                                GTK_TEXT_WINDOW_LEFT);
	if (event->window != win)
		return FALSE;
	
//	style = gtk_style_copy (widget->style);
//	style = gtk_style_copy (gtk_widget_get_default_style());
	
	y1 = event->area.y;
	y2 = y1 + event->area.height;
	
	gtk_text_view_window_to_buffer_coords (text_view,
	                                       GTK_TEXT_WINDOW_LEFT,
	                                       0,
	                                       y1,
	                                       NULL,
	                                       &y1);
	
	gtk_text_view_window_to_buffer_coords (text_view,
	                                       GTK_TEXT_WINDOW_LEFT,
	                                       0,
	                                       y2,
	                                       NULL,
	                                       &y2);
	
	numbers = g_array_new (FALSE, FALSE, sizeof (gint));
	pixels = g_array_new (FALSE, FALSE, sizeof (gint));
	
	get_lines (text_view,
	           y1,
	           y2,
	           pixels,
	           numbers,
	           &count);
	
	/* a zero-lined document should display a "1"; we don't need to worry about
	scrolling effects of the text widget in this special case */
	
	if (count == 0)
	{
		gint y = 0;
		gint n = 0;
		count = 1;
		g_array_append_val (pixels, y);
		g_array_append_val (numbers, n);
	}
	
DV({g_print("Painting line numbers %d - %d\n",
			g_array_index(numbers, gint, 0),
			g_array_index(numbers, gint, count - 1));	});
	
	layout = gtk_widget_create_pango_layout (widget, "");
	
//	str = g_strdup_printf ("%d", gtk_text_buffer_get_line_count(text_view->buffer));
	g_snprintf (str, sizeof (str),
			"%d", MAX (99, gtk_text_buffer_get_line_count(text_view->buffer)));
	pango_layout_set_text (layout, str, -1);
//	g_free (str);
	
	pango_layout_get_pixel_size (layout, &layout_width, NULL);
	
	min_number_window_width = calculate_min_number_window_width(widget);
	if (layout_width > min_number_window_width)
		gtk_text_view_set_border_window_size (text_view,
			GTK_TEXT_WINDOW_LEFT, layout_width + margin + submargin);
	else {
//		if ((gtk_text_view_get_border_window_size (text_view, GTK_TEXT_WINDOW_LEFT) - 5) > layout_width) {
			gtk_text_view_set_border_window_size (text_view,
				GTK_TEXT_WINDOW_LEFT, min_number_window_width + margin + submargin);
//		}
		justify_width = min_number_window_width - layout_width;
	}
	
	pango_layout_set_width (layout, layout_width);
	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
	
	alist = pango_attr_list_new();
	attr = pango_attr_foreground_new(
		widget->style->text_aa->red,
		widget->style->text_aa->green,
		widget->style->text_aa->blue);
	attr->start_index = 0;
	attr->end_index = G_MAXUINT;
	pango_attr_list_insert(alist, attr);
	pango_layout_set_attributes(layout, alist);
	pango_attr_list_unref(alist);
	
	/* Draw fully internationalized numbers! */
	
	i = 0;
	while (i < count)
	{
		gint pos;
		
		gtk_text_view_buffer_to_window_coords (text_view,
		                                       GTK_TEXT_WINDOW_LEFT,
		                                       0,
		                                       g_array_index (pixels, gint, i),
		                                       NULL,
		                                       &pos);
		
//		str = g_strdup_printf ("%d", g_array_index (numbers, gint, i) + 1);
		g_snprintf (str, sizeof (str),
				"%d", g_array_index (numbers, gint, i) + 1);
		
		pango_layout_set_text (layout, str, -1);
		
		gtk_paint_layout (widget->style,
		                  win,
		                  GTK_WIDGET_STATE (widget),
		                  FALSE,
		                  NULL,
		                  widget,
		                  NULL,
#if GTK_CHECK_VERSION(2, 6, 0)  // Is this solution???
		                  layout_width + justify_width + margin / 2 + 1,
#else
		                  layout_width + justify_width + margin / 2,
#endif
		                  pos,
		                  layout);
//		g_free (str);
		
		++i;
	}
	
	g_array_free (pixels, TRUE);
	g_array_free (numbers, TRUE);
	
	g_object_unref (G_OBJECT (layout));
//	g_object_ref (G_OBJECT (style));
	
	/* don't stop emission, need to draw children */
	
	}}}}}
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);
        }
    }
}
Esempio n. 14
0
void init_attr_list() {
    letter_label_attr_list = pango_attr_list_new();
    PangoAttribute *fcolor = pango_attr_foreground_new(0xffff, 0, 0);
    pango_attr_list_insert(letter_label_attr_list, fcolor);
}
static void
gm_cell_renderer_bitext_update_text (GmCellRendererBitext *renderer,
				     GtkWidget *widget,
				     gboolean is_selected)
{
  GtkStyle *style = NULL;
  PangoAttrList *attr_list = NULL;
  GdkColor color;
  PangoAttribute *attr_color = NULL;
  PangoAttribute *attr_style = NULL;
  PangoAttribute *attr_size = NULL;
  gchar *str = NULL;

  if (renderer->priv->is_valid && renderer->priv->is_selected == is_selected)
    return;

  style = gtk_widget_get_style (widget);

  attr_list = pango_attr_list_new ();

  /* secondary text will be in italic */
  attr_style = pango_attr_style_new (PANGO_STYLE_NORMAL);
  attr_style->start_index = strlen (renderer->priv->primary_text) + 1;
  attr_style->end_index = (guint) - 1;
  pango_attr_list_insert (attr_list, attr_style);

  if (!is_selected) {

    color = style->text_aa[GTK_STATE_NORMAL];

    attr_color = pango_attr_foreground_new (color.red,
					    color.green, color.blue);
    attr_color->start_index = attr_style->start_index;
    attr_color->end_index = (guint) - 1;
    pango_attr_list_insert (attr_list, attr_color);
  }

  attr_size = pango_attr_size_new ((int) (pango_font_description_get_size (style->font_desc) * 0.8));	/* we want the secondary text smaller */
  attr_size->start_index = attr_style->start_index;
  attr_size->end_index = (guint) - 1;
  pango_attr_list_insert (attr_list, attr_size);

  if (renderer->priv->secondary_text && strcmp (renderer->priv->secondary_text, ""))
    str = g_strdup_printf ("%s\n%s",
                           renderer->priv->primary_text,
                           renderer->priv->secondary_text);
  else
    str = g_strdup_printf ("%s",
                           renderer->priv->primary_text);

  g_object_set (renderer,
		"visible", TRUE,
		"weight", PANGO_WEIGHT_NORMAL,
		"text", str,
		"attributes", attr_list,
		NULL);
  g_free (str);
  pango_attr_list_unref (attr_list);

  renderer->priv->is_selected = is_selected;
  renderer->priv->is_valid = TRUE;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
static void
cell_renderer_text_update_text (EmpathyCellRendererText *cell,
				GtkWidget              *widget,
				gboolean                selected)
{
	EmpathyCellRendererTextPriv *priv;
	PangoAttrList              *attr_list;
	PangoAttribute             *attr_color, *attr_size;
	GtkStyle                   *style;
	gchar                      *str;

	priv = GET_PRIV (cell);

	if (priv->is_valid && priv->is_selected == selected) {
		return;
	}

	if (priv->is_group) {
		g_object_set (cell,
			      "visible", TRUE,
			      "weight", PANGO_WEIGHT_BOLD,
			      "text", priv->name,
			      "attributes", NULL,
			      "xpad", 1,
			      "ypad", 1,
			      NULL);

		priv->is_selected = selected;
		priv->is_valid = TRUE;
		return;
	}

	style = gtk_widget_get_style (widget);

	attr_list = pango_attr_list_new ();

	attr_size = pango_attr_size_new (pango_font_description_get_size (style->font_desc) / 1.2);
	attr_size->start_index = strlen (priv->name) + 1;
	attr_size->end_index = -1;
	pango_attr_list_insert (attr_list, attr_size);

	if (!selected) {
		GdkColor color;

		color = style->text_aa[GTK_STATE_NORMAL];

		attr_color = pango_attr_foreground_new (color.red, color.green, color.blue);
		attr_color->start_index = attr_size->start_index;
		attr_color->end_index = -1;
		pango_attr_list_insert (attr_list, attr_color);
	}

	if (!priv->status || !priv->status[0] || !priv->show_status) {
		str = g_strdup (priv->name);
	} else {
		str = g_strdup_printf ("%s\n%s", priv->name, priv->status);
	}

	g_object_set (cell,
		      "visible", TRUE,
		      "weight", PANGO_WEIGHT_NORMAL,
		      "text", str,
		      "attributes", attr_list,
		      "xpad", 0,
		      "ypad", 1,
		      NULL);

	g_free (str);
	pango_attr_list_unref (attr_list);

	priv->is_selected = selected;
	priv->is_valid = TRUE;
}
Esempio n. 18
0
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
					  gint page_nr, gpointer user_data)
{
	DocInfo *dinfo = user_data;
	GeanyEditor *editor;
	cairo_t *cr;
	gdouble width, height;
	gdouble x = 0.0, y = 0.0;
	/*gint layout_h;*/
	gint count;
	GString *str;

	if (dinfo == NULL || page_nr >= dinfo->n_pages)
		return;

	editor = dinfo->doc->editor;

	if (dinfo->n_pages > 0)
	{
		gdouble fraction = (page_nr + 1) / (gdouble) dinfo->n_pages;
		gchar *text = g_strdup_printf(_("Page %d of %d"), page_nr, dinfo->n_pages);
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets.progressbar), fraction);
		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text);
		g_free(text);
	}

#ifdef GEANY_PRINT_DEBUG
	geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d",
		page_nr, dinfo->n_pages, dinfo->lines_per_page);
#endif

	str = g_string_sized_new(256);
	cr = gtk_print_context_get_cairo_context(context);
	width = gtk_print_context_get_width(context);
	height = gtk_print_context_get_height(context);

	cairo_set_source_rgb(cr, 0, 0, 0);
#ifdef GEANY_PRINT_DEBUG
	cairo_set_line_width(cr, 0.2);
	cairo_rectangle(cr, 0, 0, width, height);
	cairo_stroke(cr);
#endif
	cairo_move_to(cr, 0, 0);

	pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);
	pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_LEFT);
	pango_layout_set_ellipsize(dinfo->layout, FALSE);
	pango_layout_set_justify(dinfo->layout, FALSE);

	if (printing_prefs.print_page_header)
		add_page_header(dinfo, cr, width, page_nr);

	count = 0;	/* the actual line counter for the current page, might be different from
				 * dinfo->cur_line due to possible line breaks */
	while (count < dinfo->lines_per_page)
	{
		gchar c = 'a';
		gint style = -1;
		PangoAttrList *layout_attr;
		PangoAttribute *attr;
		gint colours[3] = { 0 };
		gboolean add_linenumber = TRUE;
		gboolean at_eol;

		while (count < dinfo->lines_per_page && c != '\0')
		{
			at_eol = FALSE;

			g_string_erase(str, 0, str->len); /* clear the string */

			/* line numbers */
			if (printing_prefs.print_line_numbers && add_linenumber)
			{
				/* if we had a wrapped line on the last page which needs to be continued, don't
				 * add a line number */
				if (dinfo->long_line)
				{
					add_linenumber = FALSE;
				}
				else
				{
					gchar *line_number = NULL;
					gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1);
					gchar *fill = g_strnfill(
						dinfo->max_line_number_margin - cur_line_number_margin - 1, ' ');

					line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1);
					g_string_append(str, line_number);
					dinfo->cur_line++; /* increase document line */
					add_linenumber = FALSE;
					style = STYLE_LINENUMBER;
					c = 'a'; /* dummy value */
					g_free(fill);
					g_free(line_number);
				}
			}
			/* data */
			else
			{
				style = sci_get_style_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				if (c == '\0' || style == -1)
				{	/* if c gets 0, we are probably out of document boundaries,
					 * so stop to break out of outer loop */
					count = dinfo->lines_per_page;
					break;
				}
				dinfo->cur_pos++;

				/* convert tabs to spaces which seems to be better than using Pango tabs */
				if (c == '\t')
				{
					gint tab_width = sci_get_tab_width(editor->sci);
					gchar *s = g_strnfill(tab_width, ' ');
					g_string_append(str, s);
					g_free(s);
				}
				/* don't add line breaks, they are handled manually below */
				else if (c == '\r' || c == '\n')
				{
					gchar c_next = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
					at_eol = TRUE;
					if (c == '\r' && c_next == '\n')
						dinfo->cur_pos++; /* skip LF part of CR/LF */
				}
				else
				{
					g_string_append_c(str, c); /* finally add the character */

					/* handle UTF-8: since we add char by char (better: byte by byte), we need to
					 * keep UTF-8 characters together(e.g. two bytes for one character)
					 * the input is always UTF-8 and c is signed, so all non-Ascii
					 * characters are less than 0 and consist of all bytes less than 0.
					 * style doesn't change since it is only one character with multiple bytes. */
					while (c < 0)
					{
						c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
						if (c < 0)
						{	/* only add the byte when it is part of the UTF-8 character
							 * otherwise we could add e.g. a '\n' and it won't be visible in the
							 * printed document */
							g_string_append_c(str, c);
							dinfo->cur_pos++;
						}
					}
				}
			}

			if (! at_eol)
			{
				/* set text */
				pango_layout_set_text(dinfo->layout, str->str, -1);
				/* attributes */
				layout_attr = pango_attr_list_new();
				/* foreground colour */
				get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* background colour */
				get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_background_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* bold text */
				if (dinfo->styles[style][BOLD])
				{
					attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
					ADD_ATTR(layout_attr, attr);
				}
				/* italic text */
				if (dinfo->styles[style][ITALIC])
				{
					attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
					ADD_ATTR(layout_attr, attr);
				}
				pango_layout_set_attributes(dinfo->layout, layout_attr);
				pango_layout_context_changed(dinfo->layout);
				pango_attr_list_unref(layout_attr);
			}

			cairo_get_current_point(cr, &x, &y);


			/* normal line break at eol character in document */
			if (at_eol)
			{
				/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
				/*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/
				cairo_move_to(cr, 0, y + dinfo->line_height);

				count++;
				/* we added a new document line so request a new line number */
				add_linenumber = TRUE;
			}
			else
			{
				gint x_offset = 0;
				/* maybe we need to force a line break because of too long line */
				if (x >= (width - dinfo->font_width))
				{
					/* don't start the line at horizontal origin because we need to skip the
					 * line number margin */
					if (printing_prefs.print_line_numbers)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
					}

					/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
					/*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/
					/* this is faster but not exactly the same as above */
					cairo_move_to(cr, x_offset, y + dinfo->line_height);
					cairo_get_current_point(cr, &x, &y);
					count++;
				}
				if (count < dinfo->lines_per_page)
				{
					/* str->len is counted in bytes not characters, so use g_utf8_strlen() */
					x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width);

					if (dinfo->long_line && count == 0)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
						dinfo->long_line = FALSE;
					}

					pango_cairo_show_layout(cr, dinfo->layout);
					cairo_move_to(cr, x + x_offset, y);
				}
				else
				/* we are on a wrapped line but we are out of lines on this page, so continue
				 * the current line on the next page and remember to continue in current line */
					dinfo->long_line = TRUE;
			}
		}
	}

	if (printing_prefs.print_line_numbers)
	{	/* print a thin line between the line number margin and the data */
		gint y_start = 0;

		if (printing_prefs.print_page_header)
			y_start = (dinfo->line_height * 3) - 2;	/* "- 2": to connect the line number line to
													 * the page header frame */

		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start);
		cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1,
			y + dinfo->line_height); /* y is last added line, we reuse it */
		cairo_stroke(cr);
	}

	if (printing_prefs.print_page_numbers)
	{
		gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1);
		pango_layout_set_markup(dinfo->layout, line, -1);
		pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER);
		cairo_move_to(cr, 0, height - dinfo->line_height);
		pango_cairo_show_layout(cr, dinfo->layout);
		g_free(line);

#ifdef GEANY_PRINT_DEBUG
		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height));
		cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height));
		cairo_stroke(cr);
#endif
	}
	g_string_free(str, TRUE);
}
Esempio n. 19
0
static gboolean
span_parse_func     (MarkupData            *md,
		     OpenTag               *tag,
		     const gchar          **names,
		     const gchar          **values,
		     GMarkupParseContext   *context,
		     GError               **error)
{
  int line_number, char_number;
  int i;

  const char *family = NULL;
  const char *size = NULL;
  const char *style = NULL;
  const char *weight = NULL;
  const char *variant = NULL;
  const char *stretch = NULL;
  const char *desc = NULL;
  const char *foreground = NULL;
  const char *background = NULL;
  const char *underline = NULL;
  const char *underline_color = NULL;
  const char *strikethrough = NULL;
  const char *strikethrough_color = NULL;
  const char *rise = NULL;
  const char *letter_spacing = NULL;
  const char *lang = NULL;
  const char *fallback = NULL;
  const char *gravity = NULL;
  const char *gravity_hint = NULL;

  g_markup_parse_context_get_position (context,
				       &line_number, &char_number);

#define CHECK_DUPLICATE(var) G_STMT_START{                              \
	  if ((var) != NULL) {                                          \
	    g_set_error (error, G_MARKUP_ERROR,                         \
			 G_MARKUP_ERROR_INVALID_CONTENT,                \
			 _("Attribute '%s' occurs twice on <span> tag " \
			   "on line %d char %d, may only occur once"),  \
			 names[i], line_number, char_number);           \
	    return FALSE;                                               \
	  }}G_STMT_END
#define CHECK_ATTRIBUTE2(var, name) \
	if (attr_strcmp (names[i], (name)) == 0) { \
	  CHECK_DUPLICATE (var); \
	  (var) = values[i]; \
	  found = TRUE; \
	  break; \
	}
#define CHECK_ATTRIBUTE(var) CHECK_ATTRIBUTE2 (var, G_STRINGIFY (var))

  i = 0;
  while (names[i])
    {
      gboolean found = FALSE;

      switch (names[i][0]) {
      case 'f':
	CHECK_ATTRIBUTE (fallback);
	CHECK_ATTRIBUTE2(desc, "font");
	CHECK_ATTRIBUTE2(desc, "font_desc");
	CHECK_ATTRIBUTE2(family, "face");

	CHECK_ATTRIBUTE2(family, "font_family");
	CHECK_ATTRIBUTE2(size, "font_size");
	CHECK_ATTRIBUTE2(stretch, "font_stretch");
	CHECK_ATTRIBUTE2(style, "font_style");
	CHECK_ATTRIBUTE2(variant, "font_variant");
	CHECK_ATTRIBUTE2(weight, "font_weight");

	CHECK_ATTRIBUTE (foreground);
	CHECK_ATTRIBUTE2 (foreground, "fgcolor");
	break;
      case 's':
	CHECK_ATTRIBUTE (size);
	CHECK_ATTRIBUTE (stretch);
	CHECK_ATTRIBUTE (strikethrough);
	CHECK_ATTRIBUTE (strikethrough_color);
	CHECK_ATTRIBUTE (style);
	break;
      case 'g':
	CHECK_ATTRIBUTE (gravity);
	CHECK_ATTRIBUTE (gravity_hint);
	break;
      case 'l':
	CHECK_ATTRIBUTE (lang);
	CHECK_ATTRIBUTE (letter_spacing);
	break;
      case 'u':
	CHECK_ATTRIBUTE (underline);
	CHECK_ATTRIBUTE (underline_color);
	break;
      default:
	CHECK_ATTRIBUTE (background);
	CHECK_ATTRIBUTE2 (background, "bgcolor");
	CHECK_ATTRIBUTE2(foreground, "color");
	CHECK_ATTRIBUTE (rise);
	CHECK_ATTRIBUTE (variant);
	CHECK_ATTRIBUTE (weight);
	break;
      }

      if (!found)
	{
	  g_set_error (error, G_MARKUP_ERROR,
		       G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
		       _("Attribute '%s' is not allowed on the <span> tag "
			 "on line %d char %d"),
		       names[i], line_number, char_number);
	  return FALSE;
	}

      ++i;
    }

  /* Parse desc first, then modify it with other font-related attributes. */
  if (G_UNLIKELY (desc))
    {
      PangoFontDescription *parsed;

      parsed = pango_font_description_from_string (desc);
      if (parsed)
	{
	  add_attribute (tag, pango_attr_font_desc_new (parsed));
	  if (tag)
	    open_tag_set_absolute_font_size (tag, pango_font_description_get_size (parsed));
	  pango_font_description_free (parsed);
	}
    }

  if (G_UNLIKELY (family))
    {
      add_attribute (tag, pango_attr_family_new (family));
    }

  if (G_UNLIKELY (size))
    {
      if (g_ascii_isdigit (*size))
	{
	  const char *end;
	  gint n;

/* cap size from the top at an arbitrary 2048 */
#define MAX_SIZE (2048 * PANGO_SCALE)

	  if ((end = size, !pango_scan_int (&end, &n)) || *end != '\0' || n < 0 || n > MAX_SIZE)
	    {
	      g_set_error (error,
			   G_MARKUP_ERROR,
			   G_MARKUP_ERROR_INVALID_CONTENT,
			   _("Value of 'size' attribute on <span> tag on line %d "
			     "could not be parsed; should be an integer less than %d, or a "
			     "string such as 'small', not '%s'"),
			   line_number, MAX_SIZE+1, size);
	      goto error;
	    }

	  add_attribute (tag, pango_attr_size_new (n));
	  if (tag)
	    open_tag_set_absolute_font_size (tag, n);
	}
      else if (strcmp (size, "smaller") == 0)
	{
	  if (tag)
	    {
	      tag->scale_level_delta -= 1;
	      tag->scale_level -= 1;
	    }
	}
      else if (strcmp (size, "larger") == 0)
	{
	  if (tag)
	    {
	      tag->scale_level_delta += 1;
	      tag->scale_level += 1;
	    }
	}
      else if (parse_absolute_size (tag, size))
	; /* nothing */
      else
	{
	  g_set_error (error,
		       G_MARKUP_ERROR,
		       G_MARKUP_ERROR_INVALID_CONTENT,
		       _("Value of 'size' attribute on <span> tag on line %d "
			 "could not be parsed; should be an integer, or a "
			 "string such as 'small', not '%s'"),
		       line_number, size);
	  goto error;
	}
    }

  if (G_UNLIKELY (style))
    {
      PangoStyle pango_style;

      if (pango_parse_style (style, &pango_style, FALSE))
	add_attribute (tag, pango_attr_style_new (pango_style));
      else
	{
	  g_set_error (error,
		       G_MARKUP_ERROR,
		       G_MARKUP_ERROR_INVALID_CONTENT,
		       _("'%s' is not a valid value for the 'style' attribute "
			 "on <span> tag, line %d; valid values are "
			 "'normal', 'oblique', 'italic'"),
		       style, line_number);
	  goto error;
	}
    }

  if (G_UNLIKELY (weight))
    {
      PangoWeight pango_weight;

      if (pango_parse_weight (weight, &pango_weight, FALSE))
	add_attribute (tag,
		       pango_attr_weight_new (pango_weight));
      else
	{
	  g_set_error (error,
		       G_MARKUP_ERROR,
		       G_MARKUP_ERROR_INVALID_CONTENT,
		       _("'%s' is not a valid value for the 'weight' "
			 "attribute on <span> tag, line %d; valid "
			 "values are for example 'light', 'ultrabold' or a number"),
		       weight, line_number);
	  goto error;
	}
    }

  if (G_UNLIKELY (variant))
    {
      PangoVariant pango_variant;

      if (pango_parse_variant (variant, &pango_variant, FALSE))
	add_attribute (tag, pango_attr_variant_new (pango_variant));
      else
	{
	  g_set_error (error,
		       G_MARKUP_ERROR,
		       G_MARKUP_ERROR_INVALID_CONTENT,
		       _("'%s' is not a valid value for the 'variant' "
			 "attribute on <span> tag, line %d; valid values are "
			 "'normal', 'smallcaps'"),
		       variant, line_number);
	  goto error;
	}
    }

  if (G_UNLIKELY (stretch))
    {
      PangoStretch pango_stretch;

      if (pango_parse_stretch (stretch, &pango_stretch, FALSE))
	add_attribute (tag, pango_attr_stretch_new (pango_stretch));
      else
	{
	  g_set_error (error,
		       G_MARKUP_ERROR,
		       G_MARKUP_ERROR_INVALID_CONTENT,
		       _("'%s' is not a valid value for the 'stretch' "
			 "attribute on <span> tag, line %d; valid "
			 "values are for example 'condensed', "
			 "'ultraexpanded', 'normal'"),
		       stretch, line_number);
	  goto error;
	}
    }

  if (G_UNLIKELY (foreground))
    {
      PangoColor color;

      if (!span_parse_color ("foreground", foreground, &color, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_foreground_new (color.red, color.green, color.blue));
    }

  if (G_UNLIKELY (background))
    {
      PangoColor color;

      if (!span_parse_color ("background", background, &color, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_background_new (color.red, color.green, color.blue));
    }

  if (G_UNLIKELY (underline))
    {
      PangoUnderline ul = PANGO_UNDERLINE_NONE;

      if (!span_parse_enum ("underline", underline, PANGO_TYPE_UNDERLINE, &ul, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_underline_new (ul));
    }

  if (G_UNLIKELY (underline_color))
    {
      PangoColor color;

      if (!span_parse_color ("underline_color", underline_color, &color, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_underline_color_new (color.red, color.green, color.blue));
    }

  if (G_UNLIKELY (gravity))
    {
      PangoGravity gr = PANGO_GRAVITY_SOUTH;

      if (!span_parse_enum ("gravity", gravity, PANGO_TYPE_GRAVITY, &gr, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_gravity_new (gr));
    }

  if (G_UNLIKELY (gravity_hint))
    {
      PangoGravityHint hint = PANGO_GRAVITY_HINT_NATURAL;

      if (!span_parse_enum ("gravity_hint", gravity_hint, PANGO_TYPE_GRAVITY_HINT, &hint, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_gravity_hint_new (hint));
    }

  if (G_UNLIKELY (strikethrough))
    {
      gboolean b = FALSE;

      if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_strikethrough_new (b));
    }

  if (G_UNLIKELY (strikethrough_color))
    {
      PangoColor color;

      if (!span_parse_color ("strikethrough_color", strikethrough_color, &color, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_strikethrough_color_new (color.red, color.green, color.blue));
    }

  if (G_UNLIKELY (fallback))
    {
      gboolean b = FALSE;

      if (!span_parse_boolean ("fallback", fallback, &b, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_fallback_new (b));
    }

  if (G_UNLIKELY (rise))
    {
      gint n = 0;

      if (!span_parse_int ("rise", rise, &n, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_rise_new (n));
    }

  if (G_UNLIKELY (letter_spacing))
    {
      gint n = 0;

      if (!span_parse_int ("letter_spacing", letter_spacing, &n, line_number, error))
	goto error;

      add_attribute (tag, pango_attr_letter_spacing_new (n));
    }

  if (G_UNLIKELY (lang))
    {
      add_attribute (tag,
		     pango_attr_language_new (pango_language_from_string (lang)));
    }

  return TRUE;

 error:

  return FALSE;
}
Esempio n. 20
0
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);
}
static PangoAttrList*
hildon_font_selection_dialog_create_attrlist    (HildonFontSelectionDialog *fontsel, 
                                                 guint start_index, 
                                                 guint len)
{
    PangoAttrList *list;
    PangoAttribute *attr;
    gint size, position;
    gboolean family_set, size_set, color_set, bold, bold_set,
             italic, italic_set, underline, underline_set,
             strikethrough, strikethrough_set, position_set;
    GdkColor *color = NULL;
    gchar *family = NULL;
    gdouble font_scaling = 1.0;

    list = pango_attr_list_new ();

    g_object_get (G_OBJECT (fontsel),
            "family", &family, "family-set", &family_set,
            "size", &size, "size-set", &size_set,
            "color", &color, "color-set", &color_set,
            "bold", &bold, "bold-set", &bold_set,
            "italic", &italic, "italic-set", &italic_set,
            "underline", &underline, "underline-set", &underline_set,
            "strikethrough", &strikethrough, "strikethrough-set", 
            &strikethrough_set, "position", &position, 
            "position-set", &position_set, 
            "font-scaling", &font_scaling,
            NULL);

    /* family */
    if (family_set)
    {
        attr = pango_attr_family_new (family);
        add_preview_text_attr (list, attr, start_index, len);
    }
    g_free (family);

    /* size */
    if (size_set)
    {
        attr = pango_attr_size_new (size * PANGO_SCALE);
        add_preview_text_attr (list, attr, start_index, len);
    }

    /*color*/
    if (color_set)
    {
        attr = pango_attr_foreground_new (color->red, color->green, color->blue);
        add_preview_text_attr (list, attr, start_index, len);
    }

    if (color != NULL)
        gdk_color_free (color);

    /*weight*/
    if (bold_set)
    {
        if (bold)
            attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
        else
            attr = pango_attr_weight_new (PANGO_WEIGHT_NORMAL);

        add_preview_text_attr(list, attr, start_index, len);
    }

    /* style */
    if (italic_set)
    {
        if (italic)
            attr = pango_attr_style_new (PANGO_STYLE_ITALIC);
        else
            attr = pango_attr_style_new (PANGO_STYLE_NORMAL);

        add_preview_text_attr(list, attr, start_index, len);
    }

    /* underline */
    if (underline_set)
    {
        if (underline)
            attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
        else
            attr = pango_attr_underline_new (PANGO_UNDERLINE_NONE);

        add_preview_text_attr(list, attr, start_index, len);
    }

    /* strikethrough */
    if (strikethrough_set)
    {
        if (strikethrough)
            attr = pango_attr_strikethrough_new (TRUE);
        else
            attr = pango_attr_strikethrough_new (FALSE);

        add_preview_text_attr(list, attr, start_index, len);
    }

    /* position */
    if (position_set)
    {
        switch (position)
        {
            case 1: /*super*/
                attr = pango_attr_rise_new (SUPERSCRIPT_RISE);
                break;
            case -1: /*sub*/
                attr = pango_attr_rise_new (SUBSCRIPT_LOW);
                break;
            default: /*normal*/
                attr = pango_attr_rise_new (0);
                break;
        }

        add_preview_text_attr (list, attr, start_index, len);
    }

    /* font scaling for preview */
    if (font_scaling)
    {
        attr = pango_attr_scale_new(font_scaling);
        add_preview_text_attr(list, attr, 0, len + start_index);
    }

    return list;
}
Esempio n. 22
0
/**
 * 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);
}
Esempio n. 23
0
static void
decorate_text (GimpAboutDialog *dialog,
               gint             anim_type,
               gdouble          time)
{
  GtkStyle       *style = gtk_widget_get_style (dialog->anim_area);
  const gchar    *text;
  const gchar    *ptr;
  gint            letter_count = 0;
  gint            text_length  = 0;
  gint            text_bytelen = 0;
  gint            cluster_start, cluster_end;
  gunichar        unichr;
  PangoAttrList  *attrlist = NULL;
  PangoAttribute *attr;
  PangoRectangle  irect = {0, 0, 0, 0};
  PangoRectangle  lrect = {0, 0, 0, 0};
  GdkColor        mix;

  mix_colors (style->bg + GTK_STATE_NORMAL,
              style->fg + GTK_STATE_NORMAL, &mix, time);

  text = pango_layout_get_text (dialog->layout);
  g_return_if_fail (text != NULL);

  text_length = g_utf8_strlen (text, -1);
  text_bytelen = strlen (text);

  attrlist = pango_attr_list_new ();

  dialog->textrange[0] = 0;
  dialog->textrange[1] = text_bytelen;

  switch (anim_type)
    {
    case 0: /* Fade in */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_insert (attrlist, attr);
      break;

    case 1: /* Fade in, spread */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_change (attrlist, attr);

      ptr = text;

      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          ptr = g_utf8_next_char (ptr);
          cluster_end = (ptr - text);

          if (unichr == 0x200b)
            {
              lrect.width = (1.0 - time) * 15.0 * PANGO_SCALE + 0.5;
              attr = pango_attr_shape_new (&irect, &lrect);
              attr->start_index = cluster_start;
              attr->end_index = cluster_end;
              pango_attr_list_change (attrlist, attr);
            }
          cluster_start = cluster_end;
        }
      break;

    case 2: /* Fade in, sinewave */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_change (attrlist, attr);

      ptr = text;

      cluster_start = 0;

      while ((unichr = g_utf8_get_char (ptr)))
        {
          if (unichr == 0x200b)
            {
              cluster_end = ptr - text;
              attr = pango_attr_rise_new ((1.0 -time) * 18000 *
                                          sin (4.0 * time +
                                               (float) letter_count * 0.7));
              attr->start_index = cluster_start;
              attr->end_index = cluster_end;
              pango_attr_list_change (attrlist, attr);

              letter_count++;
              cluster_start = cluster_end;
            }

          ptr = g_utf8_next_char (ptr);
        }
      break;

    case 3: /* letterwise Fade in */
      ptr = text;

      letter_count  = 0;
      cluster_start = 0;

      while ((unichr = g_utf8_get_char (ptr)))
        {
          gint    border = (text_length + 15) * time - 15;
          gdouble pos;

          if (letter_count < border)
            pos = 0;
          else if (letter_count > border + 15)
            pos = 1;
          else
            pos = ((gdouble) (letter_count - border)) / 15;

          mix_colors (style->fg + GTK_STATE_NORMAL,
                      style->bg + GTK_STATE_NORMAL,
                      &mix, pos);

          ptr = g_utf8_next_char (ptr);

          cluster_end = ptr - text;

          attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
          attr->start_index = cluster_start;
          attr->end_index = cluster_end;
          pango_attr_list_change (attrlist, attr);

          if (pos < 1.0)
            dialog->textrange[1] = cluster_end;

          letter_count++;
          cluster_start = cluster_end;
        }

      break;

    default:
      g_printerr ("Unknown animation type %d\n", anim_type);
    }

  pango_layout_set_attributes (dialog->layout, attrlist);
  pango_attr_list_unref (attrlist);
}
Esempio n. 24
0
/* 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;
}
Esempio n. 25
0
static void
_fcitx_im_context_update_formatted_preedit_cb(FcitxClient* im, GPtrArray* array, int cursor_pos, void* user_data)
{
    FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb");
    FcitxIMContext* context =  FCITX_IM_CONTEXT(user_data);

    gboolean visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            visible = true;
        g_free(context->preedit_string);
        context->preedit_string = NULL;
    }

    if (context->attrlist != NULL) {
        pango_attr_list_unref(context->attrlist);
    }

    context->attrlist = pango_attr_list_new();

    GString* gstr = g_string_new(NULL);

    int i = 0;
    for (i = 0; i < array->len; i++) {
        size_t bytelen = strlen(gstr->str);
        FcitxPreeditItem* preedit = g_ptr_array_index(array, i);
        const gchar* s = preedit->string;
        gint type = preedit->type;

        PangoAttribute *pango_attr = NULL;
        if ((type & MSG_NOUNDERLINE) == 0) {
            pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
        }

        if (type & MSG_HIGHLIGHT) {
            gboolean hasColor;
            GdkColor fg;
            GdkColor bg;

            if (context->client_window) {
                GtkWidget *widget;
                gdk_window_get_user_data (context->client_window,
                                          (gpointer *)&widget);
                if (GTK_IS_WIDGET(widget)) {
                    hasColor = true;
                    GtkStyle* style = gtk_widget_get_style(widget);
                    fg = style->text[GTK_STATE_SELECTED];
                    bg = style->bg[GTK_STATE_SELECTED];
                }
            }

            if (!hasColor) {
                fg.red = 0xffff;
                fg.green = 0xffff;
                fg.blue = 0xffff;
                bg.red = 0x43ff;
                bg.green = 0xacff;
                bg.blue = 0xe8ff;
            }

            pango_attr = pango_attr_foreground_new(fg.red, fg.green, fg.blue);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
            pango_attr = pango_attr_background_new(bg.red, bg.green, bg.blue);
            pango_attr->start_index = bytelen;
            pango_attr->end_index = bytelen + strlen(s);
            pango_attr_list_insert(context->attrlist, pango_attr);
        }
        gstr = g_string_append(gstr, s);
    }

    gchar* str = g_string_free(gstr, FALSE);

    context->preedit_string = g_strdup(str);
    char* tempstr = g_strndup(str, cursor_pos);
    context->cursor_pos =  fcitx_utf8_strlen(tempstr);
    g_free(tempstr);

    gboolean new_visible = false;

    if (context->preedit_string != NULL) {
        if (strlen(context->preedit_string) != 0)
            new_visible = true;
    }
    gboolean flag = new_visible != visible;

    if (new_visible) {
        if (flag) {
            /* invisible => visible */
            g_signal_emit(context, _signal_preedit_start_id, 0);
        }
        g_signal_emit(context, _signal_preedit_changed_id, 0);
    } else {
        if (flag) {
            /* visible => invisible */
            g_signal_emit(context, _signal_preedit_changed_id, 0);
            g_signal_emit(context, _signal_preedit_end_id, 0);
        } else {
            /* still invisible */
            /* do nothing */
        }
    }

    g_signal_emit(context, _signal_preedit_changed_id, 0);
}