talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 1f06c36ebba9256d9db823072939af0e2385aaf0
parent 35bc7bd9f2ec7124ed3678b520ba51e81da5750a
Author: Colin Leroy <colin@colino.net>
Date:   Wed, 11 Feb 2009 20:05:41 +0000

2009-02-11 [colin]	3.7.0cvs59

	* src/gtk/spell_entry.c
	* src/gtk/spell_entry.h
		Forgot to add files

Diffstat:
MChangeLog | 6++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Asrc/gtk/spell_entry.c | 666+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/gtk/spell_entry.h | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 763 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,9 @@ +2009-02-11 [colin] 3.7.0cvs59 + + * src/gtk/spell_entry.c + * src/gtk/spell_entry.h + Forgot to add files + 2009-02-11 [colin] 3.7.0cvs58 * src/compose.c diff --git a/PATCHSETS b/PATCHSETS @@ -3720,3 +3720,4 @@ ( cvs diff -u -r 1.39.2.16 -r 1.39.2.17 src/matcher.h; ) > 3.7.0cvs56.patchset ( cvs diff -u -r 1.1.2.20 -r 1.1.2.21 src/printing.c; cvs diff -u -r 1.9.2.48 -r 1.9.2.49 src/common/defs.h; ) > 3.7.0cvs57.patchset ( cvs diff -u -r 1.382.2.498 -r 1.382.2.499 src/compose.c; cvs diff -u -r 1.20.2.21 -r 1.20.2.22 src/gtk/Makefile.am; cvs diff -u -r 1.9.2.64 -r 1.9.2.65 src/gtk/gtkaspell.c; cvs diff -u -r 1.5.2.16 -r 1.5.2.17 src/gtk/gtkaspell.h; ) > 3.7.0cvs58.patchset +( diff -u /dev/null src/gtk/spell_entry.c; diff -u /dev/null src/gtk/spell_entry.h; ) > 3.7.0cvs59.patchset diff --git a/configure.ac b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=7 MICRO_VERSION=0 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=58 +EXTRA_VERSION=59 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/gtk/spell_entry.c b/src/gtk/spell_entry.c @@ -0,0 +1,666 @@ +/* + * @file libsexy/sexy-icon-entry.c Entry widget + * + * @Copyright (C) 2004-2006 Christian Hammond. + * Some of this code is from gtkspell, Copyright (C) 2002 Evan Martin. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + Adapted for Claws Mail (c) 2009 Pawel Pekala + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef USE_ENCHANT + +#include <glib.h> +#include <glib/gi18n.h> + +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> + +#include <string.h> +#include <glib.h> +#include <gtk/gtkwidget.h> +#include <gtk/gtkentry.h> +#include <gtk/gtkseparator.h> +#include <gtk/gtkmenuitem.h> + +#include "spell_entry.h" +#include "prefs_common.h" +#include "codeconv.h" +#include "defs.h" + +static void claws_spell_entry_init (ClawsSpellEntry *entry); +static void claws_spell_entry_editable_init (GtkEditableClass *iface); +static void claws_spell_entry_finalize (GObject *object); +static void claws_spell_entry_destroy (GtkObject *object); +static gint claws_spell_entry_expose (GtkWidget *widget, + GdkEventExpose *event); +static gint claws_spell_entry_button_press (GtkWidget *widget, + GdkEventButton *event); +static gboolean claws_spell_entry_popup_menu (GtkWidget *widget, + ClawsSpellEntry *entry); +static void claws_spell_entry_populate_popup (ClawsSpellEntry *entry, + GtkMenu *menu, + gpointer data); +static void claws_spell_entry_changed (GtkEditable *editable, + gpointer data); + +struct _ClawsSpellEntryPriv +{ + PangoAttrList *attr_list; + gint mark_character; + gchar **words; + gint *word_starts; + gint *word_ends; +}; + +static GtkEntryClass *parent_class = NULL; + + +G_DEFINE_TYPE_EXTENDED(ClawsSpellEntry, claws_spell_entry, GTK_TYPE_ENTRY, 0, G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE, claws_spell_entry_editable_init)); + + +static void claws_spell_entry_class_init(ClawsSpellEntryClass *klass) +{ + GObjectClass *g_object_class; + GtkObjectClass *gtk_object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent(klass); + + g_object_class = G_OBJECT_CLASS(klass); + g_object_class->finalize = claws_spell_entry_finalize; + + gtk_object_class = GTK_OBJECT_CLASS(klass); + gtk_object_class->destroy = claws_spell_entry_destroy; + + widget_class = GTK_WIDGET_CLASS(klass); + widget_class->expose_event = claws_spell_entry_expose; + widget_class->button_press_event = claws_spell_entry_button_press; + + g_type_class_add_private(g_object_class, + sizeof(struct _ClawsSpellEntryPriv)); +} + +static void claws_spell_entry_init(ClawsSpellEntry *entry) +{ + entry->gtkaspell = NULL; + + entry->priv = g_new0(ClawsSpellEntryPriv, 1); + entry->priv->attr_list = pango_attr_list_new(); + + g_signal_connect(G_OBJECT(entry), "popup-menu", + G_CALLBACK(claws_spell_entry_popup_menu), entry); + g_signal_connect(G_OBJECT(entry), "populate-popup", + G_CALLBACK(claws_spell_entry_populate_popup), NULL); + g_signal_connect(G_OBJECT(entry), "changed", + G_CALLBACK(claws_spell_entry_changed), NULL); +} + +static void claws_spell_entry_editable_init (GtkEditableClass *iface) {} + +static void claws_spell_entry_finalize(GObject *object) +{ + ClawsSpellEntry *entry = CLAWS_SPELL_ENTRY(object); + + if (entry->priv->attr_list) + pango_attr_list_unref(entry->priv->attr_list); + if (entry->priv->words) + g_strfreev(entry->priv->words); + + g_free(entry->priv->word_starts); + g_free(entry->priv->word_ends); + g_free(entry->priv); + entry->priv = NULL; + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +static void claws_spell_entry_destroy(GtkObject *object) +{ + GTK_OBJECT_CLASS(parent_class)->destroy(object); +} + +GtkWidget *claws_spell_entry_new(void) +{ + return GTK_WIDGET( g_object_new(CLAWS_TYPE_SPELL_ENTRY, NULL) ); +} + +void claws_spell_entry_set_gtkaspell(ClawsSpellEntry *entry, GtkAspell *gtkaspell) +{ + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(gtkaspell != NULL); + + entry->gtkaspell = gtkaspell; +} + +static gint gtk_entry_find_position (GtkEntry *entry, gint x) +{ + PangoLayout *layout; + PangoLayoutLine *line; + const gchar *text; + gint cursor_index; + gint index; + gint pos; + gboolean trailing; + + x = x + entry->scroll_offset; + + layout = gtk_entry_get_layout(entry); + text = pango_layout_get_text(layout); + cursor_index = g_utf8_offset_to_pointer(text, entry->current_pos) - text; + + line = pango_layout_get_lines(layout)->data; + pango_layout_line_x_to_index(line, x * PANGO_SCALE, &index, &trailing); + + if (index >= cursor_index && entry->preedit_length) { + if (index >= cursor_index + entry->preedit_length) { + index -= entry->preedit_length; + } else { + index = cursor_index; + trailing = FALSE; + } + } + + pos = g_utf8_pointer_to_offset (text, text + index); + pos += trailing; + + return pos; +} + +static void get_word_extents_from_position(ClawsSpellEntry *entry, gint *start, + gint *end, guint position) +{ + const gchar *text; + gint i, bytes_pos; + + *start = -1; + *end = -1; + + if (entry->priv->words == NULL) + return; + + text = gtk_entry_get_text(GTK_ENTRY(entry)); + bytes_pos = (gint) (g_utf8_offset_to_pointer(text, position) - text); + + for (i = 0; entry->priv->words[i]; i++) { + if (bytes_pos >= entry->priv->word_starts[i] && + bytes_pos <= entry->priv->word_ends[i]) { + *start = entry->priv->word_starts[i]; + *end = entry->priv->word_ends[i]; + return; + } + } +} + +static gchar *get_word(ClawsSpellEntry *entry, const int start, const int end) +{ + const gchar *text; + gchar *word; + + if (start >= end) + return NULL; + + text = gtk_entry_get_text(GTK_ENTRY(entry)); + word = g_new0(gchar, end - start + 2); + g_strlcpy(word, text + start, end - start + 1); + + return word; +} + +static void replace_word(ClawsSpellEntry *entry, const gchar *newword) +{ + gint cursor, start_pos, end_pos; + const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry)); + + start_pos = entry->gtkaspell->start_pos; + end_pos = entry->gtkaspell->end_pos; + + cursor = gtk_editable_get_position(GTK_EDITABLE(entry)); + /* is the cursor at the end? If so, restore it there */ + if (g_utf8_strlen(text, -1) == cursor) + cursor = -1; + else if(cursor < entry->priv->mark_character || + cursor > entry->priv->mark_character) + cursor = entry->priv->mark_character; + + gtk_editable_delete_text(GTK_EDITABLE(entry), start_pos, end_pos); + gtk_editable_insert_text(GTK_EDITABLE(entry), newword, strlen(newword), + &start_pos); + gtk_editable_set_position(GTK_EDITABLE(entry), cursor); +} + + +static gboolean word_misspelled(ClawsSpellEntry *entry, int start, int end) +{ + gchar *word; + gboolean ret; + + word = get_word(entry, start, end); + if (word == NULL) + return FALSE; + + ret = gtkaspell_misspelled_test(entry->gtkaspell, word); + + g_free(word); + return ret; +} + +static void entry_strsplit_utf8(GtkEntry *entry, gchar ***set, gint **starts, gint **ends) +{ + PangoLayout *layout; + PangoLogAttr *log_attrs; + const gchar *text; + gint n_attrs, n_strings, i, j; + + layout = gtk_entry_get_layout(GTK_ENTRY(entry)); + text = gtk_entry_get_text(GTK_ENTRY(entry)); + pango_layout_get_log_attrs(layout, &log_attrs, &n_attrs); + + /* Find how many words we have */ + n_strings = 0; + for (i = 0; i < n_attrs; i++) + if (log_attrs[i].is_word_start) + n_strings++; + + *set = g_new0(gchar *, n_strings + 1); + *starts = g_new0(gint, n_strings); + *ends = g_new0(gint, n_strings); + + /* Copy out strings */ + for (i = 0, j = 0; i < n_attrs; i++) { + if (log_attrs[i].is_word_start) { + gint cend, bytes; + gchar *start; + + /* Find the end of this string */ + cend = i; + while (!(log_attrs[cend].is_word_end)) + cend++; + + /* Copy sub-string */ + start = g_utf8_offset_to_pointer(text, i); + bytes = (gint) (g_utf8_offset_to_pointer(text, cend) - start); + (*set)[j] = g_new0(gchar, bytes + 1); + (*starts)[j] = (gint) (start - text); + (*ends)[j] = (gint) (start - text + bytes); + g_utf8_strncpy((*set)[j], start, cend - i); + + /* Move on to the next word */ + j++; + } + } + + g_free (log_attrs); +} + +static void insert_misspelled_marker(ClawsSpellEntry *entry, guint start, guint end) +{ + guint16 red = (guint16) (((gdouble)((prefs_common.misspelled_col & + 0xff0000) >> 16) / 255.0) * 65535.0); + guint16 green = (guint16) (((gdouble)((prefs_common.misspelled_col & + 0x00ff00) >> 8) / 255.0) * 65535.0); + guint16 blue = (guint16) (((gdouble) (prefs_common.misspelled_col & + 0x0000ff) / 255.0) * 65535.0); + PangoAttribute *fcolor, *ucolor, *unline; + + if(prefs_common.misspelled_col != 0) { + fcolor = pango_attr_foreground_new(red, green, blue); + fcolor->start_index = start; + fcolor->end_index = end; + + pango_attr_list_insert(entry->priv->attr_list, fcolor); + } else { + ucolor = pango_attr_underline_color_new (65535, 0, 0); + unline = pango_attr_underline_new (PANGO_UNDERLINE_ERROR); + + ucolor->start_index = start; + unline->start_index = start; + + ucolor->end_index = end; + unline->end_index = end; + + pango_attr_list_insert (entry->priv->attr_list, ucolor); + pango_attr_list_insert (entry->priv->attr_list, unline); + } +} + +static gboolean check_word(ClawsSpellEntry *entry, int start, int end) +{ + GtkAspell *gtkaspell = entry->gtkaspell; + PangoAttrIterator *it; + gint s, e; + gboolean misspelled; + gchar *text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + gchar *word = NULL; + + /* Check to see if we've got any attributes at this position. + * If so, free them, since we'll readd it if the word is misspelled */ + it = pango_attr_list_get_iterator(entry->priv->attr_list); + if (it == NULL) + return FALSE; + do { + pango_attr_iterator_range(it, &s, &e); + if (s == start) { + GSList *attrs = pango_attr_iterator_get_attrs(it); + g_slist_foreach(attrs, (GFunc) pango_attribute_destroy, NULL); + g_slist_free(attrs); + } + } while (pango_attr_iterator_next(it)); + pango_attr_iterator_destroy(it); + + if ((misspelled = word_misspelled(entry, start, end))) { + insert_misspelled_marker(entry, start, end); + + word = get_word(entry, start, end); + strncpy(gtkaspell->theword, (gchar *)word, GTKASPELLWORDSIZE - 1); + gtkaspell->theword[GTKASPELLWORDSIZE - 1] = 0; + gtkaspell->start_pos = g_utf8_pointer_to_offset(text, (text+start)); + gtkaspell->end_pos = g_utf8_pointer_to_offset(text, (text+end)); + gtkaspell_free_suggestions_list(gtkaspell); + g_free(word); + } + + g_free(text); + + return misspelled; +} + +void claws_spell_entry_recheck_all(ClawsSpellEntry *entry) +{ + GdkRectangle rect; + PangoLayout *layout; + int length, i; + + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(entry->gtkaspell != NULL); + + if (entry->priv->words == NULL) + return; + + /* Remove all existing pango attributes. These will get readded as we check */ + pango_attr_list_unref(entry->priv->attr_list); + entry->priv->attr_list = pango_attr_list_new(); + + /* Loop through words */ + for (i = 0; entry->priv->words[i]; i++) { + length = strlen(entry->priv->words[i]); + if (length == 0) + continue; + check_word(entry, entry->priv->word_starts[i], entry->priv->word_ends[i]); + } + + layout = gtk_entry_get_layout(GTK_ENTRY(entry)); + pango_layout_set_attributes(layout, entry->priv->attr_list); + + if (GTK_WIDGET_REALIZED(GTK_WIDGET(entry))) { + rect.x = 0; rect.y = 0; + rect.width = GTK_WIDGET(entry)->allocation.width; + rect.height = GTK_WIDGET(entry)->allocation.height; + gdk_window_invalidate_rect(GTK_WIDGET(entry)->window, &rect, TRUE); + } +} + +static gint claws_spell_entry_expose(GtkWidget *widget, GdkEventExpose *event) +{ + ClawsSpellEntry *entry = CLAWS_SPELL_ENTRY(widget); + GtkEntry *gtk_entry = GTK_ENTRY(widget); + PangoLayout *layout; + + if (entry->gtkaspell != NULL) { + layout = gtk_entry_get_layout(gtk_entry); + pango_layout_set_attributes(layout, entry->priv->attr_list); + } + + return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event); +} + +static gint claws_spell_entry_button_press(GtkWidget *widget, GdkEventButton *event) +{ + ClawsSpellEntry *entry = CLAWS_SPELL_ENTRY(widget); + GtkEntry *gtk_entry = GTK_ENTRY(widget); + gint pos; + + pos = gtk_entry_find_position(gtk_entry, event->x); + entry->priv->mark_character = pos; + + return GTK_WIDGET_CLASS(parent_class)->button_press_event (widget, event); +} + +static gboolean claws_spell_entry_popup_menu(GtkWidget *widget, ClawsSpellEntry *entry) +{ + entry->priv->mark_character = gtk_editable_get_position (GTK_EDITABLE (entry)); + return FALSE; +} + +static void set_position(gpointer data, gint pos) +{ + gtk_editable_set_position(GTK_EDITABLE(data), pos); +} + +static gboolean find_misspelled_cb(gpointer data, gboolean forward) +{ + ClawsSpellEntry *entry = (ClawsSpellEntry *)data; + GtkAspell *gtkaspell = entry->gtkaspell; + gboolean misspelled = FALSE; + gint cursor, minpos, maxpos, i, words_len = 0; + gint start, end; + gchar *text; + + if (entry->priv->words == NULL) + return FALSE; + + gtkaspell->orig_pos = gtk_editable_get_position(GTK_EDITABLE(entry)); + text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + cursor = g_utf8_offset_to_pointer(text, gtkaspell->orig_pos) - text; + + if (gtk_editable_get_selection_bounds(GTK_EDITABLE(entry), &start, &end)) { + minpos = g_utf8_offset_to_pointer(text, start) - text; + maxpos = g_utf8_offset_to_pointer(text, end) - text; + } else { + minpos = forward ? cursor : 0; + maxpos = forward ? strlen(text)-1 : cursor; + } + g_free(text); + + while(entry->priv->words[words_len]) + words_len++; + + if (forward) { + for(i=0; i < words_len; i++) + if (entry->priv->word_ends[i] > minpos && + (misspelled = check_word(entry, + entry->priv->word_starts[i], + entry->priv->word_ends[i]))) + break; + } else { + for(i=words_len-1; i >= 0; i--) + if (entry->priv->word_starts[i] < maxpos && + (misspelled = check_word(entry, + entry->priv->word_starts[i], + entry->priv->word_ends[i]))) + break; + } + + return misspelled; +} + +static gboolean check_word_cb(gpointer data) +{ + ClawsSpellEntry *entry = (ClawsSpellEntry *)data; + gint start, end; + + get_word_extents_from_position(entry, &start, &end, entry->priv->mark_character); + return check_word(entry, start, end); +} + +static void replace_word_cb(gpointer data, const gchar *newword) +{ + replace_word((ClawsSpellEntry *) data, newword); +} + +static void set_menu_pos(GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, gpointer data) +{ + ClawsSpellEntry *entry = (ClawsSpellEntry *) data; + GtkAspell *gtkaspell = entry->gtkaspell; + gint pango_offset, win_x, win_y, scr_x, scr_y, text_index, entry_x; + gchar *text; + GtkRequisition subject_rq; + PangoLayout *layout = gtk_entry_get_layout(GTK_ENTRY(entry)); + PangoLayoutLine *line = pango_layout_get_lines(layout)->data; + + gtk_widget_get_child_requisition(GTK_WIDGET(entry), &subject_rq); + + /* screen -> compose window coords */ + gdk_window_get_origin(GTK_WIDGET(gtkaspell->parent_window)->window, + &scr_x, &scr_y); + + /* compose window -> subject entry coords */ + gtk_widget_translate_coordinates(GTK_WIDGET(entry), + gtkaspell->parent_window, 0, 0, &win_x, &win_y); + + text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + text_index = g_utf8_offset_to_pointer(text, gtkaspell->end_pos) - text; + g_free(text); + + pango_offset = gtk_entry_text_index_to_layout_index(GTK_ENTRY(entry), + text_index); + pango_layout_line_index_to_x(line, pango_offset, TRUE, &entry_x); + + *x = scr_x + win_x + PANGO_PIXELS(entry_x) + 8; + *y = scr_y + win_y + subject_rq.height; +} + +void claws_spell_entry_context_set(ClawsSpellEntry *entry) +{ + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(entry->gtkaspell != NULL); + + entry->gtkaspell->ctx.set_position = set_position; + entry->gtkaspell->ctx.set_menu_pos = set_menu_pos; + entry->gtkaspell->ctx.find_misspelled = find_misspelled_cb; + entry->gtkaspell->ctx.check_word = check_word_cb; + entry->gtkaspell->ctx.replace_word = replace_word_cb; + entry->gtkaspell->ctx.data = (gpointer) entry; +} + +static void claws_spell_entry_populate_popup(ClawsSpellEntry *entry, GtkMenu *menu, + gpointer data) +{ + GtkAspell *gtkaspell = entry->gtkaspell; + gint start, end; + gchar *word; + + if (gtkaspell == NULL) + return; + + get_word_extents_from_position(entry, &start, &end, entry->priv->mark_character); + + if ((word = get_word(entry, start, end)) != NULL) { + strncpy(gtkaspell->theword, word, GTKASPELLWORDSIZE - 1); + g_free(word); + } + + gtkaspell->misspelled = word_misspelled(entry, start, end); + + claws_spell_entry_context_set(entry); + gtkaspell_make_context_menu(menu, gtkaspell); +} + +static void claws_spell_entry_changed(GtkEditable *editable, gpointer data) +{ + ClawsSpellEntry *entry = CLAWS_SPELL_ENTRY(editable); + + if (entry->gtkaspell == NULL) + return; + + if (entry->priv->words) { + g_strfreev(entry->priv->words); + g_free(entry->priv->word_starts); + g_free(entry->priv->word_ends); + } + entry_strsplit_utf8(GTK_ENTRY(entry), &entry->priv->words, + &entry->priv->word_starts, &entry->priv->word_ends); + if(entry->gtkaspell->check_while_typing == TRUE) + claws_spell_entry_recheck_all(entry); +} + +static void continue_check(gpointer *data) +{ + ClawsSpellEntry *entry = (ClawsSpellEntry *)data; + GtkAspell *gtkaspell = entry->gtkaspell; + gint pos = gtk_editable_get_position(GTK_EDITABLE(entry)); + + if (gtkaspell->misspelled && pos < gtkaspell->end_check_pos) + gtkaspell->misspelled = gtkaspell_check_next_prev(gtkaspell, TRUE); + else + gtkaspell->continue_check = NULL; +} + +void claws_spell_entry_check_all(ClawsSpellEntry *entry) +{ + gint start, end; + gchar *text; + + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(entry->gtkaspell != NULL); + + if (!gtk_editable_get_selection_bounds(GTK_EDITABLE(entry), &start, &end)) { + text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + + start = 0; + end = g_utf8_strlen(text, -1) - 1; + + g_free(text); + } + + gtk_editable_set_position(GTK_EDITABLE(entry), start); + entry->gtkaspell->continue_check = continue_check; + entry->gtkaspell->end_check_pos = end; + + claws_spell_entry_context_set(entry); + entry->gtkaspell->misspelled = + gtkaspell_check_next_prev(entry->gtkaspell, TRUE); +} + +void claws_spell_entry_check_backwards(ClawsSpellEntry *entry) +{ + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(entry->gtkaspell != NULL); + + entry->gtkaspell->continue_check = NULL; + claws_spell_entry_context_set(entry); + gtkaspell_check_next_prev(entry->gtkaspell, FALSE); +} + +void claws_spell_entry_check_forwards_go(ClawsSpellEntry *entry) +{ + g_return_if_fail(CLAWS_IS_SPELL_ENTRY(entry)); + g_return_if_fail(entry->gtkaspell != NULL); + + entry->gtkaspell->continue_check = NULL; + claws_spell_entry_context_set(entry); + gtkaspell_check_next_prev(entry->gtkaspell, TRUE); +} + +#endif /* USE_ENCHANT */ diff --git a/src/gtk/spell_entry.h b/src/gtk/spell_entry.h @@ -0,0 +1,89 @@ +/* + * @file libsexy/sexy-icon-entry.h Entry widget + * + * @Copyright (C) 2004-2006 Christian Hammond. + * Some of this code is from gtkspell, Copyright (C) 2002 Evan Martin. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + Adapted for Claws Mail (c) 2008 Pawel Pekala + */ + +#ifndef __SPELL_ENTRY_H__ +#define __SPELL_ENTRY_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef USE_ENCHANT + +G_BEGIN_DECLS + +typedef struct _ClawsSpellEntry ClawsSpellEntry; +typedef struct _ClawsSpellEntryClass ClawsSpellEntryClass; +typedef struct _ClawsSpellEntryPriv ClawsSpellEntryPriv; + +#include <gtk/gtkentry.h> +#include <gtk/gtktextview.h> +#include <gtk/gtkcombobox.h> +#include "gtkaspell.h" + +#define CLAWS_TYPE_SPELL_ENTRY (claws_spell_entry_get_type()) +#define CLAWS_SPELL_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CLAWS_TYPE_SPELL_ENTRY, ClawsSpellEntry)) +#define CLAWS_SPELL_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CLAWS_TYPE_SPELL_ENTRY, ClawsSpellEntryClass)) +#define CLAWS_IS_SPELL_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CLAWS_TYPE_SPELL_ENTRY)) + +struct _ClawsSpellEntry +{ + GtkEntry parent_object; + + ClawsSpellEntryPriv *priv; + GtkAspell *gtkaspell; + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +struct _ClawsSpellEntryClass +{ + GtkEntryClass parent_class; + + void (*gtk_reserved1)(void); + void (*gtk_reserved2)(void); + void (*gtk_reserved3)(void); + void (*gtk_reserved4)(void); +}; + +GType claws_spell_entry_get_type (void); +GtkWidget * claws_spell_entry_new (void); +void claws_spell_entry_set_gtkaspell (ClawsSpellEntry *entry, + GtkAspell *gtkaspell); +void claws_spell_entry_recheck_all (ClawsSpellEntry *entry); +void claws_spell_entry_check_all (ClawsSpellEntry *entry); +void claws_spell_entry_context_set (ClawsSpellEntry *entry); +void claws_spell_entry_check_backwards (ClawsSpellEntry *entry); +void claws_spell_entry_check_forwards_go (ClawsSpellEntry *entry); + + +G_END_DECLS + +#endif /* USE_ENCHANT */ +#endif /* __SPELL_ENTRY_H__ */