/** * go_pango_attr_list_unset: * @list: #PangoAttrList * @start: starting character index * @end: last character index * @type: #PangoAttrType * * See http://bugzilla.gnome.org/show_bug.cgi?id=163679 **/ void go_pango_attr_list_unset (PangoAttrList *list, gint start, gint end, PangoAttrType type) { PangoAttrList *matches; struct cb_unset data; g_return_if_fail (list != NULL); if (start >= end || end < 0) return; /* * Pull out the attribute subset we even care about. Notice that this * is all-or-nothing for a given type so any reordering will not * matter. */ matches = pango_attr_list_filter (list, cb_unset1, &type); if (!matches) return; /* Get rid of whole segments and adjust end_index of rest. */ data.list = list; data.start_index = start; data.end_index = end; (void)pango_attr_list_filter (matches, cb_unset2, &data); pango_attr_list_unref (matches); }
PangoAttrList * ms_container_read_markup (MSContainer const *c, guint8 const *data, size_t txo_len, char const *str) { TXORun txo_run; size_t str_len; XL_CHECK_CONDITION_VAL (txo_len >= 16, pango_attr_list_new ()); /* min two records */ str_len = g_utf8_strlen (str, -1); txo_run.last = G_MAXINT; txo_run.accum = NULL; for (txo_len -= 16 ; (gssize)txo_len >= 0 ; txo_len -= 8) { guint16 o = GSF_LE_GET_GUINT16 (data + txo_len); guint16 idx = GSF_LE_GET_GUINT16 (data + txo_len + 2); XL_CHECK_CONDITION_VAL (o <= str_len, txo_run.accum); txo_run.first = g_utf8_offset_to_pointer (str, o) - str; XL_CHECK_CONDITION_VAL (txo_run.first < txo_run.last, txo_run.accum); if (idx != 0) { if (!txo_run.accum) txo_run.accum = pango_attr_list_new (); pango_attr_list_filter (ms_container_get_markup (c, idx), (PangoAttrFilterFunc) append_txorun, &txo_run); } txo_run.last = txo_run.first; } return txo_run.accum; }
static void cb_entry_insert_text (GtkEditable *editable, gchar const *text, gint len_bytes, gint *pos_in_chars, WBCGtk *wbcg) { char const *str = gtk_entry_get_text (GTK_ENTRY (editable)); int pos_in_bytes = g_utf8_offset_to_pointer (str, *pos_in_chars) - str; if (wbcg->auto_completing && len_bytes != 0 && (!g_unichar_isalpha (g_utf8_get_char (text)) || *pos_in_chars != gtk_entry_get_text_length (GTK_ENTRY (editable)))) { wbcg->auto_completing = FALSE; } if (wbcg->edit_line.full_content) { (void)pango_attr_list_filter (wbcg->edit_line.cur_fmt, cb_set_attr_list_len, GINT_TO_POINTER (len_bytes)); go_pango_attr_list_open_hole (wbcg->edit_line.full_content, pos_in_bytes, len_bytes); pango_attr_list_splice (wbcg->edit_line.full_content, wbcg->edit_line.cur_fmt, pos_in_bytes, 0); go_pango_attr_list_open_hole (wbcg->edit_line.markup, pos_in_bytes, len_bytes); pango_attr_list_splice (wbcg->edit_line.markup, wbcg->edit_line.cur_fmt, pos_in_bytes, 0); } }
/** * go_pango_attr_list_open_hole: * @tape: An attribute list * @pos: a text position in bytes * @len: length of segment in bytes * * This function opens up a blank segment of attributes. This is what to * call after inserting a segment into the text described by the attributes. */ void go_pango_attr_list_open_hole (PangoAttrList *tape, guint pos, guint len) { /* Clean out the tape. */ PangoAttrList *tape2 = pango_attr_list_filter (tape, cb_splice_true, NULL); if (tape2) { struct cb_splice data; data.result = tape; data.pos = pos; data.len = len; (void)pango_attr_list_filter (tape2, cb_splice, &data); pango_attr_list_unref (tape2); } }
gboolean go_pango_attr_list_is_empty (const PangoAttrList *attrs) { gboolean empty = TRUE; if (attrs) (void)pango_attr_list_filter ((PangoAttrList *)attrs, cb_empty, &empty); return empty; }
static void set_or_unset (PangoAttrList *dst, const PangoAttribute *attr, PangoAttrList *ref) { struct cb_set_or_unset data; data.attr = attr; data.set_in_ref = FALSE; (void)pango_attr_list_filter (ref, cb_set_or_unset, &data); if (data.set_in_ref) go_pango_attr_list_unset (dst, attr->start_index, attr->end_index, attr->klass->type); else pango_attr_list_change (dst, pango_attribute_copy (attr)); }
/** * go_pango_attr_list_erase: * @attrs: An attribute list * @pos: a text position in bytes * @len: length of segment in bytes * * This function erases a segment of attributes. This is what to call * after deleting a segment from the text described by the attributes. */ void go_pango_attr_list_erase (PangoAttrList *attrs, guint pos, guint len) { PangoAttrList *gunk; struct cb_erase data; if (attrs == NULL) return; data.start_pos = pos; data.end_pos = pos + len; data.len = len; gunk = pango_attr_list_filter (attrs, (PangoAttrFilterFunc)cb_delete_filter, &data); if (gunk != NULL) pango_attr_list_unref (gunk); }
PangoAttrList * go_pango_translate_attributes (PangoAttrList *attrs) { PangoAttrList *n_attrs, *filtered; if (attrs == NULL) return NULL; n_attrs = pango_attr_list_copy (attrs); filtered = pango_attr_list_filter (n_attrs, filter_func, NULL); if (filtered == NULL) { pango_attr_list_unref (n_attrs); return attrs; } else { PangoAttrIterator *iter, *f_iter; f_iter = pango_attr_list_get_iterator (filtered); do { gint f_range_start, f_range_end; gint range_start, range_end; /* We need to restart everytime since we are changing n_attrs */ iter = pango_attr_list_get_iterator (n_attrs); pango_attr_iterator_range (f_iter, &f_range_start, &f_range_end); pango_attr_iterator_range (iter, &range_start, &range_end); while (range_end <= f_range_start) { if (!pango_attr_iterator_next (iter)) break; pango_attr_iterator_range (iter, &range_start, &range_end); } /* Now range_end > f_range_start >= range_start */ go_pango_translate_here (iter, f_iter, n_attrs); pango_attr_iterator_destroy (iter); } while (pango_attr_iterator_next (f_iter)); pango_attr_iterator_destroy (f_iter); } pango_attr_list_unref (filtered); return n_attrs; }
void go_load_pango_attributes_into_buffer (PangoAttrList *markup, GtkTextBuffer *buffer, gchar const *str) { PangoAttrIterator * iter; PangoAttrList *copied_markup; PangoAttrList *our_markup; if (markup == NULL) return; /* For some styles we create named tags. The names are taken from the Pango enums */ copied_markup = pango_attr_list_copy (markup); our_markup = pango_attr_list_filter (copied_markup, go_load_pango_attributes_into_buffer_named_filter, NULL); pango_attr_list_unref (copied_markup); if (our_markup != NULL) { iter = pango_attr_list_get_iterator (our_markup); do { GSList *attr = pango_attr_iterator_get_attrs (iter); if (attr != NULL) { GSList *ptr; gint start, end; GtkTextIter start_iter, end_iter; char const *name; pango_attr_iterator_range (iter, &start, &end); start = go_load_pango_byte_to_char (str, start); end = go_load_pango_byte_to_char (str, end); gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); for (ptr = attr; ptr != NULL; ptr = ptr->next) { PangoAttribute *attribute = ptr->data; GtkTextTag *tag; int val; switch (attribute->klass->type) { case PANGO_ATTR_STYLE: name = (((PangoAttrInt *)attribute)->value == PANGO_STYLE_NORMAL) ? "PANGO_STYLE_NORMAL" : "PANGO_STYLE_ITALIC"; tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer), name); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); break; case PANGO_ATTR_STRIKETHROUGH: name = (((PangoAttrInt *)attribute)->value) ? "PANGO_STRIKETHROUGH_TRUE" : "PANGO_STRIKETHROUGH_FALSE"; tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer), name); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); break; case PANGO_ATTR_UNDERLINE: val = ((PangoAttrInt *)attribute)->value; if (val == PANGO_UNDERLINE_NONE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_NONE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_SINGLE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_SINGLE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_DOUBLE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_DOUBLE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_LOW) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_LOW", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_ERROR) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_ERROR", &start_iter, &end_iter); break; case PANGO_ATTR_WEIGHT: val = ((PangoAttrInt *)attribute)->value; if (val < (PANGO_WEIGHT_THIN + PANGO_WEIGHT_ULTRALIGHT)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_THIN", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRALIGHT", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_BOOK)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_LIGHT", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_BOOK + PANGO_WEIGHT_NORMAL)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_BOOK", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_MEDIUM)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_NORMAL", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_MEDIUM + PANGO_WEIGHT_SEMIBOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_MEDIUM", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_SEMIBOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_BOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRABOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_HEAVY + PANGO_WEIGHT_ULTRAHEAVY)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_HEAVY", &start_iter, &end_iter); else gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRAHEAVY", &start_iter, &end_iter); break; default: break; } } g_slist_free_full (attr, (GDestroyNotify)pango_attribute_destroy); } } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); pango_attr_list_unref (our_markup); } /* For other styles (that are not at true/false type styles) we use unnamed styles */ copied_markup = pango_attr_list_copy (markup); our_markup = pango_attr_list_filter (copied_markup, go_load_pango_attributes_into_buffer_filter, NULL); pango_attr_list_unref (copied_markup); if (our_markup != NULL) { iter = pango_attr_list_get_iterator (our_markup); do { GSList *attr = pango_attr_iterator_get_attrs (iter); if (attr != NULL) { char *string; GSList *ptr; gint start, end; GtkTextIter start_iter, end_iter; GtkTextTag *tag = gtk_text_buffer_create_tag (buffer, NULL, NULL); for (ptr = attr; ptr != NULL; ptr = ptr->next) { PangoAttribute *attribute = ptr->data; switch (attribute->klass->type) { case PANGO_ATTR_FOREGROUND: string = pango_color_to_string (&((PangoAttrColor *)attribute)->color); g_object_set (G_OBJECT (tag), "foreground", string, "foreground-set", TRUE, NULL); g_free (string); break; case PANGO_ATTR_RISE: g_object_set (G_OBJECT (tag), "rise", ((PangoAttrInt *)attribute)->value, "rise-set", TRUE, NULL); break; default: break; } } pango_attr_iterator_range (iter, &start, &end); start = go_load_pango_byte_to_char (str, start); end = go_load_pango_byte_to_char (str, end); gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); g_slist_free_full (attr, (GDestroyNotify)pango_attribute_destroy); } } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); pango_attr_list_unref (our_markup); } }
void gnm_pango_attr_dump (PangoAttrList *list) { g_print ("PangoAttrList at %p\n", list); pango_attr_list_filter (list, cb_gnm_pango_attr_dump, NULL); }