GtkWidget * gimp_text_style_editor_new (Gimp *gimp, GimpText *text, GimpTextBuffer *buffer, GimpContainer *fonts, gdouble resolution_x, gdouble resolution_y) { g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), NULL); g_return_val_if_fail (resolution_x > 0.0, NULL); g_return_val_if_fail (resolution_y > 0.0, NULL); return g_object_new (GIMP_TYPE_TEXT_STYLE_EDITOR, "gimp", gimp, "text", text, "buffer", buffer, "fonts", fonts, "resolution-x", resolution_x, "resolution-y", resolution_y, NULL); }
gboolean gimp_text_buffer_has_markup (GimpTextBuffer *buffer) { GtkTextIter iter; g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), FALSE); gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter); do { GSList *tags = gtk_text_iter_get_tags (&iter); if (tags) { g_slist_free (tags); return TRUE; } } while (gtk_text_iter_forward_char (&iter)); return FALSE; }
static void gimp_text_style_editor_constructed (GObject *object) { GimpTextStyleEditor *editor = GIMP_TEXT_STYLE_EDITOR (object); if (G_OBJECT_CLASS (parent_class)->constructed) G_OBJECT_CLASS (parent_class)->constructed (object); g_assert (GIMP_IS_GIMP (editor->gimp)); g_assert (GIMP_IS_FONT_LIST (editor->fonts)); g_assert (GIMP_IS_TEXT (editor->text)); g_assert (GIMP_IS_TEXT_BUFFER (editor->buffer)); editor->context = gimp_context_new (editor->gimp, "text style editor", NULL); g_signal_connect (editor->context, "font-changed", G_CALLBACK (gimp_text_style_editor_font_changed), editor); gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (editor->size_entry), 0, editor->resolution_y, TRUE); /* use the global user context so we get the global FG/BG colors */ gimp_color_panel_set_context (GIMP_COLOR_PANEL (editor->color_button), gimp_get_user_context (editor->gimp)); gimp_container_view_set_container (GIMP_CONTAINER_VIEW (editor->font_entry), editor->fonts); gimp_container_view_set_context (GIMP_CONTAINER_VIEW (editor->font_entry), editor->context); gimp_text_style_editor_create_toggle (editor, editor->buffer->bold_tag, GTK_STOCK_BOLD, _("Bold")); gimp_text_style_editor_create_toggle (editor, editor->buffer->italic_tag, GTK_STOCK_ITALIC, _("Italic")); gimp_text_style_editor_create_toggle (editor, editor->buffer->underline_tag, GTK_STOCK_UNDERLINE, _("Underline")); gimp_text_style_editor_create_toggle (editor, editor->buffer->strikethrough_tag, GTK_STOCK_STRIKETHROUGH, _("Strikethrough")); g_signal_connect_swapped (editor->text, "notify::font", G_CALLBACK (gimp_text_style_editor_update), editor); g_signal_connect_swapped (editor->text, "notify::font-size", G_CALLBACK (gimp_text_style_editor_update), editor); g_signal_connect_swapped (editor->text, "notify::font-size-unit", G_CALLBACK (gimp_text_style_editor_update), editor); g_signal_connect_swapped (editor->text, "notify::color", G_CALLBACK (gimp_text_style_editor_update), editor); g_signal_connect_data (editor->buffer, "changed", G_CALLBACK (gimp_text_style_editor_update), editor, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); g_signal_connect_data (editor->buffer, "apply-tag", G_CALLBACK (gimp_text_style_editor_update), editor, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); g_signal_connect_data (editor->buffer, "remove-tag", G_CALLBACK (gimp_text_style_editor_update), editor, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); g_signal_connect_data (editor->buffer, "mark-set", G_CALLBACK (gimp_text_style_editor_update), editor, 0, G_CONNECT_AFTER | G_CONNECT_SWAPPED); }
GtkWidget * gimp_text_editor_new (const gchar *title, GtkWindow *parent, Gimp *gimp, GimpMenuFactory *menu_factory, GimpText *text, GimpTextBuffer *text_buffer, gdouble xres, gdouble yres) { GimpTextEditor *editor; GtkWidget *content_area; GtkWidget *toolbar; GtkWidget *style_editor; GtkWidget *scrolled_window; gboolean use_header_bar; g_return_val_if_fail (title != NULL, NULL); g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL); g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (text_buffer), NULL); g_object_get (gtk_settings_get_default (), "gtk-dialogs-use-header", &use_header_bar, NULL); editor = g_object_new (GIMP_TYPE_TEXT_EDITOR, "title", title, "role", "gimp-text-editor", "transient-for", parent, "help-func", gimp_standard_help_func, "help-id", GIMP_HELP_TEXT_EDITOR_DIALOG, "use-header-bar", use_header_bar, NULL); gtk_dialog_add_button (GTK_DIALOG (editor), _("_Close"), GTK_RESPONSE_CLOSE); g_signal_connect (editor, "response", G_CALLBACK (gtk_widget_destroy), NULL); g_signal_connect_object (text_buffer, "changed", G_CALLBACK (gimp_text_editor_text_changed), editor, 0); editor->ui_manager = gimp_menu_factory_manager_new (menu_factory, "<TextEditor>", editor); content_area = gtk_dialog_get_content_area (GTK_DIALOG (editor)); toolbar = gtk_ui_manager_get_widget (GTK_UI_MANAGER (editor->ui_manager), "/text-editor-toolbar"); if (toolbar) { gtk_box_pack_start (GTK_BOX (content_area), toolbar, FALSE, FALSE, 0); gtk_widget_show (toolbar); } style_editor = gimp_text_style_editor_new (gimp, text, text_buffer, gimp_data_factory_get_container (gimp->font_factory), xres, yres); gtk_box_pack_start (GTK_BOX (content_area), style_editor, FALSE, FALSE, 0); gtk_widget_show (style_editor); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2); gtk_box_pack_start (GTK_BOX (content_area), scrolled_window, TRUE, TRUE, 0); gtk_widget_show (scrolled_window); editor->view = gtk_text_view_new_with_buffer (GTK_TEXT_BUFFER (text_buffer)); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (editor->view), GTK_WRAP_WORD_CHAR); gtk_container_add (GTK_CONTAINER (scrolled_window), editor->view); gtk_widget_show (editor->view); switch (editor->base_dir) { case GIMP_TEXT_DIRECTION_LTR: case GIMP_TEXT_DIRECTION_TTB_RTL: case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT: case GIMP_TEXT_DIRECTION_TTB_LTR: case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT: gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_LTR); break; case GIMP_TEXT_DIRECTION_RTL: gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_RTL); break; } gtk_widget_set_size_request (editor->view, 200, 64); editor->font_toggle = gtk_check_button_new_with_mnemonic (_("_Use selected font")); gtk_box_pack_start (GTK_BOX (content_area), editor->font_toggle, FALSE, FALSE, 0); gtk_widget_show (editor->font_toggle); g_signal_connect (editor->font_toggle, "toggled", G_CALLBACK (gimp_text_editor_font_toggled), editor); gtk_widget_grab_focus (editor->view); gimp_ui_manager_update (editor->ui_manager, editor); return GTK_WIDGET (editor); }
void gimp_text_buffer_change_kerning (GimpTextBuffer *buffer, const GtkTextIter *start, const GtkTextIter *end, gint count) { GtkTextIter iter; GtkTextIter span_start; GtkTextIter span_end; GtkTextTag *span_tag; gint span_kerning; g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer)); g_return_if_fail (start != NULL); g_return_if_fail (end != NULL); if (gtk_text_iter_equal (start, end)) return; iter = *start; span_start = *start; span_tag = gimp_text_buffer_get_iter_kerning (buffer, &iter, &span_kerning); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); do { GtkTextTag *iter_tag; gint iter_kerning; gtk_text_iter_forward_char (&iter); iter_tag = gimp_text_buffer_get_iter_kerning (buffer, &iter, &iter_kerning); span_end = iter; if (iter_kerning != span_kerning || gtk_text_iter_compare (&iter, end) >= 0) { if (span_kerning != 0) { gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), span_tag, &span_start, &span_end); } if (span_kerning + count != 0) { span_tag = gimp_text_buffer_get_kerning_tag (buffer, span_kerning + count); gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), span_tag, &span_start, &span_end); } span_start = iter; span_kerning = iter_kerning; span_tag = iter_tag; } /* We might have moved too far */ if (gtk_text_iter_compare (&iter, end) > 0) iter = *end; } while (! gtk_text_iter_equal (&iter, end)); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); }
gboolean gimp_text_buffer_save (GimpTextBuffer *buffer, GFile *file, gboolean selection_only, GError **error) { GOutputStream *output; GtkTextIter start_iter; GtkTextIter end_iter; gchar *text_contents; GError *my_error = NULL; g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), FALSE); g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &my_error)); if (! output) { g_set_error (error, my_error->domain, my_error->code, _("Could not open '%s' for writing: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); return FALSE; } if (selection_only) gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer), &start_iter, &end_iter); else gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start_iter, &end_iter); text_contents = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer), &start_iter, &end_iter, TRUE); if (text_contents) { gint text_length = strlen (text_contents); if (! g_output_stream_write_all (output, text_contents, text_length, NULL, NULL, &my_error)) { g_set_error (error, my_error->domain, my_error->code, _("Writing palette file '%s' failed: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); g_free (text_contents); g_object_unref (output); return FALSE; } g_free (text_contents); } g_object_unref (output); return TRUE; }
gboolean gimp_text_buffer_load (GimpTextBuffer *buffer, GFile *file, GError **error) { GInputStream *input; gchar buf[2048]; gint to_read; gsize bytes_read; gsize total_read = 0; gint remaining = 0; GtkTextIter iter; GError *my_error = NULL; g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), FALSE); g_return_val_if_fail (G_IS_FILE (file), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); if (! input) { g_set_error (error, my_error->domain, my_error->code, _("Could not open '%s' for reading: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); return FALSE; } gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); gimp_text_buffer_set_text (buffer, NULL); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &iter); do { gboolean success; const char *leftover; to_read = sizeof (buf) - remaining - 1; success = g_input_stream_read_all (input, buf + remaining, to_read, &bytes_read, NULL, &my_error); total_read += bytes_read; buf[bytes_read + remaining] = '\0'; g_utf8_validate (buf, bytes_read + remaining, &leftover); gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, buf, leftover - buf); gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &iter); remaining = (buf + remaining + bytes_read) - leftover; memmove (buf, leftover, remaining); if (! success) { if (total_read > 0) { g_message (_("Input file '%s' appears truncated: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); break; } gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); g_object_unref (input); g_propagate_error (error, my_error); return FALSE; } } while (remaining <= 6 && bytes_read == to_read); if (remaining) g_message (_("Invalid UTF-8 data in file '%s'."), gimp_file_get_utf8_name (file)); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); g_object_unref (input); return TRUE; }
void gimp_text_buffer_get_iter_at_index (GimpTextBuffer *buffer, GtkTextIter *iter, gint index, gboolean layout_index) { GtkTextIter start; GtkTextIter end; gchar *string; g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer)); gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end); string = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer), &start, &end, TRUE); if (layout_index) { gchar *my_string = string; gint my_index = 0; gchar *tmp; do { GSList *tags = gtk_text_iter_get_tags (&start); GSList *list; tmp = g_utf8_next_char (my_string); my_index += (tmp - my_string); my_string = tmp; for (list = tags; list; list = g_slist_next (list)) { GtkTextTag *tag = list->data; if (g_list_find (buffer->kerning_tags, tag)) { index = MAX (0, index - WORD_JOINER_LENGTH); break; } } g_slist_free (tags); gtk_text_iter_forward_char (&start); /* We might have moved too far */ if (gtk_text_iter_compare (&start, &end) > 0) start = end; } while (my_index < index && ! gtk_text_iter_equal (&start, &end)); } string[index] = '\0'; gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), iter, g_utf8_strlen (string, -1)); g_free (string); }
void gimp_text_buffer_insert (GimpTextBuffer *buffer, const gchar *text) { GtkTextIter iter, start; gint start_offset; gboolean insert_tags_set; GList *insert_tags; GList *remove_tags; GSList *tags_off = NULL; g_return_if_fail (GIMP_IS_TEXT_BUFFER (buffer)); gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (buffer))); start_offset = gtk_text_iter_get_offset (&iter); insert_tags_set = buffer->insert_tags_set; insert_tags = buffer->insert_tags; remove_tags = buffer->remove_tags; buffer->insert_tags_set = FALSE; buffer->insert_tags = NULL; buffer->remove_tags = NULL; tags_off = gtk_text_iter_get_toggled_tags (&iter, FALSE); gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer)); gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, text, -1); gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, start_offset); if (insert_tags_set) { GList *list; for (list = remove_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } for (list = insert_tags; list; list = g_list_next (list)) { GtkTextTag *tag = list->data; gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } } if (tags_off) { GSList *slist; for (slist = tags_off; slist; slist = g_slist_next (slist)) { GtkTextTag *tag = slist->data; if (! g_list_find (remove_tags, tag) && ! g_list_find (buffer->kerning_tags, tag)) { gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (buffer), tag, &start, &iter); } } g_slist_free (tags_off); } g_list_free (remove_tags); g_list_free (insert_tags); gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer)); }
const gchar * gimp_text_buffer_tag_to_name (GimpTextBuffer *buffer, GtkTextTag *tag, const gchar **attribute, gchar **value) { g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (buffer), NULL); g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), NULL); if (attribute) *attribute = NULL; if (value) *value = NULL; if (tag == buffer->bold_tag) { return "b"; } else if (tag == buffer->italic_tag) { return "i"; } else if (tag == buffer->underline_tag) { return "u"; } else if (tag == buffer->strikethrough_tag) { return "s"; } else if (g_list_find (buffer->size_tags, tag)) { if (attribute) *attribute = GIMP_TEXT_ATTR_NAME_SIZE; if (value) *value = g_strdup_printf ("%d", gimp_text_tag_get_size (tag)); return "span"; } else if (g_list_find (buffer->baseline_tags, tag)) { if (attribute) *attribute = GIMP_TEXT_ATTR_NAME_BASELINE; if (value) *value = g_strdup_printf ("%d", gimp_text_tag_get_baseline (tag)); return "span"; } else if (g_list_find (buffer->kerning_tags, tag)) { if (attribute) *attribute = GIMP_TEXT_ATTR_NAME_KERNING; if (value) *value = g_strdup_printf ("%d", gimp_text_tag_get_kerning (tag)); return "span"; } else if (g_list_find (buffer->font_tags, tag)) { if (attribute) *attribute = GIMP_TEXT_ATTR_NAME_FONT; if (value) *value = gimp_text_tag_get_font (tag); return "span"; } else if (g_list_find (buffer->color_tags, tag)) { if (attribute) *attribute = GIMP_TEXT_ATTR_NAME_COLOR; if (value) { GimpRGB color; guchar r, g, b; gimp_text_tag_get_color (tag, &color); gimp_rgb_get_uchar (&color, &r, &g, &b); *value = g_strdup_printf ("#%02x%02x%02x", r, g, b); } return "span"; } return NULL; }