diff options
Diffstat (limited to 'widgets/text')
-rw-r--r-- | widgets/text/.cvsignore | 11 | ||||
-rw-r--r-- | widgets/text/e-completion-match.c | 185 | ||||
-rw-r--r-- | widgets/text/e-completion-match.h | 68 | ||||
-rw-r--r-- | widgets/text/e-completion-test.c | 220 | ||||
-rw-r--r-- | widgets/text/e-completion-view.c | 933 | ||||
-rw-r--r-- | widgets/text/e-completion-view.h | 102 | ||||
-rw-r--r-- | widgets/text/e-completion.c | 640 | ||||
-rw-r--r-- | widgets/text/e-completion.h | 102 | ||||
-rw-r--r-- | widgets/text/e-entry-test.c | 83 | ||||
-rw-r--r-- | widgets/text/e-entry.c | 1400 | ||||
-rw-r--r-- | widgets/text/e-entry.h | 87 | ||||
-rw-r--r-- | widgets/text/e-table-text-model.c | 234 | ||||
-rw-r--r-- | widgets/text/e-table-text-model.h | 64 | ||||
-rw-r--r-- | widgets/text/e-text-model-repos.c | 87 | ||||
-rw-r--r-- | widgets/text/e-text-model-repos.h | 69 | ||||
-rw-r--r-- | widgets/text/e-text-model-test.c | 91 | ||||
-rw-r--r-- | widgets/text/e-text-model-uri.c | 344 | ||||
-rw-r--r-- | widgets/text/e-text-model-uri.h | 56 | ||||
-rw-r--r-- | widgets/text/e-text-model.c | 633 | ||||
-rw-r--r-- | widgets/text/e-text-model.h | 113 | ||||
-rw-r--r-- | widgets/text/e-text-test.c | 168 | ||||
-rw-r--r-- | widgets/text/e-text.c | 3876 | ||||
-rw-r--r-- | widgets/text/e-text.h | 275 |
23 files changed, 0 insertions, 9841 deletions
diff --git a/widgets/text/.cvsignore b/widgets/text/.cvsignore deleted file mode 100644 index 792b9f5af2..0000000000 --- a/widgets/text/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -.libs -.pure -Makefile -Makefile.in -*.lo -*.la -e-text-test -e-entry-test -e-text-model-test -e-completion-test
\ No newline at end of file diff --git a/widgets/text/e-completion-match.c b/widgets/text/e-completion-match.c deleted file mode 100644 index 0da197d1fe..0000000000 --- a/widgets/text/e-completion-match.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion-match.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> -#include <string.h> -#include <gal/widgets/e-unicode.h> -#include "e-completion-match.h" - -static void -e_completion_match_destroy (ECompletionMatch *match) -{ - if (match) { - g_free (match->match_text); - g_free (match->menu_text); - if (match->destroy) - match->destroy (match); - g_free (match); - } -} - -void -e_completion_match_construct (ECompletionMatch *match) -{ - g_return_if_fail (match != NULL); - - match->match_text = NULL; - match->menu_text = NULL; - match->score = 0; - match->sort_major = 0; - match->sort_minor = 0; - match->user_data = NULL; - match->ref = 1; - match->hit_count = 0; - match->destroy = NULL; -} - -void -e_completion_match_ref (ECompletionMatch *match) -{ - g_return_if_fail (match != NULL); - g_return_if_fail (match->ref > 0); - - ++match->ref; -} - -void -e_completion_match_unref (ECompletionMatch *match) -{ - if (match) { - g_return_if_fail (match->ref > 0); - - --match->ref; - if (match->ref == 0) { - e_completion_match_destroy (match); - } - } -} - -void -e_completion_match_set_text (ECompletionMatch *match, - const gchar *match_text, - const gchar *menu_text) -{ - g_return_if_fail (match != NULL); - - /* We silently drop any entries w/ invalid utf8. - This is not optimal behavior. */ - - if (match_text && ! g_utf8_validate (match_text, -1, NULL)) { - match_text = NULL; - } - - if (menu_text && ! g_utf8_validate (menu_text, -1, NULL)) { - menu_text = NULL; - } - - if (match->match_text && match->match_text != match_text) { - g_free (match->match_text); - } - match->match_text = g_strdup (match_text); - - if (match->menu_text && match->menu_text != menu_text) { - g_free (match->menu_text); - } - match->menu_text = g_strdup (menu_text); -} - -const gchar * -e_completion_match_get_match_text (ECompletionMatch *match) -{ - g_return_val_if_fail (match != NULL, NULL); - return match->match_text; -} - -const gchar * -e_completion_match_get_menu_text (ECompletionMatch *match) -{ - g_return_val_if_fail (match != NULL, NULL); - return match->menu_text; -} - -gint -e_completion_match_compare (const ECompletionMatch *a, const ECompletionMatch *b) -{ - gint rv; - - /* Deal with NULL arguments. */ - if (!(a || b)) { - if (!(a && b)) - return 0; - return a ? -1 : 1; - } - - if ( (rv = (b->sort_major < a->sort_major) - (a->sort_major < b->sort_major)) ) - return rv; - - /* Sort the scores high->low. */ - if ( (rv = (b->score > a->score) - (a->score > b->score)) ) - return rv; - - if ( (rv = (b->sort_minor < a->sort_minor) - (a->sort_minor < b->sort_minor)) ) - return rv; - - return 0; -} - -gint -e_completion_match_compare_alpha (const ECompletionMatch *a, const ECompletionMatch *b) -{ - gint rv, rv2; - - /* Deal with NULL arguments. */ - if (!(a || b)) { - if (!(a && b)) - return 0; - return a ? -1 : 1; - } - - /* The sort_major trumps everything. */ - if ( (rv = (b->sort_major < a->sort_major) - (a->sort_major < b->sort_major)) ) - return rv; - - /* Sort the scores high->low. */ - if ( (rv = (b->score > a->score) - (a->score > b->score)) ) - return rv; - - /* When the match text is the same, we use the minor fields */ - rv2 = strcmp (a->match_text, b->match_text); - if ( !rv2 && (rv = (b->sort_minor < a->sort_minor) - (a->sort_minor < b->sort_minor)) ) - return rv; - - return strcmp (a->menu_text, b->menu_text); -} - -ECompletionMatch * -e_completion_match_new (const gchar *match_text, const gchar *menu_text, double score) -{ - ECompletionMatch *match = g_new0 (ECompletionMatch, 1); - - e_completion_match_construct (match); - e_completion_match_set_text (match, match_text, menu_text); - match->score = score; - - return match; -} diff --git a/widgets/text/e-completion-match.h b/widgets/text/e-completion-match.h deleted file mode 100644 index f2773ee094..0000000000 --- a/widgets/text/e-completion-match.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion-match.h - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef __E_COMPLETION_MATCH_H__ -#define __E_COMPLETION_MATCH_H__ - -#include <glib.h> -#include <gtk/gtkwidget.h> - -G_BEGIN_DECLS - -typedef struct _ECompletionMatch ECompletionMatch; - -struct _ECompletionMatch { - gchar *match_text; /* in utf8 */ - gchar *menu_text; /* in utf8 */ - double score; - gint sort_major; - gint sort_minor; - gpointer user_data; - - gint ref; - gint hit_count; - void (*destroy) (ECompletionMatch *); -}; - -typedef void (*ECompletionMatchFn) (ECompletionMatch *, gpointer closure); - -void e_completion_match_construct (ECompletionMatch *); -void e_completion_match_ref (ECompletionMatch *); -void e_completion_match_unref (ECompletionMatch *); - -void e_completion_match_set_text (ECompletionMatch *, const gchar *match_text, const gchar *label_text); -const gchar *e_completion_match_get_match_text (ECompletionMatch *); -const gchar *e_completion_match_get_menu_text (ECompletionMatch *); - -gint e_completion_match_compare (const ECompletionMatch *, const ECompletionMatch *); -gint e_completion_match_compare_alpha (const ECompletionMatch *, const ECompletionMatch *); - -ECompletionMatch *e_completion_match_new (const gchar *match_text, const gchar *menu_text, double score); - - - - -G_END_DECLS - -#endif /* __E_COMPLETION_MATCH_H__ */ - diff --git a/widgets/text/e-completion-test.c b/widgets/text/e-completion-test.c deleted file mode 100644 index dfefe23e1b..0000000000 --- a/widgets/text/e-completion-test.c +++ /dev/null @@ -1,220 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion-test.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <gnome.h> -#include "e-completion.h" -#include "e-entry.h" - -#define TIMEOUT 10 - -/* Dictionary Lookup test */ - -static gint word_count = 0; -static gchar **word_array = NULL; - -static void -read_dict (void) -{ - FILE *in = fopen ("/usr/share/dict/words", "r"); - gchar buffer[128]; - GList *word_list = NULL, *iter; - gint i; - - while (fgets (buffer, 128, in)) { - gint len = strlen (buffer); - if (len > 0 && buffer[len-1] == '\n') - buffer[len-1] = '\0'; - word_list = g_list_prepend (word_list, g_strdup (buffer)); - ++word_count; - } - fclose (in); - - word_array = g_new (gchar *, word_count); - i = word_count-1; - for (iter = word_list; iter != NULL; iter = g_list_next (iter)) { - word_array[i] = (gchar *)iter->data; - --i; - } -} - -static gint -find_word (const gchar *str) -{ - gint a, b; - - if (word_array == NULL) - read_dict (); - - a = 0; - b = word_count-1; - - while (b-a > 1) { - gint m = (a+b)/2; - gint cmp = g_strcasecmp (str, word_array[m]); - - if (cmp < 0) - b = m; - else if (cmp > 0) - a = m; - else - return m; - } - - return b; -} - -struct { - ECompletion *complete; - const gchar *txt; - gint start; - gint current; - gint len; - gint limit; - gint count; -} dict_info; -static guint dict_tag = 0; - -static gboolean -dict_check (gpointer ptr) -{ - gint limit = dict_info.limit; - gint i; - - /* If this is the first iteration, do the binary search in our word list to figure out - where to start. We do less work on the first iteration, to give more of a sense of - immediate feedback. */ - if (dict_info.start < 0) { - dict_info.start = dict_info.current = find_word (dict_info.txt); - } - - i = dict_info.current; - while (limit > 0 - && i < word_count - && dict_info.count < 50 - && g_strncasecmp (dict_info.txt, word_array[i], dict_info.len) == 0) { - - ECompletionMatch *match = g_new (ECompletionMatch, 1); - e_completion_match_construct (match); - e_completion_match_set_text (match, word_array[i], NULL); - match->score = dict_info.len / (double)strlen (word_array[i]); - e_completion_found_match (dict_info.complete, match); - - ++i; - --limit; - ++dict_info.count; - } - dict_info.current = i; - dict_info.limit = MIN (dict_info.limit*2, 400); - - if (limit != 0) { - dict_tag = 0; - e_completion_end_search (dict_info.complete); - return FALSE; - } - - - - return TRUE; -} - -static void -request_dict_search (ECompletion *complete, const gchar *txt, gint pos, gint limit, gpointer user_data) -{ - gint len = strlen (txt); - - if (dict_tag != 0) { - gtk_timeout_remove (dict_tag); - dict_tag = 0; - } - - if (len > 0) { - dict_info.complete = complete; - dict_info.txt = txt; - dict_info.start = -1; - dict_info.current = -1; - dict_info.len = len; - dict_info.limit = 100; - dict_info.count = 0; - dict_tag = gtk_timeout_add (TIMEOUT, dict_check, NULL); - } else { - e_completion_end_search (complete); - } -} - -static void -end_dict_search (ECompletion *complete, gpointer user_data) -{ - if (dict_tag != 0) { - gtk_timeout_remove (dict_tag); - dict_tag = 0; - } -} - -static void -popup_cb (EEntry *popup, GdkEventButton *ev, gint pos, gpointer user_data) -{ - g_print ("popup at pos %d\n", pos); -} - -int -main (int argc, gchar **argv) -{ - ECompletion* complete; - GtkWidget *entry; - GtkWidget *win; - - gnome_init ("ETextModelTest", "0.0", argc, argv); - - read_dict (); - - complete = e_completion_new (); - g_signal_connect (complete, - "request_completion", - G_CALLBACK (request_dict_search), - NULL); - g_signal_connect (complete, - "end_completion", - G_CALLBACK (end_dict_search), - NULL); - g_signal_connect (complete, - "cancel_completion", - G_CALLBACK (end_dict_search), - NULL); - - win = gtk_window_new (GTK_WINDOW_TOPLEVEL); - entry = e_entry_new (); - e_entry_enable_completion_full (E_ENTRY (entry), complete, 0, NULL); - e_entry_set_editable (E_ENTRY (entry), TRUE); - - g_signal_connect (entry, - "popup", - G_CALLBACK (popup_cb), - NULL); - - gtk_container_add (GTK_CONTAINER (win), entry); - gtk_widget_show_all (win); - - gtk_main (); - - return 0; -} diff --git a/widgets/text/e-completion-view.c b/widgets/text/e-completion-view.c deleted file mode 100644 index 4e5bba3f9e..0000000000 --- a/widgets/text/e-completion-view.c +++ /dev/null @@ -1,933 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion-view.c - A text completion selection widget - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Miguel de Icaza <miguel@ximian.com> - * Adapted by Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> - -#include "e-completion-view.h" - -#include <math.h> -#include <gdk/gdkkeysyms.h> -#include <gal/e-table/e-table-simple.h> -#include <gal/e-table/e-table-scrolled.h> -#include <gal/util/e-i18n.h> -#include "gal/util/e-marshal.h" - -enum { - E_COMPLETION_VIEW_NONEMPTY, - E_COMPLETION_VIEW_ADDED, - E_COMPLETION_VIEW_FULL, - E_COMPLETION_VIEW_BROWSE, - E_COMPLETION_VIEW_UNBROWSE, - E_COMPLETION_VIEW_ACTIVATE, - E_COMPLETION_VIEW_LAST_SIGNAL -}; - -static guint e_completion_view_signals[E_COMPLETION_VIEW_LAST_SIGNAL] = { 0 }; - -static void e_completion_view_disconnect (ECompletionView *cv); -static ETable *e_completion_view_table (ECompletionView *cv); -static void e_completion_view_clear_choices (ECompletionView *cv); -static void e_completion_view_set_cursor_row (ECompletionView *cv, gint r); -static void e_completion_view_select (ECompletionView *cv, gint r); - -static gint e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpointer user_data); - -static void e_completion_view_class_init (ECompletionViewClass *klass); -static void e_completion_view_init (ECompletionView *completion); -static void e_completion_view_dispose (GObject *object); - -#define PARENT_TYPE GTK_TYPE_EVENT_BOX -static GtkObjectClass *parent_class; - - - -static gint -e_completion_view_local_key_press_handler (GtkWidget *w, GdkEventKey *ev) -{ - return e_completion_view_key_press_handler (w, ev, w); -} - -static void -e_completion_view_paint (GtkWidget *widget, GdkRectangle *area) -{ - gint i; - - g_return_if_fail (widget != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (widget)); - g_return_if_fail (area != NULL); - - if (!GTK_WIDGET_DRAWABLE (widget)) - return; - - for (i = 0; i < E_COMPLETION_VIEW (widget)->border_width; ++i) { - - gdk_draw_rectangle (widget->window, - widget->style->black_gc, - FALSE, i, i, - widget->allocation.width-1-2*i, - widget->allocation.height-1-2*i); - - } - -} - -#if 0 -static void -e_completion_view_draw (GtkWidget *widget, GdkRectangle *area) -{ - GtkBin *bin; - GdkRectangle child_area; - - g_return_if_fail (widget != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (widget)); - g_return_if_fail (area != NULL); - - if (GTK_WIDGET_DRAWABLE (widget)) { - bin = GTK_BIN (widget); - - e_completion_view_paint (widget, area); - - if (bin->child && gtk_widget_intersect (bin->child, area, &child_area)) - gtk_widget_draw (bin->child, &child_area); - } -} -#endif - -static gint -e_completion_view_expose_event (GtkWidget *widget, GdkEventExpose *event) -{ - GtkBin *bin; - GdkEventExpose child_event; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (E_IS_COMPLETION_VIEW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - if (GTK_WIDGET_DRAWABLE (widget)) { - bin = GTK_BIN (widget); - - e_completion_view_paint (widget, &event->area); - - child_event = *event; - if (bin->child && - GTK_WIDGET_NO_WINDOW (bin->child) && - gtk_widget_intersect (bin->child, &event->area, &child_event.area)) - gtk_widget_event (bin->child, (GdkEvent*) &child_event); - } - - return FALSE; -} - -static void -e_completion_view_size_request (GtkWidget *widget, GtkRequisition *requisition) -{ - GtkBin *bin; - - g_return_if_fail (widget != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (widget)); - g_return_if_fail (requisition != NULL); - - bin = GTK_BIN (widget); - - requisition->width = 2 * E_COMPLETION_VIEW (widget)->border_width; - requisition->height = 2 * E_COMPLETION_VIEW (widget)->border_width; - - if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { - GtkRequisition child_requisition; - - gtk_widget_size_request (bin->child, &child_requisition); - - requisition->width += child_requisition.width; - requisition->height += child_requisition.height; - } -} - -static void -e_completion_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) -{ - GtkBin *bin; - GtkAllocation child_allocation; - - g_return_if_fail (widget != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (widget)); - g_return_if_fail (allocation != NULL); - - bin = GTK_BIN (widget); - widget->allocation = *allocation; - - child_allocation.x = E_COMPLETION_VIEW (widget)->border_width; - child_allocation.width = MAX(0, (gint)allocation->width - child_allocation.x * 2); - - child_allocation.y = E_COMPLETION_VIEW (widget)->border_width; - child_allocation.height = MAX (0, (gint)allocation->height - child_allocation.y * 2); - - if (GTK_WIDGET_REALIZED (widget)) { - gdk_window_move_resize (widget->window, - allocation->x, - allocation->y, - allocation->width, - allocation->height); - } - - if (bin->child) { - gtk_widget_size_allocate (bin->child, &child_allocation); - } -} - -E_MAKE_TYPE (e_completion_view, - "ECompletionView", - ECompletionView, - e_completion_view_class_init, - e_completion_view_init, - PARENT_TYPE) - -static void -e_completion_view_class_init (ECompletionViewClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - e_completion_view_signals[E_COMPLETION_VIEW_NONEMPTY] = - g_signal_new ("nonempty", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, nonempty), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_view_signals[E_COMPLETION_VIEW_ADDED] = - g_signal_new ("added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, added), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_view_signals[E_COMPLETION_VIEW_FULL] = - g_signal_new ("full", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, full), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_view_signals[E_COMPLETION_VIEW_BROWSE] = - g_signal_new ("browse", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, browse), - NULL, NULL, - e_marshal_NONE__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - - e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE] = - g_signal_new ("unbrowse", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, unbrowse), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_view_signals[E_COMPLETION_VIEW_ACTIVATE] = - g_signal_new ("activate", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionViewClass, activate), - NULL, NULL, - e_marshal_NONE__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - - object_class->dispose = e_completion_view_dispose; - - widget_class->key_press_event = e_completion_view_local_key_press_handler; - widget_class->expose_event = e_completion_view_expose_event; - widget_class->size_request = e_completion_view_size_request; - widget_class->size_allocate = e_completion_view_size_allocate; -} - -static void -e_completion_view_init (ECompletionView *completion) -{ - completion->border_width = 2; - completion->choices = g_ptr_array_new (); -} - -static void -e_completion_view_dispose (GObject *object) -{ - ECompletionView *cv = E_COMPLETION_VIEW (object); - - e_completion_view_disconnect (cv); - - if (cv->choices) { - e_completion_view_clear_choices (cv); - - g_ptr_array_free (cv->choices, TRUE); - cv->choices = NULL; - } - - if (cv->key_widget) { - g_signal_handler_disconnect (cv->key_widget, cv->key_signal_id); - g_object_unref (cv->key_widget); - cv->key_widget = NULL; - } - - if (cv->completion) - g_object_unref (cv->completion); - cv->completion = NULL; - - if (G_OBJECT_CLASS (parent_class)->dispose) - (G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -e_completion_view_disconnect (ECompletionView *cv) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - - if (cv->begin_signal_id) - g_signal_handler_disconnect (cv->completion, cv->begin_signal_id); - if (cv->comp_signal_id) - g_signal_handler_disconnect (cv->completion, cv->comp_signal_id); - if (cv->restart_signal_id) - g_signal_handler_disconnect (cv->completion, cv->restart_signal_id); - if (cv->cancel_signal_id) - g_signal_handler_disconnect (cv->completion, cv->cancel_signal_id); - if (cv->end_signal_id) - g_signal_handler_disconnect (cv->completion, cv->end_signal_id); - if (cv->clear_signal_id) - g_signal_handler_disconnect (cv->completion, cv->clear_signal_id); - if (cv->lost_signal_id) - g_signal_handler_disconnect (cv->completion, cv->lost_signal_id); - - cv->begin_signal_id = 0; - cv->comp_signal_id = 0; - cv->restart_signal_id = 0; - cv->cancel_signal_id = 0; - cv->end_signal_id = 0; - cv->clear_signal_id = 0; - cv->lost_signal_id = 0; -} - -static ETable * -e_completion_view_table (ECompletionView *cv) -{ - return e_table_scrolled_get_table (E_TABLE_SCROLLED (cv->table)); -} - -static void -e_completion_view_clear_choices (ECompletionView *cv) -{ - ECompletionMatch *match; - GPtrArray *m; - int i; - - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - - m = cv->choices; - for (i = 0; i < m->len; i++) { - match = g_ptr_array_index (m, i); - e_completion_match_unref (match); - } - g_ptr_array_set_size (m, 0); -} - -static void -e_completion_view_set_cursor_row (ECompletionView *cv, gint r) -{ - ETable *table; - GtkAdjustment *adj; - gint x, y1, y2, r1, r2, c; - double fracline; - gint iteration_count=0; - - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); -#ifndef G_DISABLE_CHECKS - /* choices->len is unsigned, but it is reasonable for r to be - * < 0 */ - if (r > 0) { - g_return_if_fail (r < cv->choices->len); - } -#endif - - adj = e_scroll_frame_get_vadjustment (E_SCROLL_FRAME (cv->table)); - - table = e_completion_view_table (cv); - - if (r < 0) { - e_selection_model_clear (E_SELECTION_MODEL(table->selection)); - - /* Move back to the top when we clear the selection */ - gtk_adjustment_set_value (adj, adj->lower); - return; - } - - e_table_set_cursor_row (table, r); - - /* OK, now the tricky bit. We try to insure that this row is - visible. */ - - /* If we are selecting the first or last row, then it is easy. We just - cram the vadjustment all the way up/down. */ - if (r == 0) { - gtk_adjustment_set_value (adj, adj->lower); - return; - } else if (r == cv->choices->len - 1) { - gtk_adjustment_set_value (adj, adj->upper - adj->page_size); - return; - } - - fracline = ((adj->upper - adj->lower - adj->page_size) / (gint)cv->choices->len) / 4; - - while (iteration_count < 100) { - x = GTK_LAYOUT(table->table_canvas)->hadjustment->value; - y1 = GTK_LAYOUT(table->table_canvas)->vadjustment->value; - - y2 = y1 + cv->table->allocation.height; - - e_table_group_compute_location (e_completion_view_table (cv)->group, &x, &y1, &r1, &c); - e_table_group_compute_location (e_completion_view_table (cv)->group, &x, &y2, &r2, &c); - - if (r <= r1) { - gtk_adjustment_set_value (adj, adj->value - fracline); - } else if (r >= r2) { - gtk_adjustment_set_value (adj, adj->value + fracline); - } else - return; - - ++iteration_count; - } - - g_assert_not_reached (); -} - -static void -e_completion_view_select (ECompletionView *cv, gint r) -{ - ECompletionMatch *match; - - match = g_ptr_array_index (cv->choices, r); - - cv->selection = r; - e_completion_view_set_cursor_row (cv, r); - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_ACTIVATE], 0, match); -} - -static gint -e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - gint dir = 0; - gboolean key_handled = TRUE, complete_key = FALSE, uncomplete_key = FALSE, is_space = FALSE; - - /* FIXME: This is totally lame. - The ECompletionView should be able to specify multiple completion/uncompletion keys, or just - have sensible defaults. */ - - if ((cv->complete_key && key_event->keyval == cv->complete_key) - || ((key_event->keyval == GDK_n || key_event->keyval == GDK_N) && (key_event->state & GDK_CONTROL_MASK))) - complete_key = TRUE; - - if ((cv->uncomplete_key && key_event->keyval == cv->uncomplete_key) - || ((key_event->keyval == GDK_p || key_event->keyval == GDK_P) && (key_event->state & GDK_CONTROL_MASK))) - uncomplete_key = TRUE; - - /* Start up a completion.*/ - if (complete_key && !cv->editable) { - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_BROWSE], 0, NULL); - goto stop_emission; - } - - /* Stop our completion. */ - if (uncomplete_key && cv->editable && cv->selection < 0) { - e_completion_view_set_cursor_row (cv, -1); - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE], 0); - goto stop_emission; - } - - if (!cv->editable) - return FALSE; - - switch (key_event->keyval) { - - case GDK_n: - case GDK_N: - /* We (heart) emacs: treat ctrl-n as down */ - if (! (key_event->state & GDK_CONTROL_MASK)) - return FALSE; - - case GDK_Down: - case GDK_KP_Down: - dir = 1; - break; - - case GDK_p: - case GDK_P: - /* Treat ctrl-p as up */ - if (! (key_event->state & GDK_CONTROL_MASK)) - return FALSE; - - case GDK_Up: - case GDK_KP_Up: - dir = -1; - break; - - case GDK_Tab: - /* If our cursor is still up in the entry, move down into - the popup. Otherwise unbrowse. */ - if (cv->choices->len > 0) { - if (cv->selection < 0) { - cv->selection = 0; - dir = 0; - } else { - cv->selection = -1; - dir = 0; - key_handled = FALSE; - } - } - break; - - case GDK_space: - case GDK_KP_Space: - is_space = TRUE; - - case GDK_Return: - case GDK_KP_Enter: - if (cv->selection < 0) { - /* We don't have a selection yet, move to the first selection if there is - more than one option. If there is only one option, select it automatically. */ - - /* Let space pass through. */ - if (is_space) - return FALSE; - - if (cv->choices->len == 1) { - e_completion_view_select (cv, 0); - goto stop_emission; - } else { - cv->selection = 0; - dir = 0; - } - - } else { - /* Our cursor is down in the pop-up, so we make our selection. */ - e_completion_view_select (cv, cv->selection); - goto stop_emission; - } - break; - - case GDK_Escape: - /* Unbrowse hack */ - cv->selection = -1; - dir = 0; - break; - - default: - return FALSE; - } - - cv->selection += dir; - - if (cv->selection >= (int)cv->choices->len) { - cv->selection = cv->choices->len - 1; - /* Don't re-emit the browse signal */ - goto stop_emission; - } - - e_completion_view_set_cursor_row (cv, cv->selection); - - if (cv->selection >= 0) - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_BROWSE], 0, - g_ptr_array_index (cv->choices, cv->selection)); - else - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE], 0); - - stop_emission: - - if (key_handled) - g_signal_stop_emission_by_name (w, "key_press_event"); - - return key_handled; -} - -static void -begin_completion_cb (ECompletion *completion, const gchar *txt, gint pos, gint limit, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - - e_completion_view_clear_choices (cv); - cv->have_all_choices = FALSE; - - e_table_model_changed (cv->model); -} - -static void -restart_completion_cb (ECompletion *completion, gpointer user_data) -{ - /* For now, handle restarts like the beginning of a new completion. */ - begin_completion_cb (completion, NULL, 0, 0, user_data); -} - -static void -cancel_completion_cb (ECompletion *completion, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - - /* On a cancel, clear our choices and issue an "unbrowse" signal. */ - e_completion_view_clear_choices (cv); - cv->have_all_choices = TRUE; - e_completion_view_set_cursor_row (cv, -1); - e_table_model_changed (cv->model); - - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE] ,0); -} - -static void -completion_cb (ECompletion *completion, ECompletionMatch *match, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - gint r = cv->choices->len; - gboolean first = (cv->choices->len == 0); - - e_completion_match_ref (match); - g_ptr_array_add (cv->choices, match); - - e_table_model_row_inserted (cv->model, r); - - if (first) - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_NONEMPTY], 0); - - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_ADDED], 0); -} - -static void -end_completion_cb (ECompletion *completion, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - - /* Do a final refresh of the table. */ - e_table_model_changed (cv->model); - - cv->have_all_choices = TRUE; - g_signal_emit (cv, e_completion_view_signals[E_COMPLETION_VIEW_FULL], 0); -} - -static void -clear_completion_cb (ECompletion *completion, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - - e_completion_view_clear_choices (cv); - cv->have_all_choices = FALSE; - - e_table_model_changed (cv->model); -} - -static void -lost_completion_cb (ECompletion *completion, ECompletionMatch *match, gpointer user_data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (user_data); - int i; - GPtrArray *c = cv->choices; - - for (i = 0; i < c->len; i++) - if (g_ptr_array_index (c, i) == match) - break; - - g_return_if_fail (i == c->len); - - /* FIXME: do remove_index_fast(), then row_changed and - * row_deleted (if there are more than 1 row still) */ - g_ptr_array_remove_index (c, i); - e_table_model_row_deleted (cv->model, i); - - e_completion_match_unref (match); -} - -/*** Table Callbacks ***/ - -static char *simple_spec = -"<ETableSpecification no-headers=\"true\" draw-grid=\"false\" cursor-mode=\"line\" alternating-row-colors=\"false\" gettext-domain=\"" E_I18N_DOMAIN "\">" -" <ETableColumn model_col=\"0\" _title=\"Node\" expansion=\"1.0\" " -" minimum_width=\"16\" resizable=\"true\" cell=\"string\" " -" compare=\"string\"/> " -" <ETableState> " -" <column source=\"0\"/> " -" <grouping></grouping> " -" </ETableState> " -"</ETableSpecification>"; - -static gint -table_col_count (ETableModel *etm, gpointer data) -{ - return 1; -} - -static gint -table_row_count (ETableModel *etm, gpointer data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (data); - return cv->choices->len; -} - -static gboolean -table_is_cell_editable (ETableModel *etm, gint c, gint r, gpointer data) -{ - return FALSE; -} - -static gpointer -table_value_at (ETableModel *etm, gint c, gint r, gpointer data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (data); - ECompletionMatch *match; - - match = g_ptr_array_index (cv->choices, r); - - return (gpointer) e_completion_match_get_menu_text (match); -} - -static gchar * -table_value_to_string (ETableModel *em, gint col, gconstpointer val, gpointer data) -{ - return (gchar *) val; -} - -static void -table_click_cb (ETable *et, gint r, gint c, GdkEvent *ev, gpointer data) -{ - ECompletionView *cv = E_COMPLETION_VIEW (data); - - e_completion_view_select (cv, r); -} - -void -e_completion_view_construct (ECompletionView *cv, ECompletion *completion) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - g_return_if_fail (completion != NULL); - g_return_if_fail (E_IS_COMPLETION (completion)); - - /* Make sure we don't call construct twice. */ - g_return_if_fail (cv->completion == NULL); - - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (cv), GTK_CAN_FOCUS); - - cv->completion = completion; - g_object_ref (completion); - - cv->begin_signal_id = g_signal_connect (completion, - "begin_completion", - G_CALLBACK (begin_completion_cb), - cv); - cv->comp_signal_id = g_signal_connect (completion, - "completion", - G_CALLBACK (completion_cb), - cv); - cv->restart_signal_id = g_signal_connect (completion, - "restart_completion", - G_CALLBACK (restart_completion_cb), - cv); - cv->cancel_signal_id = g_signal_connect (completion, - "cancel_completion", - G_CALLBACK (cancel_completion_cb), - cv); - cv->end_signal_id = g_signal_connect (completion, - "end_completion", - G_CALLBACK (end_completion_cb), - cv); - cv->clear_signal_id = g_signal_connect (completion, - "clear_completion", - G_CALLBACK (clear_completion_cb), - cv); - cv->lost_signal_id = g_signal_connect (completion, - "lost_completion", - G_CALLBACK (lost_completion_cb), - cv); - - cv->model = e_table_simple_new (table_col_count, - table_row_count, - NULL, - - table_value_at, - NULL, - table_is_cell_editable, - - NULL, NULL, - - NULL, NULL, NULL, NULL, - table_value_to_string, - cv); - - cv->table = e_table_scrolled_new (cv->model, NULL, simple_spec, NULL); - g_object_unref (cv->model); - - e_scroll_frame_set_shadow_type (E_SCROLL_FRAME (cv->table), GTK_SHADOW_NONE); - e_scroll_frame_set_scrollbar_spacing (E_SCROLL_FRAME (cv->table), 0); - e_scroll_frame_set_policy (E_SCROLL_FRAME (cv->table), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - - gtk_container_add (GTK_CONTAINER (cv), cv->table); - gtk_widget_show_all (cv->table); - - g_signal_connect (e_completion_view_table (cv), - "click", - G_CALLBACK (table_click_cb), - cv); - - cv->selection = -1; -} - -GtkWidget * -e_completion_view_new (ECompletion *completion) -{ - gpointer p; - - g_return_val_if_fail (completion != NULL, NULL); - g_return_val_if_fail (E_IS_COMPLETION (completion), NULL); - - p = g_object_new (E_COMPLETION_VIEW_TYPE, NULL); - - e_completion_view_construct (E_COMPLETION_VIEW (p), completion); - - return GTK_WIDGET (p); -} - -void -e_completion_view_connect_keys (ECompletionView *cv, GtkWidget *w) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - g_return_if_fail (w == NULL || GTK_IS_WIDGET (w)); - - if (cv->key_widget) { - g_signal_handler_disconnect (cv->key_widget, cv->key_signal_id); - g_object_unref (cv->key_widget); - } - - if (w) { - cv->key_widget = w; - g_object_ref (w); - - cv->key_signal_id = g_signal_connect (w, - "key_press_event", - G_CALLBACK (e_completion_view_key_press_handler), - cv); - } else { - cv->key_widget = NULL; - cv->key_signal_id = 0; - } -} - -void -e_completion_view_set_complete_key (ECompletionView *cv, gint keyval) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - - cv->complete_key = keyval; -} - -void -e_completion_view_set_uncomplete_key (ECompletionView *cv, gint keyval) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - - cv->uncomplete_key = keyval; -} - -void -e_completion_view_set_width (ECompletionView *cv, gint width) -{ - GtkWidget *w; - gint y, r, dummy, line_height, final_height; - double drop_room, lines; - - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - g_return_if_fail (width > 0); - - w = GTK_WIDGET (cv); - - if (! GTK_WIDGET_REALIZED (w)) { - gtk_widget_set_usize (w, width, -1); - return; - } - - /* A Horrible Hack(tm) to figure out the height of a single table row */ - - for (line_height=5, r=0; r == 0 && line_height < 1000; line_height += 2) { - dummy = 0; - e_table_group_compute_location (e_completion_view_table (cv)->group, - &dummy, &line_height, &r, &dummy); - } - - if (line_height >= 1000) { - /* Something went wrong, so we make a (possibly very lame) guess */ - line_height = 30; - } - - - gdk_window_get_origin (w->window, NULL, &y); - y += w->allocation.y; - - lines = 5; /* default maximum */ - lines = MIN (lines, cv->choices->len); - - drop_room = (gdk_screen_height () - y) / (double)line_height; - drop_room = MAX (drop_room, 1); - - lines = MIN (lines, drop_room); - - /* We reduce the total height by a bit; in practice, this seems to work out well. */ - final_height = (gint) floor (line_height * (0.5 + (float)lines) * 0.97); - gtk_widget_set_usize (w, width, final_height); -} - -void -e_completion_view_set_editable (ECompletionView *cv, gboolean x) -{ - g_return_if_fail (cv != NULL); - g_return_if_fail (E_IS_COMPLETION_VIEW (cv)); - - if (x == cv->editable) - return; - - cv->editable = x; - cv->selection = -1; - e_completion_view_set_cursor_row (cv, -1); -} - - diff --git a/widgets/text/e-completion-view.h b/widgets/text/e-completion-view.h deleted file mode 100644 index 9aa3860ebd..0000000000 --- a/widgets/text/e-completion-view.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion-view.h - A text completion selection widget - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Miguel de Icaza <miguel@ximian.com> - * Adapted by Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_COMPLETION_VIEW_H -#define E_COMPLETION_VIEW_H - -#include <gtk/gtk.h> -#include <gal/e-table/e-table.h> -#include "e-completion.h" - -G_BEGIN_DECLS - -#define E_COMPLETION_VIEW_TYPE (e_completion_view_get_type ()) -#define E_COMPLETION_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_COMPLETION_VIEW_TYPE, ECompletionView)) -#define E_COMPLETION_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_COMPLETION_VIEW_TYPE, ECompletionViewClass)) -#define E_IS_COMPLETION_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_COMPLETION_VIEW_TYPE)) -#define E_IS_COMPLETION_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_COMPLETION_VIEW_TYPE)) - -typedef struct _ECompletionView ECompletionView; -typedef struct _ECompletionViewClass ECompletionViewClass; - -struct _ECompletionView { - GtkEventBox parent; - - ETableModel *model; - GtkWidget *table; - - GPtrArray *choices; - - ECompletion *completion; - guint begin_signal_id; - guint comp_signal_id; - guint restart_signal_id; - guint cancel_signal_id; - guint end_signal_id; - guint clear_signal_id; - guint lost_signal_id; - - GtkWidget *key_widget; - guint key_signal_id; - - gint complete_key; - gint uncomplete_key; - - gboolean have_all_choices; - - gboolean editable; - gint selection; - - gint border_width; -}; - -struct _ECompletionViewClass { - GtkEventBoxClass parent_class; - - /* Signals */ - void (*nonempty) (ECompletionView *cv); - void (*added) (ECompletionView *cv); - void (*full) (ECompletionView *cv); - void (*browse) (ECompletionView *cv, ECompletionMatch *match); - void (*unbrowse) (ECompletionView *cv); - void (*activate) (ECompletionView *cv, ECompletionMatch *match); -}; - -GtkType e_completion_view_get_type (void); - -void e_completion_view_construct (ECompletionView *cv, ECompletion *completion); -GtkWidget *e_completion_view_new (ECompletion *completion); - -void e_completion_view_connect_keys (ECompletionView *cv, GtkWidget *w); - -void e_completion_view_set_complete_key (ECompletionView *cv, gint keyval); -void e_completion_view_set_uncomplete_key (ECompletionView *cv, gint keyval); - -void e_completion_view_set_width (ECompletionView *cv, gint width); -void e_completion_view_set_editable (ECompletionView *cv, gboolean); - -G_END_DECLS - - -#endif /* E_COMPLETION_H */ diff --git a/widgets/text/e-completion.c b/widgets/text/e-completion.c deleted file mode 100644 index cddd6ed4f4..0000000000 --- a/widgets/text/e-completion.c +++ /dev/null @@ -1,640 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion.c - A base class for text completion. - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Miguel de Icaza <miguel@ximian.com> - * Adapted by Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> -#include <string.h> -#include <stdio.h> -#include <gtk/gtk.h> -#include "e-completion.h" -#include "gal/util/e-util.h" -#include "gal/util/e-marshal.h" - -enum { - E_COMPLETION_REQUEST_COMPLETION, - E_COMPLETION_BEGIN_COMPLETION, - E_COMPLETION_COMPLETION, - E_COMPLETION_RESTART_COMPLETION, - E_COMPLETION_CANCEL_COMPLETION, - E_COMPLETION_END_COMPLETION, - E_COMPLETION_CLEAR_COMPLETION, - E_COMPLETION_LOST_COMPLETION, - E_COMPLETION_LAST_SIGNAL -}; - -static guint e_completion_signals[E_COMPLETION_LAST_SIGNAL] = { 0 }; - -struct _ECompletionPrivate { - gboolean searching; - gboolean done_search; - gboolean refining; - gchar *search_text; - GPtrArray *matches; - gint match_count; - gint pos; - gint limit; - double min_score, max_score; - gint refinement_count; - GList *search_stack; -}; - -typedef struct { - gchar *text; - gint pos; -} ECompletionSearch; - -static void e_completion_class_init (ECompletionClass *klass); -static void e_completion_init (ECompletion *complete); -static void e_completion_dispose (GObject *object); - -static void e_completion_add_match (ECompletion *complete, ECompletionMatch *); -static void e_completion_clear_search_stack (ECompletion *complete); -static void e_completion_clear_matches (ECompletion *complete); -static gboolean e_completion_sort (ECompletion *complete); -static void e_completion_restart (ECompletion *complete); - -#define PARENT_TYPE GTK_TYPE_OBJECT -static GtkObjectClass *parent_class; - - - -E_MAKE_TYPE (e_completion, - "ECompletion", - ECompletion, - e_completion_class_init, - e_completion_init, - PARENT_TYPE) - -static void -e_completion_class_init (ECompletionClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - - parent_class = g_type_class_ref (PARENT_TYPE); - - e_completion_signals[E_COMPLETION_REQUEST_COMPLETION] = - g_signal_new ("request_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, request_completion), - NULL, NULL, - e_marshal_NONE__POINTER_INT_INT, - G_TYPE_NONE, 3, - G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT); - - e_completion_signals[E_COMPLETION_BEGIN_COMPLETION] = - g_signal_new ("begin_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, begin_completion), - NULL, NULL, - e_marshal_NONE__POINTER_INT_INT, - G_TYPE_NONE, 3, - G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT); - - e_completion_signals[E_COMPLETION_COMPLETION] = - g_signal_new ("completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, completion), - NULL, NULL, - e_marshal_NONE__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - - e_completion_signals[E_COMPLETION_RESTART_COMPLETION] = - g_signal_new ("restart_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, restart_completion), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_signals[E_COMPLETION_CANCEL_COMPLETION] = - g_signal_new ("cancel_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, cancel_completion), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_signals[E_COMPLETION_END_COMPLETION] = - g_signal_new ("end_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, end_completion), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_signals[E_COMPLETION_CLEAR_COMPLETION] = - g_signal_new ("clear_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, clear_completion), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_completion_signals[E_COMPLETION_LOST_COMPLETION] = - g_signal_new ("lost_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ECompletionClass, lost_completion), - NULL, NULL, - e_marshal_NONE__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - object_class->dispose = e_completion_dispose; -} - -static void -e_completion_init (ECompletion *complete) -{ - complete->priv = g_new0 (struct _ECompletionPrivate, 1); - complete->priv->matches = g_ptr_array_new (); -} - -static void -e_completion_dispose (GObject *object) -{ - ECompletion *complete = E_COMPLETION (object); - - if (complete->priv) { - g_free (complete->priv->search_text); - complete->priv->search_text = NULL; - - e_completion_clear_matches (complete); - e_completion_clear_search_stack (complete); - - g_ptr_array_free (complete->priv->matches, TRUE); - complete->priv->matches = NULL; - - g_free (complete->priv); - complete->priv = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->dispose) - (G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -e_completion_add_match (ECompletion *complete, ECompletionMatch *match) -{ - g_return_if_fail (complete && E_IS_COMPLETION (complete)); - g_return_if_fail (match != NULL); - - g_ptr_array_add (complete->priv->matches, match); - - if (complete->priv->matches->len == 1) { - - complete->priv->min_score = complete->priv->max_score = match->score; - - } else { - - complete->priv->min_score = MIN (complete->priv->min_score, match->score); - complete->priv->max_score = MAX (complete->priv->max_score, match->score); - - } -} - -static void -e_completion_clear_matches (ECompletion *complete) -{ - ECompletionMatch *match; - GPtrArray *m; - int i; - - g_return_if_fail (E_IS_COMPLETION (complete)); - - m = complete->priv->matches; - for (i = 0; i < m->len; i++) { - match = g_ptr_array_index (m, i); - e_completion_match_unref (match); - } - g_ptr_array_set_size (m, 0); - - complete->priv->min_score = 0; - complete->priv->max_score = 0; -} - -void -e_completion_clear (ECompletion *complete) -{ - g_return_if_fail (E_IS_COMPLETION (complete)); - - /* FIXME: do we really want _clear and _clear_matches() ? */ - - /* I think yes, because it is convenient to be able to clear our match cache - without emitting a "clear_completion" signal. -JT */ - - e_completion_clear_matches (complete); - e_completion_clear_search_stack (complete); - complete->priv->refinement_count = 0; - complete->priv->match_count = 0; - g_signal_emit (complete, e_completion_signals[E_COMPLETION_CLEAR_COMPLETION], 0); -} - -static void -e_completion_push_search (ECompletion *complete, const gchar *text, gint pos) -{ - ECompletionSearch *search; - - g_return_if_fail (E_IS_COMPLETION (complete)); - - search = g_new (ECompletionSearch, 1); - search->text = complete->priv->search_text; - search->pos = complete->priv->pos; - complete->priv->search_stack = g_list_prepend (complete->priv->search_stack, search); - - complete->priv->search_text = g_strdup (text); - complete->priv->pos = pos; -} - -static void -e_completion_pop_search (ECompletion *complete) -{ - ECompletionSearch *search; - GList *old_link = complete->priv->search_stack; - - g_return_if_fail (E_IS_COMPLETION (complete)); - g_return_if_fail (complete->priv->search_stack != NULL); - - g_free (complete->priv->search_text); - - search = complete->priv->search_stack->data; - complete->priv->search_text = search->text; - complete->priv->pos = search->pos; - - g_free (search); - complete->priv->search_stack = g_list_remove_link (complete->priv->search_stack, - complete->priv->search_stack); - g_list_free_1 (old_link); -} - -static void -e_completion_clear_search_stack (ECompletion *complete) -{ - GList *iter; - - g_return_if_fail (E_IS_COMPLETION (complete)); - - for (iter = complete->priv->search_stack; iter != NULL; iter = g_list_next (iter)) { - ECompletionSearch *search = iter->data; - g_free (search->text); - g_free (search); - } - g_list_free (complete->priv->search_stack); - complete->priv->search_stack = NULL; -} - -static void -e_completion_refine_search (ECompletion *comp, const gchar *text, gint pos, ECompletionRefineFn refine_fn) -{ - GPtrArray *m; - gint i; - - comp->priv->refining = TRUE; - - e_completion_push_search (comp, text, pos); - - g_signal_emit (comp, e_completion_signals[E_COMPLETION_BEGIN_COMPLETION], 0, text, pos, comp->priv->limit); - - comp->priv->match_count = 0; - - comp->priv->searching = TRUE; - - m = comp->priv->matches; - for (i = 0; i < m->len; ++i) { - ECompletionMatch *match = g_ptr_array_index (m, i); - if (comp->priv->refinement_count == match->hit_count - && refine_fn (comp, match, text, pos)) { - ++match->hit_count; - g_signal_emit (comp, e_completion_signals[E_COMPLETION_COMPLETION], 0, match); - ++comp->priv->match_count; - } - } - - ++comp->priv->refinement_count; - - g_signal_emit (comp, e_completion_signals[E_COMPLETION_END_COMPLETION], 0); - - comp->priv->searching = FALSE; - comp->priv->refining = FALSE; -} - -static void -e_completion_unrefine_search (ECompletion *comp) -{ - GPtrArray *m; - gint i; - - comp->priv->refining = TRUE; - - e_completion_pop_search (comp); - - g_signal_emit (comp, e_completion_signals[E_COMPLETION_BEGIN_COMPLETION], 0, - comp->priv->search_text, comp->priv->pos, comp->priv->limit); - - comp->priv->match_count = 0; - --comp->priv->refinement_count; - - comp->priv->searching = TRUE; - - m = comp->priv->matches; - for (i = 0; i < m->len; ++i) { - ECompletionMatch *match = g_ptr_array_index (m, i); - if (comp->priv->refinement_count <= match->hit_count) { - match->hit_count = comp->priv->refinement_count; - g_signal_emit (comp, e_completion_signals[E_COMPLETION_COMPLETION], 0, match); - ++comp->priv->match_count; - } - } - - g_signal_emit (comp, e_completion_signals[E_COMPLETION_END_COMPLETION], 0); - - comp->priv->searching = FALSE; - comp->priv->refining = FALSE; -} - -void -e_completion_begin_search (ECompletion *complete, const gchar *text, gint pos, gint limit) -{ - ECompletionClass *klass; - ECompletionRefineFn refine_fn; - - g_return_if_fail (complete != NULL); - g_return_if_fail (E_IS_COMPLETION (complete)); - g_return_if_fail (text != NULL); - - klass = E_COMPLETION_CLASS (GTK_OBJECT_GET_CLASS (complete)); - - if (!complete->priv->searching && complete->priv->done_search) { - - /* If the search we are requesting is the same as what we had before our last refinement, - treat the request as an unrefine. */ - if (complete->priv->search_stack != NULL) { - ECompletionSearch *search = complete->priv->search_stack->data; - if ((klass->ignore_pos_on_auto_unrefine || search->pos == pos) - && !strcmp (search->text, text)) { - e_completion_unrefine_search (complete); - return; - } - } - - if (klass->auto_refine - && (refine_fn = klass->auto_refine (complete, - complete->priv->search_text, complete->priv->pos, - text, pos))) { - e_completion_refine_search (complete, text, pos, refine_fn); - return; - } - - } - - /* Stop any prior search. */ - if (complete->priv->searching) - e_completion_cancel_search (complete); - - e_completion_clear_search_stack (complete); - - g_free (complete->priv->search_text); - complete->priv->search_text = g_strdup (text); - - complete->priv->pos = pos; - complete->priv->searching = TRUE; - complete->priv->done_search = FALSE; - - e_completion_clear_matches (complete); - - complete->priv->limit = limit > 0 ? limit : G_MAXINT; - complete->priv->refinement_count = 0; - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_BEGIN_COMPLETION], 0, text, pos, limit); - g_signal_emit (complete, e_completion_signals[E_COMPLETION_REQUEST_COMPLETION], 0, text, pos, limit); -} - -void -e_completion_cancel_search (ECompletion *complete) -{ - g_return_if_fail (complete != NULL); - g_return_if_fail (E_IS_COMPLETION (complete)); - - /* If there is no search to cancel, just silently return. */ - if (!complete->priv->searching) - return; - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_CANCEL_COMPLETION], 0); - - complete->priv->searching = FALSE; -} - -gboolean -e_completion_searching (ECompletion *complete) -{ - g_return_val_if_fail (complete != NULL, FALSE); - g_return_val_if_fail (E_IS_COMPLETION (complete), FALSE); - - return complete->priv->searching; -} - -gboolean -e_completion_refining (ECompletion *complete) -{ - g_return_val_if_fail (complete != NULL, FALSE); - g_return_val_if_fail (E_IS_COMPLETION (complete), FALSE); - - return complete->priv->refining; -} - -const gchar * -e_completion_search_text (ECompletion *complete) -{ - g_return_val_if_fail (complete != NULL, NULL); - g_return_val_if_fail (E_IS_COMPLETION (complete), NULL); - - return complete->priv->search_text; -} - -gint -e_completion_search_text_pos (ECompletion *complete) -{ - g_return_val_if_fail (complete != NULL, -1); - g_return_val_if_fail (E_IS_COMPLETION (complete), -1); - - return complete->priv->pos; -} - -gint -e_completion_match_count (ECompletion *complete) -{ - g_return_val_if_fail (complete != NULL, 0); - g_return_val_if_fail (E_IS_COMPLETION (complete), 0); - - return complete->priv->refinement_count > 0 ? complete->priv->match_count : complete->priv->matches->len; -} - -void -e_completion_foreach_match (ECompletion *complete, ECompletionMatchFn fn, gpointer closure) -{ - GPtrArray *m; - int i; - - g_return_if_fail (complete != NULL); - g_return_if_fail (E_IS_COMPLETION (complete)); - - if (fn == NULL) - return; - - m = complete->priv->matches; - for (i = 0; i < m->len; i++) { - ECompletionMatch *match = g_ptr_array_index (m, i); - if (match->hit_count == complete->priv->refinement_count) { - fn (match, closure); - } - } -} - -ECompletion * -e_completion_new (void) -{ - return E_COMPLETION (g_object_new (E_COMPLETION_TYPE, NULL)); -} - -static gboolean -e_completion_sort (ECompletion *complete) -{ - GPtrArray *m; - int i; - GList *sort_list = NULL, *j; - gboolean diff; - - m = complete->priv->matches; - - for (i = 0; i < m->len; i++) - sort_list = g_list_append (sort_list, - g_ptr_array_index (m, i)); - - sort_list = g_list_sort (sort_list, (GCompareFunc) e_completion_match_compare_alpha); - - diff = FALSE; - - for (i=0, j=sort_list; i < m->len; i++, j = g_list_next (j)) { - if (g_ptr_array_index (m, i) == j->data) - continue; - - diff = TRUE; - g_ptr_array_index (m, i) = j->data; - } - - g_list_free (sort_list); - - return diff; -} - -/* Emit a restart signal and re-declare our matches, up to the limit. */ -static void -e_completion_restart (ECompletion *complete) -{ - GPtrArray *m; - gint i, count; - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_RESTART_COMPLETION], 0); - - m = complete->priv->matches; - for (i = count = 0; - i < m->len && count < complete->priv->limit; - i++, count++) { - g_signal_emit (complete, - e_completion_signals[E_COMPLETION_COMPLETION], 0, - g_ptr_array_index (m, i)); - } -} - -void -e_completion_found_match (ECompletion *complete, ECompletionMatch *match) -{ - g_return_if_fail (complete); - g_return_if_fail (E_IS_COMPLETION (complete)); - g_return_if_fail (match != NULL); - - if (! complete->priv->searching) { - g_warning ("e_completion_found_match(...,\"%s\",...) called outside of a search", match->match_text); - return; - } - - /* For now, do nothing when we hit the limit --- just don't - * announce the incoming matches. */ - if (complete->priv->matches->len >= complete->priv->limit) { - e_completion_match_unref (match); - return; - } - - e_completion_add_match (complete, match); - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_COMPLETION], 0, match); -} - -/* to optimize this, make the match a hash table */ -void -e_completion_lost_match (ECompletion *complete, ECompletionMatch *match) -{ - gboolean removed; - - g_return_if_fail (E_IS_COMPLETION (complete)); - g_return_if_fail (match != NULL); - - /* FIXME: remove fast */ - removed = g_ptr_array_remove (complete->priv->matches, - match); - - /* maybe just return here? */ - g_return_if_fail (removed); - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_LOST_COMPLETION], 0, match); - - e_completion_match_unref (match); -} - -void -e_completion_end_search (ECompletion *complete) -{ - g_return_if_fail (complete != NULL); - g_return_if_fail (E_IS_COMPLETION (complete)); - g_return_if_fail (complete->priv->searching); - - /* our table model should be sorted by a non-visible column of - * doubles (the score) rather than whatever we are doing - */ - /* If sorting by score accomplishes anything, issue a restart right before we end. */ - if (e_completion_sort (complete)) - e_completion_restart (complete); - - g_signal_emit (complete, e_completion_signals[E_COMPLETION_END_COMPLETION], 0); - - complete->priv->searching = FALSE; - complete->priv->done_search = TRUE; -} - diff --git a/widgets/text/e-completion.h b/widgets/text/e-completion.h deleted file mode 100644 index f8d38e45a7..0000000000 --- a/widgets/text/e-completion.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-completion.h - A base class for text completion. - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Miguel de Icaza <miguel@ximian.com> - * Adapted by Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_COMPLETION_H -#define E_COMPLETION_H - -#include <gtk/gtkobject.h> -#include "e-completion-match.h" - -G_BEGIN_DECLS - -#define E_COMPLETION_TYPE (e_completion_get_type ()) -#define E_COMPLETION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_COMPLETION_TYPE, ECompletion)) -#define E_COMPLETION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_COMPLETION_TYPE, ECompletionClass)) -#define E_IS_COMPLETION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_COMPLETION_TYPE)) -#define E_IS_COMPLETION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_COMPLETION_TYPE)) - -typedef struct _ECompletion ECompletion; -typedef struct _ECompletionClass ECompletionClass; -struct _ECompletionPrivate; - -typedef gboolean (*ECompletionRefineFn) (ECompletion *, ECompletionMatch *, const gchar *search_text, gint pos); - -struct _ECompletion { - GtkObject parent; - - struct _ECompletionPrivate *priv; -}; - -struct _ECompletionClass { - GtkObjectClass parent_class; - - /* virtual functions */ - ECompletionRefineFn (*auto_refine) (ECompletion *comp, - const gchar *old_text, gint old_pos, - const gchar *new_text, gint new_pos); - gboolean ignore_pos_on_auto_unrefine; - - /* Signals */ - void (*request_completion) (ECompletion *comp, const gchar *search_text, gint pos, gint limit); - - void (*begin_completion) (ECompletion *comp, const gchar *search_text, gint pos, gint limit); - void (*restart_completion) (ECompletion *comp); - - void (*completion) (ECompletion *comp, ECompletionMatch *match); - void (*lost_completion) (ECompletion *comp, ECompletionMatch *match); - - void (*cancel_completion) (ECompletion *comp); - void (*end_completion) (ECompletion *comp); - void (*clear_completion) (ECompletion *comp); -}; - -GtkType e_completion_get_type (void); - -void e_completion_begin_search (ECompletion *comp, const gchar *text, gint pos, gint limit); -void e_completion_cancel_search (ECompletion *comp); - -gboolean e_completion_searching (ECompletion *comp); -gboolean e_completion_refining (ECompletion *comp); -const gchar *e_completion_search_text (ECompletion *comp); -gint e_completion_search_text_pos (ECompletion *comp); -gint e_completion_match_count (ECompletion *comp); -void e_completion_foreach_match (ECompletion *comp, ECompletionMatchFn fn, gpointer user_data); - -ECompletion *e_completion_new (void); - - - -/* These functions should only be called by derived classes or search callbacks, - or very bad things might happen. */ - -void e_completion_found_match (ECompletion *comp, ECompletionMatch *); -void e_completion_lost_match (ECompletion *comp, ECompletionMatch *); -void e_completion_clear (ECompletion *comp); -void e_completion_end_search (ECompletion *comp); - -G_END_DECLS - - -#endif /* E_COMPLETION_H */ - diff --git a/widgets/text/e-entry-test.c b/widgets/text/e-entry-test.c deleted file mode 100644 index d30ba20a9f..0000000000 --- a/widgets/text/e-entry-test.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-entry-test.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> - -#include <gnome.h> -#include "e-entry.h" -#include <gal/util/e-i18n.h> - -static void destroy_callback(gpointer data, GObject *where_object_was) -{ - exit(0); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Minicard Test" ), VERSION, - _( "Copyright (C) 2000, Helix Code, Inc." ), - authors, - _( "This should test the minicard canvas item" ), - NULL); - gtk_widget_show (about); -} -#endif - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *entry; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - gnome_init( "EEntry Test", VERSION, argc, argv); - app = gnome_app_new("EEntry Test", NULL); - - entry = e_entry_new(); - g_object_set(entry, - "editable", TRUE, - "use_ellipsis", TRUE, - NULL); - gnome_app_set_contents( GNOME_APP( app ), entry ); - - /* Connect the signals */ - g_object_weak_ref (G_OBJECT (app), - destroy_callback, app); - - gtk_widget_show_all( app ); - - gtk_main(); - - /* Not reached. */ - return 0; -} diff --git a/widgets/text/e-entry.c b/widgets/text/e-entry.c deleted file mode 100644 index 746fba6121..0000000000 --- a/widgets/text/e-entry.c +++ /dev/null @@ -1,1400 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-entry.c - An EText-based entry widget - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> -#include <math.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtksignal.h> -#include <gtk/gtktypebuiltins.h> -#include <libxml/parser.h> -#include <libgnomecanvas/gnome-canvas.h> -#include "gal/util/e-util.h" -#include "gal/util/e-i18n.h" -#include "gal/widgets/e-canvas.h" -#include "gal/widgets/e-canvas-utils.h" -#include "e-completion-view.h" -#include "e-text.h" -#include "e-entry.h" - -#define MOVE_RIGHT_AND_UP 0 - -#define EVIL_POINTER_WARPING_HACK - -#ifdef EVIL_POINTER_WARPING_HACK -#include <gdk/gdkx.h> -#endif - -#define MIN_ENTRY_WIDTH 150 - -#define d(x) - -#define PARENT_TYPE gtk_table_get_type () - -static GtkObjectClass *parent_class; - -enum { - E_ENTRY_CHANGED, - E_ENTRY_ACTIVATE, - E_ENTRY_POPUP, - E_ENTRY_COMPLETION_POPUP, - E_ENTRY_LAST_SIGNAL -}; - -static guint e_entry_signals[E_ENTRY_LAST_SIGNAL] = { 0 }; - -/* Object argument IDs */ -enum { - PROP_0, - PROP_MODEL, - PROP_EVENT_PROCESSOR, - PROP_TEXT, - PROP_FONT, - PROP_FONTSET, - PROP_FONT_GDK, - PROP_ANCHOR, - PROP_JUSTIFICATION, - PROP_X_OFFSET, - PROP_Y_OFFSET, - PROP_FILL_COLOR, - PROP_FILL_COLOR_GDK, - PROP_FILL_COLOR_RGBA, - PROP_FILL_STIPPLE, - PROP_EDITABLE, - PROP_USE_ELLIPSIS, - PROP_ELLIPSIS, - PROP_LINE_WRAP, - PROP_BREAK_CHARACTERS, - PROP_MAX_LINES, - PROP_ALLOW_NEWLINES, - PROP_DRAW_BORDERS, - PROP_DRAW_BACKGROUND, - PROP_DRAW_BUTTON, - PROP_EMULATE_LABEL_RESIZE, - PROP_CURSOR_POS -}; - -typedef struct _EEntryPrivate EEntryPrivate; -struct _EEntryPrivate { - GtkJustification justification; - - guint changed_proxy_tag; - guint activate_proxy_tag; - guint popup_proxy_tag; - /* Data related to completions */ - ECompletion *completion; - EEntryCompletionHandler handler; - GtkWidget *completion_view; - guint nonempty_signal_id; - guint added_signal_id; - guint full_signal_id; - guint browse_signal_id; - guint unbrowse_signal_id; - guint activate_signal_id; - GtkWidget *completion_view_popup; - gboolean popup_is_visible; - gchar *pre_browse_text; - gint completion_delay; - guint completion_delay_tag; - gboolean ptr_grab; - gboolean changed_since_keypress; - guint changed_since_keypress_tag; - gint last_completion_pos; - - guint draw_borders : 1; - guint emulate_label_resize : 1; - guint have_set_transient : 1; - gint last_width; -}; - -static gboolean e_entry_is_empty (EEntry *entry); -static void e_entry_show_popup (EEntry *entry, gboolean x); -static void e_entry_start_completion (EEntry *entry); -static void e_entry_start_delayed_completion (EEntry *entry, gint delay); -static void e_entry_cancel_delayed_completion (EEntry *entry); - -static void -canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, - EEntry *entry) -{ - gnome_canvas_set_scroll_region (entry->canvas, - 0, 0, alloc->width, alloc->height); - g_object_set (entry->item, - "clip_width", (double) (alloc->width), - "clip_height", (double) (alloc->height), - NULL); - - switch (entry->priv->justification) { - case GTK_JUSTIFY_RIGHT: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), - alloc->width, 0); - break; - case GTK_JUSTIFY_CENTER: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), - alloc->width / 2, 0); - break; - default: - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), - 0, 0); - break; - } -} - -static void -canvas_size_request (GtkWidget *widget, GtkRequisition *requisition, - EEntry *entry) -{ - int xthick, ythick; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GNOME_IS_CANVAS (widget)); - g_return_if_fail (requisition != NULL); - - if (entry->priv->draw_borders) { - xthick = 2 * widget->style->xthickness; - ythick = 2 * widget->style->ythickness; - } else { - xthick = ythick = 0; - } - - if (entry->priv->emulate_label_resize) { - gdouble width; - g_object_get (entry->item, - "text_width", &width, - NULL); - requisition->width = 2 + xthick + width; - } else { - requisition->width = 2 + MIN_ENTRY_WIDTH + xthick; - } - if (entry->priv->last_width != requisition->width) - gtk_widget_queue_resize (widget); - entry->priv->last_width = requisition->width; - - d(g_print("%s: width = %d\n", __FUNCTION__, requisition->width)); - - requisition->height = (2 + gtk_style_get_font (widget->style)->ascent + - gtk_style_get_font (widget->style)->descent + - ythick); -} - -static gint -canvas_focus_in_event (GtkWidget *widget, GdkEventFocus *focus, EEntry *entry) -{ - if (entry->canvas->focused_item != GNOME_CANVAS_ITEM(entry->item)) - gnome_canvas_item_grab_focus(GNOME_CANVAS_ITEM(entry->item)); - - return FALSE; -} - -static void -e_entry_text_keypress (EText *text, guint keyval, guint state, EEntry *entry) -{ - if (entry->priv->changed_since_keypress_tag) { - gtk_timeout_remove (entry->priv->changed_since_keypress_tag); - entry->priv->changed_since_keypress_tag = 0; - } - - if (entry->priv->changed_since_keypress - || (entry->priv->popup_is_visible && e_entry_get_position (entry) != entry->priv->last_completion_pos)) { - if (e_entry_is_empty (entry)) { - e_entry_cancel_delayed_completion (entry); - e_entry_show_popup (entry, FALSE); - } else if (entry->priv->completion_delay >= 0) { - int delay; - delay = entry->priv->popup_is_visible - ? 1 - : entry->priv->completion_delay; - e_entry_start_delayed_completion (entry, delay); - } - } - entry->priv->changed_since_keypress = FALSE; -} - -static gint -changed_since_keypress_timeout_fn (gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - entry->priv->changed_since_keypress = FALSE; - entry->priv->changed_since_keypress_tag = 0; - return FALSE; -} - -static void -e_entry_proxy_changed (EText *text, EEntry *entry) -{ - if (entry->priv->changed_since_keypress_tag) - gtk_timeout_remove (entry->priv->changed_since_keypress_tag); - entry->priv->changed_since_keypress = TRUE; - entry->priv->changed_since_keypress_tag = gtk_timeout_add (20, changed_since_keypress_timeout_fn, entry); - - g_signal_emit (entry, e_entry_signals [E_ENTRY_CHANGED], 0); -} - -static void -e_entry_proxy_activate (EText *text, EEntry *entry) -{ - g_signal_emit (entry, e_entry_signals [E_ENTRY_ACTIVATE], 0); -} - -static void -e_entry_proxy_popup (EText *text, GdkEventButton *ev, gint pos, EEntry *entry) -{ - g_signal_emit (entry, e_entry_signals [E_ENTRY_POPUP], 0, ev, pos); -} - -static void -e_entry_init (GtkObject *object) -{ - EEntry *entry = E_ENTRY (object); - GtkTable *gtk_table = GTK_TABLE (object); - - entry->priv = g_new0 (EEntryPrivate, 1); - - entry->priv->emulate_label_resize = FALSE; - - entry->priv->emulate_label_resize = FALSE; - - entry->canvas = GNOME_CANVAS (e_canvas_new ()); - - g_signal_connect (entry->canvas, - "size_allocate", - G_CALLBACK (canvas_size_allocate), - entry); - - g_signal_connect (entry->canvas, - "size_request", - G_CALLBACK (canvas_size_request), - entry); - - g_signal_connect (entry->canvas, - "focus_in_event", - G_CALLBACK(canvas_focus_in_event), - entry); - - entry->priv->draw_borders = TRUE; - entry->priv->last_width = -1; - - entry->item = E_TEXT(gnome_canvas_item_new( - gnome_canvas_root (entry->canvas), - e_text_get_type(), - "clip", TRUE, - "fill_clip_rectangle", TRUE, - "anchor", GTK_ANCHOR_NW, - "draw_borders", TRUE, - "draw_background", TRUE, - "draw_button", FALSE, - "max_lines", 1, - "editable", TRUE, - "allow_newlines", FALSE, - NULL)); - - g_signal_connect (entry->item, - "keypress", - G_CALLBACK (e_entry_text_keypress), - entry); - - entry->priv->justification = GTK_JUSTIFY_LEFT; - gtk_table_attach (gtk_table, GTK_WIDGET (entry->canvas), - 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL | GTK_SHRINK, - GTK_EXPAND | GTK_FILL | GTK_SHRINK, - 0, 0); - gtk_widget_show (GTK_WIDGET (entry->canvas)); - - /* - * Proxy functions: we proxy the changed and activate signals - * from the item to ourselves - */ - entry->priv->changed_proxy_tag = g_signal_connect (entry->item, - "changed", - G_CALLBACK (e_entry_proxy_changed), - entry); - entry->priv->activate_proxy_tag = g_signal_connect (entry->item, - "activate", - G_CALLBACK (e_entry_proxy_activate), - entry); - entry->priv->popup_proxy_tag = g_signal_connect (entry->item, - "popup", - G_CALLBACK (e_entry_proxy_popup), - entry); - - entry->priv->completion_delay = 1; -} - -/** - * e_entry_construct - * - * Constructs the given EEntry. - * - **/ -void -e_entry_construct (EEntry *entry) -{ - /* Do nothing */ -} - - -/** - * e_entry_new - * - * Creates a new EEntry. - * - * Returns: The new EEntry - **/ -GtkWidget * -e_entry_new (void) -{ - EEntry *entry; - entry = g_object_new (E_ENTRY_TYPE, NULL); - e_entry_construct (entry); - - return GTK_WIDGET (entry); -} - -const gchar * -e_entry_get_text (EEntry *entry) -{ - g_return_val_if_fail (entry != NULL && E_IS_ENTRY (entry), NULL); - - return e_text_model_get_text (entry->item->model); -} - -void -e_entry_set_text (EEntry *entry, const gchar *txt) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - - e_text_model_set_text (entry->item->model, txt); -} - -static void -e_entry_set_text_quiet (EEntry *entry, const gchar *txt) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - - g_signal_handler_block (entry->item, entry->priv->changed_proxy_tag); - e_entry_set_text (entry, txt); - g_signal_handler_unblock (entry->item, entry->priv->changed_proxy_tag); -} - - -void -e_entry_set_editable (EEntry *entry, gboolean am_i_editable) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - - g_object_set (entry->item, "editable", am_i_editable, NULL); -} - -gint -e_entry_get_position (EEntry *entry) -{ - g_return_val_if_fail (entry != NULL && E_IS_ENTRY (entry), -1); - - return entry->item->selection_start; -} - -void -e_entry_set_position (EEntry *entry, gint pos) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - if (pos < 0) - pos = 0; - else if (pos > e_text_model_get_text_length (entry->item->model)) - pos = e_text_model_get_text_length (entry->item->model); - - entry->item->selection_start = entry->item->selection_end = pos; -} - -void -e_entry_select_region (EEntry *entry, gint pos1, gint pos2) -{ - gint len; - - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - - len = e_text_model_get_text_length (entry->item->model); - pos1 = CLAMP (pos1, 0, len); - pos2 = CLAMP (pos2, 0, len); - - entry->item->selection_start = MIN (pos1, pos2); - entry->item->selection_end = MAX (pos1, pos2); -} - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -/*** Completion-related code ***/ - -static gboolean -e_entry_is_empty (EEntry *entry) -{ - const gchar *txt = e_entry_get_text (entry); - - if (txt == NULL) - return TRUE; - - while (*txt) { - if (!isspace ((gint) *txt)) - return FALSE; - ++txt; - } - - return TRUE; -} - -static void -e_entry_show_popup (EEntry *entry, gboolean visible) -{ - GtkWidget *pop = entry->priv->completion_view_popup; - - if (pop == NULL) - return; - - /* The async query can give us a result after the focus was lost by the - widget. In that case, we don't want to show the pop-up. */ - if (! GTK_WIDGET_HAS_FOCUS (entry->canvas)) - return; - - if (visible) { - GtkAllocation *dim = &(GTK_WIDGET (entry)->allocation); - gint x, y, xo, yo, fudge; - const GdkEventMask grab_mask = (GdkEventMask)GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK; - - /* Figure out where to put our popup. */ - gdk_window_get_origin (GTK_WIDGET (entry)->window, &xo, &yo); - x = xo + dim->x; - y = yo + dim->height + dim->y; - -#if MOVE_RIGHT_AND_UP - /* Put our popup slightly to the right and up, to try to give a visual cue that this popup - is tied to this entry. Otherwise one-row popups can sort of "blend" with an entry - directly below. */ - fudge = MAX (dim->height/10, 3); /* just in case we are using a really big font, etc. */ - x += 2*fudge; - y -= fudge; -#else - fudge = 1; - y -= fudge; -#endif - gtk_widget_set_uposition (pop, x, y); - e_completion_view_set_width (E_COMPLETION_VIEW (entry->priv->completion_view), dim->width); - -#ifdef EVIL_POINTER_WARPING_HACK - /* - I should have learned by now to listen to Havoc... - http://developer.gnome.org/doc/GGAD/faqs.html - */ - - if (! entry->priv->popup_is_visible) { - GdkWindow *gwin = GTK_WIDGET (entry)->window; - gint xx, yy; - gdk_window_get_pointer (gwin, &xx, &yy, NULL); - xx += xo; - yy += yo; - - /* If we are inside the "zone of death" where the popup will appear, warp the pointer to safety. - This is a horrible thing to do. */ - if (y <= yy && yy < yy + dim->height && x <= xx && xx < xx + dim->width) { - XWarpPointer (GDK_WINDOW_XDISPLAY (gwin), None, GDK_WINDOW_XWINDOW (gwin), - 0, 0, 0, 0, - xx - xo, (y-1) - yo); - } - } -#endif - - gtk_widget_show (pop); - - - if (getenv ("GAL_E_ENTRY_NO_GRABS_HACK") == NULL && !entry->priv->ptr_grab) { - entry->priv->ptr_grab = (0 == gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE, - grab_mask, NULL, NULL, GDK_CURRENT_TIME)); - if (entry->priv->ptr_grab) { - gtk_grab_add (GTK_WIDGET (entry->priv->completion_view)); - } - } - - - } else { - - gtk_widget_hide (pop); - - if (entry->priv->ptr_grab) { - gdk_pointer_ungrab (GDK_CURRENT_TIME); - gtk_grab_remove (GTK_WIDGET (entry->priv->completion_view)); - } - - entry->priv->ptr_grab = FALSE; - - entry->priv->last_completion_pos = -1; - } - - e_completion_view_set_editable (E_COMPLETION_VIEW (entry->priv->completion_view), visible); - - if (entry->priv->popup_is_visible != visible) { - entry->priv->popup_is_visible = visible; - g_signal_emit (entry, e_entry_signals[E_ENTRY_COMPLETION_POPUP], 0, (gint) visible); - } -} - -static void -e_entry_refresh_popup (EEntry *entry) -{ - if (entry->priv->popup_is_visible) - e_entry_show_popup (entry, TRUE); -} - -static void -e_entry_start_completion (EEntry *entry) -{ - if (entry->priv->completion == NULL) - return; - - e_entry_cancel_delayed_completion (entry); - - if (e_entry_is_empty (entry)) - return; - - e_completion_begin_search (entry->priv->completion, - e_entry_get_text (entry), - entry->priv->last_completion_pos = e_entry_get_position (entry), - 0); /* No limit. Probably a bad idea. */ -} - -static gboolean -start_delayed_cb (gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - entry->priv->completion_delay_tag = 0; - e_entry_start_completion (entry); - return FALSE; -} - -static void -e_entry_start_delayed_completion (EEntry *entry, gint delay) -{ - if (delay < 0) - return; - - e_entry_cancel_delayed_completion (entry); - entry->priv->completion_delay_tag = gtk_timeout_add (MAX (delay, 1), start_delayed_cb, entry); -} - -static void -e_entry_cancel_delayed_completion (EEntry *entry) -{ - if (entry->priv->completion == NULL) - return; - - if (entry->priv->completion_delay_tag) { - gtk_timeout_remove (entry->priv->completion_delay_tag); - entry->priv->completion_delay_tag = 0; - } -} - -static void -nonempty_cb (ECompletionView *view, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - - e_entry_show_popup (entry, TRUE); -} - -static void -added_cb (ECompletionView *view, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - e_entry_refresh_popup (entry); -} - -static void -full_cb (ECompletionView *view, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - gboolean show; - - show = GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry->canvas)) && view->choices->len > 0; - e_entry_show_popup (entry, show); -} - -static void -browse_cb (ECompletionView *view, ECompletionMatch *match, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - - if (match == NULL) { - /* Requesting a completion. */ - e_entry_start_completion (entry); - return; - } - - if (entry->priv->pre_browse_text == NULL) - entry->priv->pre_browse_text = g_strdup (e_entry_get_text (entry)); - - /* If there is no other handler in place, echo the selected completion in - the entry. */ - if (entry->priv->handler == NULL) - e_entry_set_text_quiet (entry, e_completion_match_get_match_text (match)); -} - -static void -unbrowse_cb (ECompletionView *view, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - - if (entry->priv->pre_browse_text) { - - if (entry->priv->handler == NULL) - e_entry_set_text_quiet (entry, entry->priv->pre_browse_text); - - g_free (entry->priv->pre_browse_text); - entry->priv->pre_browse_text = NULL; - } - - e_entry_show_popup (entry, FALSE); -} - -static void -activate_cb (ECompletionView *view, ECompletionMatch *match, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - - e_entry_cancel_delayed_completion (entry); - - g_free (entry->priv->pre_browse_text); - entry->priv->pre_browse_text = NULL; - e_entry_show_popup (entry, FALSE); - - if (entry->priv->handler) - entry->priv->handler (entry, match); - else - e_entry_set_text (entry, match->match_text); - - e_entry_cancel_delayed_completion (entry); -} - -void -e_entry_enable_completion (EEntry *entry, ECompletion *completion) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - g_return_if_fail (completion != NULL && E_IS_COMPLETION (completion)); - - e_entry_enable_completion_full (entry, completion, -1, NULL); -} - -static void -button_press_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - GtkWidget *child; - - /* Bail out if our click happened inside of our widget. */ - child = gtk_get_event_widget (ev); - if (child != w) { - while (child) { - if (child == w) - return; - child = child->parent; - } - } - - /* Treat this as an unbrowse */ - unbrowse_cb (E_COMPLETION_VIEW (w), entry); -} - -static void -cancel_completion_cb (ETextModel *model, gpointer user_data) -{ - EEntry *entry = E_ENTRY (user_data); - - /* If we get the signal from the underlying text model, unbrowse. - This usually means that the text model itself has done some - sort of completion, or has otherwise transformed its contents - in some way that would render any previous completion invalid. */ - unbrowse_cb (E_COMPLETION_VIEW (entry->priv->completion_view), entry); -} - -static gint -key_press_cb (GtkWidget *w, GdkEventKey *ev, gpointer user_data) -{ - gint rv = 0; - /* Forward signal */ - g_signal_emit_by_name (user_data, "key_press_event", ev, &rv); - return rv; -} - -static gint -key_release_cb (GtkWidget *w, GdkEventKey *ev, gpointer user_data) -{ - gint rv = 0; - /* Forward signal */ - g_signal_emit_by_name (user_data, "key_release_event", ev, &rv); - return rv; -} - -static void -e_entry_make_completion_window_transient (EEntry *entry) -{ - GtkWidget *w; - - if (entry->priv->have_set_transient || entry->priv->completion_view_popup == NULL) - return; - - w = GTK_WIDGET (entry)->parent; - while (w && ! GTK_IS_WINDOW (w)) - w = w->parent; - - if (w) { - gtk_window_set_transient_for (GTK_WINDOW (entry->priv->completion_view_popup), - GTK_WINDOW (w)); - entry->priv->have_set_transient = 1; - } -} - -void -e_entry_enable_completion_full (EEntry *entry, ECompletion *completion, gint delay, EEntryCompletionHandler handler) -{ - g_return_if_fail (entry != NULL && E_IS_ENTRY (entry)); - g_return_if_fail (completion != NULL && E_IS_COMPLETION (completion)); - - /* For now, completion can't be changed mid-stream. */ - g_return_if_fail (entry->priv->completion == NULL); - - entry->priv->completion = completion; - g_object_ref (completion); - gtk_object_sink (GTK_OBJECT (completion)); - - entry->priv->completion_delay = delay; - entry->priv->handler = handler; - - entry->priv->completion_view = e_completion_view_new (completion); - /* Make the up and down keys enable and disable completions. */ - e_completion_view_set_complete_key (E_COMPLETION_VIEW (entry->priv->completion_view), GDK_Down); - e_completion_view_set_uncomplete_key (E_COMPLETION_VIEW (entry->priv->completion_view), GDK_Up); - - g_signal_connect_after (entry->priv->completion_view, - "button_press_event", - G_CALLBACK (button_press_cb), - entry); - - entry->priv->nonempty_signal_id = g_signal_connect (entry->priv->completion_view, - "nonempty", - G_CALLBACK (nonempty_cb), - entry); - - entry->priv->added_signal_id = g_signal_connect (entry->priv->completion_view, - "added", - G_CALLBACK (added_cb), - entry); - - entry->priv->full_signal_id = g_signal_connect (entry->priv->completion_view, - "full", - G_CALLBACK (full_cb), - entry); - - entry->priv->browse_signal_id = g_signal_connect (entry->priv->completion_view, - "browse", - G_CALLBACK (browse_cb), - entry); - - entry->priv->unbrowse_signal_id = g_signal_connect (entry->priv->completion_view, - "unbrowse", - G_CALLBACK (unbrowse_cb), - entry); - - entry->priv->activate_signal_id = g_signal_connect (entry->priv->completion_view, - "activate", - G_CALLBACK (activate_cb), - entry); - - entry->priv->completion_view_popup = gtk_window_new (GTK_WINDOW_POPUP); - - e_entry_make_completion_window_transient (entry); - - g_signal_connect (entry->item->model, - "cancel_completion", - G_CALLBACK (cancel_completion_cb), - entry); - - g_signal_connect (entry->priv->completion_view_popup, - "key_press_event", - G_CALLBACK (key_press_cb), - entry->canvas); - g_signal_connect (entry->priv->completion_view_popup, - "key_release_event", - G_CALLBACK (key_release_cb), - entry->canvas); - - e_completion_view_connect_keys (E_COMPLETION_VIEW (entry->priv->completion_view), - GTK_WIDGET (entry->canvas)); - - g_object_ref (entry->priv->completion_view_popup); - gtk_object_sink (GTK_OBJECT (entry->priv->completion_view_popup)); - gtk_window_set_policy (GTK_WINDOW (entry->priv->completion_view_popup), TRUE, TRUE, TRUE); - gtk_container_add (GTK_CONTAINER (entry->priv->completion_view_popup), entry->priv->completion_view); - gtk_widget_show (entry->priv->completion_view); -} - -gboolean -e_entry_completion_popup_is_visible (EEntry *entry) -{ - g_return_val_if_fail (E_IS_ENTRY (entry), FALSE); - - return entry->priv->popup_is_visible; -} - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -static void -et_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EEntry *entry = E_ENTRY (object); - GtkObject *item = GTK_OBJECT (entry->item); - - switch (prop_id){ - case PROP_MODEL: - g_object_get_property (G_OBJECT (item), "model", value); - break; - case PROP_EVENT_PROCESSOR: - g_object_get_property (G_OBJECT (item), "event_processor", value); - break; - case PROP_TEXT: - g_object_get_property (G_OBJECT (item), "text", value); - break; - - case PROP_FONT_GDK: - g_object_get_property (G_OBJECT (item), "font_gdk", value); - break; - - case PROP_JUSTIFICATION: - g_object_get_property (G_OBJECT (item), "justification", value); - break; - - case PROP_FILL_COLOR_GDK: - g_object_get_property (G_OBJECT (item), "fill_color_gdk", value); - break; - - case PROP_FILL_COLOR_RGBA: - g_object_get_property (G_OBJECT (item), "fill_color_rgba", value); - break; - - case PROP_FILL_STIPPLE: - g_object_get_property (G_OBJECT (item), "fill_stiple", value); - break; - - case PROP_EDITABLE: - g_object_get_property (G_OBJECT (item), "editable", value); - break; - - case PROP_USE_ELLIPSIS: - g_object_get_property (G_OBJECT (item), "use_ellipsis", value); - break; - - case PROP_ELLIPSIS: - g_object_get_property (G_OBJECT (item), "ellipsis", value); - break; - - case PROP_LINE_WRAP: - g_object_get_property (G_OBJECT (item), "line_wrap", value); - break; - - case PROP_BREAK_CHARACTERS: - g_object_get_property (G_OBJECT (item), "break_characters", value); - break; - - case PROP_MAX_LINES: - g_object_get_property (G_OBJECT (item), "max_lines", value); - break; - case PROP_ALLOW_NEWLINES: - g_object_get_property (G_OBJECT (item), "allow_newlines", value); - break; - - case PROP_DRAW_BORDERS: - g_value_set_boolean (value, entry->priv->draw_borders); - break; - - case PROP_DRAW_BACKGROUND: - g_object_get_property (G_OBJECT (item), "draw_background", value); - break; - - case PROP_DRAW_BUTTON: - g_object_get_property (G_OBJECT (item), "draw_button", value); - break; - - case PROP_EMULATE_LABEL_RESIZE: - g_value_set_boolean (value, entry->priv->emulate_label_resize); - break; - - case PROP_CURSOR_POS: - g_object_get_property (G_OBJECT (item), "cursor_pos", value); - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -et_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EEntry *entry = E_ENTRY (object); - GtkObject *item = GTK_OBJECT (entry->item); - GtkAnchorType anchor; - double width, height; - gint xthick; - gint ythick; - GtkWidget *widget = GTK_WIDGET(entry->canvas); - - d(g_print("%s: prop_id: %d\n", __FUNCTION__, prop_id)); - - switch (prop_id){ - case PROP_MODEL: - g_object_set_property (G_OBJECT (item), "model", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_EVENT_PROCESSOR: - g_object_set_property (G_OBJECT (item), "event_processor", value); - break; - - case PROP_TEXT: - g_object_set_property (G_OBJECT (item), "text", value); - d(g_print("%s: text: %s\n", __FUNCTION__, g_value_get_string (value))); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_FONT: - g_object_set_property (G_OBJECT (item), "font", value); - d(g_print("%s: font: %s\n", __FUNCTION__, g_value_get_string (value))); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_FONTSET: - g_object_set_property (G_OBJECT (item), "fontset", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_FONT_GDK: - g_object_set_property (G_OBJECT (item), "font_gdk", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_JUSTIFICATION: - entry->priv->justification = g_value_get_enum (value); - g_object_get(item, - "clip_width", &width, - "clip_height", &height, - NULL); - - if (entry->priv->draw_borders) { - xthick = 0; - ythick = 0; - } else { - xthick = widget->style->xthickness; - ythick = widget->style->ythickness; - } - - switch (entry->priv->justification) { - case GTK_JUSTIFY_CENTER: - anchor = GTK_ANCHOR_N; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), width / 2, ythick); - break; - case GTK_JUSTIFY_RIGHT: - anchor = GTK_ANCHOR_NE; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), width - xthick, ythick); - break; - default: - anchor = GTK_ANCHOR_NW; - e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(entry->item), xthick, ythick); - break; - } - g_object_set(item, - "justification", entry->priv->justification, - "anchor", anchor, - NULL); - break; - - case PROP_FILL_COLOR: - g_object_set_property (G_OBJECT (item), "fill_color", value); - break; - - case PROP_FILL_COLOR_GDK: - g_object_set_property (G_OBJECT (item), "fill_color_gdk", value); - break; - - case PROP_FILL_COLOR_RGBA: - g_object_set_property (G_OBJECT (item), "fill_color_rgba", value); - break; - - case PROP_FILL_STIPPLE: - g_object_set_property (G_OBJECT (item), "fill_stiple", value); - break; - - case PROP_EDITABLE: - g_object_set_property (G_OBJECT (item), "editable", value); - break; - - case PROP_USE_ELLIPSIS: - g_object_set_property (G_OBJECT (item), "use_ellipsis", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_ELLIPSIS: - g_object_set_property (G_OBJECT (item), "ellipsis", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_LINE_WRAP: - g_object_set_property (G_OBJECT (item), "line_wrap", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_BREAK_CHARACTERS: - g_object_set_property (G_OBJECT (item), "break_characters", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_MAX_LINES: - g_object_set_property (G_OBJECT (item), "max_lines", value); - if (entry->priv->emulate_label_resize) - gtk_widget_queue_resize (widget); - break; - - case PROP_ALLOW_NEWLINES: - g_object_set_property (G_OBJECT (item), "allow_newlines", value); - break; - - case PROP_DRAW_BORDERS: - if (entry->priv->draw_borders != g_value_get_boolean (value)) { - entry->priv->draw_borders = g_value_get_boolean (value); - g_object_set (item, - "draw_borders", entry->priv->draw_borders, - NULL); - gtk_widget_queue_resize (GTK_WIDGET (entry)); - } - break; - - case PROP_CURSOR_POS: - g_object_set_property (G_OBJECT (item), "cursor_pos", value); - break; - - case PROP_DRAW_BACKGROUND: - g_object_set_property (G_OBJECT (item), "draw_background", value); - break; - - case PROP_DRAW_BUTTON: - g_object_set_property (G_OBJECT (item), "draw_button", value); - break; - - case PROP_EMULATE_LABEL_RESIZE: - if (entry->priv->emulate_label_resize != g_value_get_boolean (value)) { - entry->priv->emulate_label_resize = g_value_get_boolean (value); - gtk_widget_queue_resize (widget); - } - break; - } -} - -static void -e_entry_dispose (GObject *object) -{ - EEntry *entry = E_ENTRY (object); - - if (entry->priv) { - if (entry->priv->completion_delay_tag) - gtk_timeout_remove (entry->priv->completion_delay_tag); - - if (entry->priv->completion) - g_object_unref (entry->priv->completion); - if (entry->priv->completion_view_popup) { - gtk_widget_destroy (GTK_WIDGET (entry->priv->completion_view_popup)); - g_object_unref (entry->priv->completion_view_popup); - } - g_free (entry->priv->pre_browse_text); - - if (entry->priv->changed_since_keypress_tag) - gtk_timeout_remove (entry->priv->changed_since_keypress_tag); - - if (entry->priv->ptr_grab) - gdk_pointer_ungrab (GDK_CURRENT_TIME); - - g_free (entry->priv); - entry->priv = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->dispose) - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -e_entry_realize (GtkWidget *widget) -{ - EEntry *entry; - - if (GTK_WIDGET_CLASS (parent_class)->realize) - (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); - - entry = E_ENTRY (widget); - - e_entry_make_completion_window_transient (entry); - - if (entry->priv->emulate_label_resize) { - d(g_print("%s: queue_resize\n", __FUNCTION__)); - gtk_widget_queue_resize (GTK_WIDGET (entry->canvas)); - } -} - -static void -e_entry_class_init (GObjectClass *object_class) -{ - EEntryClass *klass = E_ENTRY_CLASS(object_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(object_class); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->set_property = et_set_property; - object_class->get_property = et_get_property; - object_class->dispose = e_entry_dispose; - - widget_class->realize = e_entry_realize; - - klass->changed = NULL; - klass->activate = NULL; - - e_entry_signals[E_ENTRY_CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EEntryClass, changed), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_entry_signals[E_ENTRY_ACTIVATE] = - g_signal_new ("activate", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EEntryClass, activate), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_entry_signals[E_ENTRY_POPUP] = - g_signal_new ("popup", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EEntryClass, popup), - NULL, NULL, - e_marshal_NONE__POINTER_INT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); - - e_entry_signals[E_ENTRY_COMPLETION_POPUP] = - g_signal_new ("completion_popup", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EEntryClass, completion_popup), - NULL, NULL, - gtk_marshal_NONE__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - g_object_class_install_property (object_class, PROP_MODEL, - g_param_spec_object ("model", - _( "Model" ), - _( "Model" ), - E_TYPE_TEXT_MODEL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EVENT_PROCESSOR, - g_param_spec_object ("event_processor", - _( "Event Processor" ), - _( "Event Processor" ), - E_TEXT_EVENT_PROCESSOR_TYPE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_TEXT, - g_param_spec_string ("text", - _( "Text" ), - _( "Text" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FONT, - g_param_spec_string ("font", - _( "Font" ), - _( "Font" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FONTSET, - g_param_spec_string ("fontset", - _( "Fontset" ), - _( "Fontset" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FONT_GDK, - g_param_spec_boxed ("font_gdk", - _( "GDKFont" ), - _( "GDKFont" ), - GDK_TYPE_FONT, - G_PARAM_WRITABLE)); - - g_object_class_install_property (object_class, PROP_JUSTIFICATION, - g_param_spec_enum ("justification", - _( "Justification" ), - _( "Justification" ), - GTK_TYPE_JUSTIFICATION, GTK_JUSTIFY_LEFT, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FILL_COLOR, - g_param_spec_string ("fill_color", - _( "Fill color" ), - _( "Fill color" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FILL_COLOR_GDK, - g_param_spec_pointer ("fill_color_gdk", - _( "GDK fill color" ), - _( "GDK fill color" ), - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FILL_COLOR_RGBA, - g_param_spec_uint ("fill_color_rgba", - _( "GDK fill color" ), - _( "GDK fill color" ), - 0, G_MAXUINT, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_FILL_STIPPLE, - g_param_spec_object ("fill_stipple", - _( "Fill stipple" ), - _( "FIll stipple" ), - GDK_TYPE_WINDOW, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EDITABLE, - g_param_spec_boolean ("editable", - _( "Editable" ), - _( "Editable" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_USE_ELLIPSIS, - g_param_spec_boolean ("use_ellipsis", - _( "Use ellipsis" ), - _( "Use ellipsis" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_ELLIPSIS, - g_param_spec_string ("ellipsis", - _( "Ellipsis" ), - _( "Ellipsis" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_LINE_WRAP, - g_param_spec_boolean ("line_wrap", - _( "Line wrap" ), - _( "Line wrap" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_BREAK_CHARACTERS, - g_param_spec_string ("break_characters", - _( "Break characters" ), - _( "Break characters" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_MAX_LINES, - g_param_spec_int ("max_lines", - _( "Max lines" ), - _( "Max lines" ), - 0, G_MAXINT, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_ALLOW_NEWLINES, - g_param_spec_boolean ("allow_newlines", - _( "Allow newlines" ), - _( "Allow newlines" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_DRAW_BORDERS, - g_param_spec_boolean ("draw_borders", - _( "Draw borders" ), - _( "Draw borders" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_DRAW_BACKGROUND, - g_param_spec_boolean ("draw_background", - _( "Draw background" ), - _( "Draw background" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_DRAW_BUTTON, - g_param_spec_boolean ("draw_button", - _( "Draw button" ), - _( "Draw button" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_CURSOR_POS, - g_param_spec_int ("cursor_pos", - _( "Cursor position" ), - _( "Cursor position" ), - 0, G_MAXINT, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EMULATE_LABEL_RESIZE, - g_param_spec_boolean ("emulate_label_resize", - _( "Emulate label resize" ), - _( "Emulate label resize" ), - FALSE, - G_PARAM_READWRITE)); -} - -E_MAKE_TYPE(e_entry, "EEntry", EEntry, e_entry_class_init, e_entry_init, PARENT_TYPE) diff --git a/widgets/text/e-entry.h b/widgets/text/e-entry.h deleted file mode 100644 index 8c1093638b..0000000000 --- a/widgets/text/e-entry.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-entry.h - An EText-based entry widget - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef _E_ENTRY_H_ -#define _E_ENTRY_H_ - -#include <libgnomecanvas/gnome-canvas.h> -#include <gtk/gtktable.h> -#include <libxml/tree.h> -#include <gal/e-text/e-text.h> -#include "e-completion.h" - -G_BEGIN_DECLS - -#define E_ENTRY_TYPE (e_entry_get_type ()) -#define E_ENTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_ENTRY_TYPE, EEntry)) -#define E_ENTRY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_ENTRY_TYPE, EEntryClass)) -#define E_IS_ENTRY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_ENTRY_TYPE)) -#define E_IS_ENTRY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_ENTRY_TYPE)) - -typedef struct _EEntry EEntry; -typedef struct _EEntryClass EEntryClass; -struct _EEntryPrivate; - -typedef void (*EEntryCompletionHandler) (EEntry *entry, ECompletionMatch *match); - -struct _EEntry { - GtkTable parent; - - GnomeCanvas *canvas; - EText *item; - - struct _EEntryPrivate *priv; -}; - -struct _EEntryClass { - GtkTableClass parent_class; - - void (* changed) (EEntry *entry); - void (* activate) (EEntry *entry); - void (* popup) (EEntry *entry, GdkEventButton *ev, gint pos); - void (* completion_popup) (EEntry *entry, gint visible); -}; - -GtkType e_entry_get_type (void); - -void e_entry_construct (EEntry *entry); -GtkWidget *e_entry_new (void); - -const gchar *e_entry_get_text (EEntry *entry); -void e_entry_set_text (EEntry *entry, const gchar *text); - -gint e_entry_get_position (EEntry *entry); -void e_entry_set_position (EEntry *entry, gint); -void e_entry_select_region (EEntry *entry, gint start, gint end); - -void e_entry_set_editable (EEntry *entry, gboolean editable); - -void e_entry_enable_completion (EEntry *entry, ECompletion *completion); -void e_entry_enable_completion_full (EEntry *entry, ECompletion *completion, gint autocomplete_delay, - EEntryCompletionHandler handler); -gboolean e_entry_completion_popup_is_visible (EEntry *entry); - -G_END_DECLS - -#endif /* _E_ENTRY_H_ */ diff --git a/widgets/text/e-table-text-model.c b/widgets/text/e-table-text-model.c deleted file mode 100644 index 909a982528..0000000000 --- a/widgets/text/e-table-text-model.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-table-text-model.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> -#include <ctype.h> -#include <gtk/gtksignal.h> -#include <gal/util/e-util.h> -#include "e-table-text-model.h" - -static void e_table_text_model_class_init (ETableTextModelClass *class); -static void e_table_text_model_init (ETableTextModel *model); -static void e_table_text_model_dispose (GObject *object); - -static const gchar *e_table_text_model_get_text (ETextModel *model); -static void e_table_text_model_set_text (ETextModel *model, const gchar *text); -static void e_table_text_model_insert (ETextModel *model, gint postion, const gchar *text); -static void e_table_text_model_insert_length (ETextModel *model, gint postion, const gchar *text, gint length); -static void e_table_text_model_delete (ETextModel *model, gint postion, gint length); - -#define PARENT_TYPE E_TYPE_TEXT_MODEL -static GtkObject *parent_class; - - - -/** - * e_table_text_model_get_type: - * @void: - * - * Registers the &ETableTextModel class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &ETableTextModel class. - **/ -E_MAKE_TYPE (e_table_text_model, - "ETableTextModel", - ETableTextModel, - e_table_text_model_class_init, - e_table_text_model_init, - PARENT_TYPE) - -/* Class initialization function for the text item */ -static void -e_table_text_model_class_init (ETableTextModelClass *klass) -{ - GObjectClass *object_class; - ETextModelClass *model_class; - - object_class = (GObjectClass *) klass; - model_class = (ETextModelClass *) klass; - - parent_class = g_type_class_ref (PARENT_TYPE); - - model_class->get_text = e_table_text_model_get_text; - model_class->set_text = e_table_text_model_set_text; - model_class->insert = e_table_text_model_insert; - model_class->insert_length = e_table_text_model_insert_length; - model_class->delete = e_table_text_model_delete; - - object_class->dispose = e_table_text_model_dispose; -} - -/* Object initialization function for the text item */ -static void -e_table_text_model_init (ETableTextModel *model) -{ - model->model = NULL; - model->row = 0; - model->model_col = 0; - model->cell_changed_signal_id = 0; - model->row_changed_signal_id = 0; -} - -/* Dispose handler for the text item */ -static void -e_table_text_model_dispose (GObject *object) -{ - ETableTextModel *model; - - g_return_if_fail (object != NULL); - g_return_if_fail (E_IS_TABLE_TEXT_MODEL (object)); - - model = E_TABLE_TEXT_MODEL (object); - - if (model->model) - g_assert (GTK_IS_OBJECT (model->model)); - - if (model->cell_changed_signal_id) - g_signal_handler_disconnect (model->model, - model->cell_changed_signal_id); - model->cell_changed_signal_id = 0; - - if (model->row_changed_signal_id) - g_signal_handler_disconnect (model->model, - model->row_changed_signal_id); - model->row_changed_signal_id = 0; - - if (model->model) - g_object_unref (model->model); - model->model = NULL; - - if (G_OBJECT_CLASS (parent_class)->dispose) - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} -static const gchar * -e_table_text_model_get_text (ETextModel *text_model) -{ - ETableTextModel *model = E_TABLE_TEXT_MODEL(text_model); - if (model->model) - return (gchar *)e_table_model_value_at (model->model, model->model_col, model->row); - else - return ""; -} - -static void -e_table_text_model_set_text (ETextModel *text_model, const gchar *text) -{ - ETableTextModel *model = E_TABLE_TEXT_MODEL(text_model); - if (model->model) - e_table_model_set_value_at (model->model, model->model_col, model->row, (void *) text); -} - -static void -e_table_text_model_insert (ETextModel *text_model, gint position, const gchar *text) -{ - ETableTextModel *model = E_TABLE_TEXT_MODEL(text_model); - if (model->model){ - gchar *temp = (gchar *)e_table_model_value_at (model->model, model->model_col, model->row); - /* Can't use g_strdup_printf here because on some - systems printf ("%.*s"); is locale dependent. */ - temp = e_strdup_append_strings (temp, position, - text, -1, - temp + position, -1, - NULL); - e_table_model_set_value_at (model->model, model->model_col, model->row, temp); - g_free (temp); - } -} - -static void -e_table_text_model_insert_length (ETextModel *text_model, gint position, const gchar *text, gint length) -{ - ETableTextModel *model = E_TABLE_TEXT_MODEL(text_model); - if (model->model){ - gchar *temp = (gchar *)e_table_model_value_at (model->model, model->model_col, model->row); - /* Can't use g_strdup_printf here because on some - systems printf ("%.*s"); is locale dependent. */ - temp = e_strdup_append_strings (temp, position, - text, length, - temp + position, -1, - NULL); - e_table_model_set_value_at (model->model, model->model_col, model->row, temp); - g_free (temp); - } -} - -static void -e_table_text_model_delete (ETextModel *text_model, gint position, gint length) -{ - ETableTextModel *model = E_TABLE_TEXT_MODEL(text_model); - if (model->model){ - gchar *temp = (gchar *)e_table_model_value_at (model->model, model->model_col, model->row); - /* Can't use g_strdup_printf here because on some - systems printf ("%.*s"); is locale dependent. */ - temp = e_strdup_append_strings (temp, position, - temp + position + length, -1, - NULL); - e_table_model_set_value_at (model->model, model->model_col, model->row, temp); - g_free (temp); - } -} - -static void -cell_changed (ETableModel *table_model, int model_col, int row, ETableTextModel *model) -{ - if (model->model_col == model_col && - model->row == row) - e_text_model_changed (E_TEXT_MODEL(model)); -} - -static void -row_changed (ETableModel *table_model, int row, ETableTextModel *model) -{ - if (model->row == row) - e_text_model_changed (E_TEXT_MODEL(model)); -} - -ETableTextModel * -e_table_text_model_new (ETableModel *table_model, int row, int model_col) -{ - ETableTextModel *model; - - g_return_val_if_fail(table_model != NULL, NULL); - g_return_val_if_fail(E_IS_TABLE_MODEL(table_model), NULL); - - model = g_object_new (E_TYPE_TABLE_TEXT_MODEL, NULL); - model->model = table_model; - if (model->model){ - g_object_ref (model->model); - model->cell_changed_signal_id = - g_signal_connect (model->model, - "model_cell_changed", - G_CALLBACK(cell_changed), - model); - model->row_changed_signal_id = - g_signal_connect (model->model, - "model_row_changed", - G_CALLBACK(row_changed), - model); - } - model->row = row; - model->model_col = model_col; - return model; -} - diff --git a/widgets/text/e-table-text-model.h b/widgets/text/e-table-text-model.h deleted file mode 100644 index 46e82de1c4..0000000000 --- a/widgets/text/e-table-text-model.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-table-text-model.h - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_TABLE_TEXT_MODEL_H -#define E_TABLE_TEXT_MODEL_H - -#include <gal/e-text/e-text-model.h> -#include <gal/e-table/e-table-model.h> - -G_BEGIN_DECLS - -#define E_TYPE_TABLE_TEXT_MODEL (e_table_text_model_get_type ()) -#define E_TABLE_TEXT_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TABLE_TEXT_MODEL, ETableTextModel)) -#define E_TABLE_TEXT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TABLE_TEXT_MODEL, ETableTextModelClass)) -#define E_IS_TABLE_TEXT_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TABLE_TEXT_MODEL)) -#define E_IS_TABLE_TEXT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_TABLE_TEXT_MODEL)) - -typedef struct _ETableTextModel ETableTextModel; -typedef struct _ETableTextModelClass ETableTextModelClass; - -struct _ETableTextModel { - ETextModel parent; - - ETableModel *model; - int row; - int model_col; - - int cell_changed_signal_id; - int row_changed_signal_id; -}; - -struct _ETableTextModelClass { - ETextModelClass parent_class; - -}; - - -/* Standard Gtk function */ -GtkType e_table_text_model_get_type (void); -ETableTextModel *e_table_text_model_new (ETableModel *table_model, int row, int model_col); - -G_END_DECLS - -#endif diff --git a/widgets/text/e-text-model-repos.c b/widgets/text/e-text-model-repos.c deleted file mode 100644 index 17ffe07578..0000000000 --- a/widgets/text/e-text-model-repos.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model-repos.c - Standard ETextModelReposFn definitions - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include "e-text-model-repos.h" - -#define MODEL_CLAMP(model, pos) (CLAMP((pos), 0, strlen((model)->text))) - -gint -e_repos_shift (gint pos, gpointer data) -{ - EReposShift *info = (EReposShift *) data; - g_return_val_if_fail (data, -1); - - return e_text_model_validate_position (info->model, pos + info->change); -} - -gint -e_repos_absolute (gint pos, gpointer data) -{ - EReposAbsolute *info = (EReposAbsolute *) data; - g_return_val_if_fail (data, -1); - - pos = info->pos; - if (pos < 0) { - gint len = e_text_model_get_text_length (info->model); - pos += len + 1; - } - - return e_text_model_validate_position (info->model, pos); -} - -gint -e_repos_insert_shift (gint pos, gpointer data) -{ - EReposInsertShift *info = (EReposInsertShift *) data; - g_return_val_if_fail (data, -1); - - if (pos >= info->pos) - pos += info->len; - - return e_text_model_validate_position (info->model, pos); -} - -gint -e_repos_delete_shift (gint pos, gpointer data) -{ - EReposDeleteShift *info = (EReposDeleteShift *) data; - g_return_val_if_fail (data, -1); - - if (pos > info->pos + info->len) - pos -= info->len; - else if (pos > info->pos) - pos = info->pos; - - return e_text_model_validate_position (info->model, pos); -} - -gint -e_repos_clamp (gint pos, gpointer data) -{ - ETextModel *model; - - g_return_val_if_fail (data != NULL && E_IS_TEXT_MODEL (data), -1); - model = E_TEXT_MODEL (data); - - return e_text_model_validate_position (model, pos); -} diff --git a/widgets/text/e-text-model-repos.h b/widgets/text/e-text-model-repos.h deleted file mode 100644 index 5f0c93ee6a..0000000000 --- a/widgets/text/e-text-model-repos.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model-repos.h - Standard ETextModelReposFn definitions - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_TEXT_MODEL_REPOS_H -#define E_TEXT_MODEL_REPOS_H - -#include "e-text-model.h" - -typedef struct { - ETextModel *model; - gint change; /* Relative change to position. */ -} EReposShift; - -gint e_repos_shift (gint pos, gpointer data); - - -typedef struct { - ETextModel *model; - gint pos; /* Position to move to. Negative values count from the end buffer. - (i.e. -1 puts cursor at the end, -2 one character from end, etc.) */ -} EReposAbsolute; - -gint e_repos_absolute (gint pos, gpointer data); - - -typedef struct { - ETextModel *model; - gint pos; /* Location of first inserted character. */ - gint len; /* Number of characters inserted. */ -} EReposInsertShift; - -gint e_repos_insert_shift (gint pos, gpointer data); - - -typedef struct { - ETextModel *model; - gint pos; /* Location of first deleted character. */ - gint len; /* Number of characters deleted. */ -} EReposDeleteShift; - -gint e_repos_delete_shift (gint pos, gpointer data); - - -/* For e_repos_clamp, data is a pointer to an ETextModel. The only repositioning - that occurs is to avoid buffer overruns. */ - -gint e_repos_clamp (gint pos, gpointer data); - -#endif diff --git a/widgets/text/e-text-model-test.c b/widgets/text/e-text-model-test.c deleted file mode 100644 index 4913b7774e..0000000000 --- a/widgets/text/e-text-model-test.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model-test.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <gnome.h> -#include <gal/widgets/e-canvas.h> -#include "e-text-model.h" -#include "e-text-model-uri.h" -#include "e-text.h" -#include <gal/util/e-util.h> - -#if 0 -static void -describe_model (ETextModel *model) -{ - gint i, N; - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - N = e_text_model_object_count (model); - - g_print ("text: %s\n", e_text_model_get_text (model)); - g_print ("objs: %d\n", N); - - for (i=0; i<N; ++i) { - gchar *s = e_text_model_strdup_nth_object (model, i); - g_print ("obj%d: %s\n", i, s); - g_free (s); - } -} -#endif - -int -main (int argc, gchar **argv) -{ - GtkWidget *win[2], *canvas[2]; - GnomeCanvasItem *item[2]; - ETextModel *model; - gint i; - - gnome_init ("ETextModelTest", "0.0", argc, argv); - - model = e_text_model_uri_new (); - - e_text_model_set_text (model, "My favorite website is http://www.ximian.com. My next favorite www.assbarn.com."); - - // describe_model (model); - - for (i=0; i<2; ++i) { - win[i] = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - canvas[i] = e_canvas_new (); - gtk_widget_pop_colormap (); - - item[i] = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas[i])), - e_text_get_type (), - "model", model, - "font", "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", - "anchor", GTK_ANCHOR_NORTH, - "line_wrap", TRUE, - "width", 150.0, - "editable", TRUE, - NULL); - - gtk_container_add (GTK_CONTAINER (win[i]), canvas[i]); - gtk_widget_show_all (win[i]); - } - - gtk_main (); - - return 0; -} diff --git a/widgets/text/e-text-model-uri.c b/widgets/text/e-text-model-uri.c deleted file mode 100644 index 858771b481..0000000000 --- a/widgets/text/e-text-model-uri.c +++ /dev/null @@ -1,344 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model-uri.c - a text model w/ clickable URIs - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> - -#include "e-text-model-uri.h" - -#include <ctype.h> -#include <sys/types.h> -#include <regex.h> -#include <gtk/gtkmain.h> -#include <libgnome/gnome-url.h> -#include <gal/util/e-util.h> - -static void e_text_model_uri_class_init (ETextModelURIClass *class); -static void e_text_model_uri_init (ETextModelURI *model); -static void e_text_model_uri_dispose (GObject *object); - -static void objectify_uris (ETextModelURI *model); - -static void e_text_model_uri_objectify (ETextModel *model); -static gint e_text_model_uri_validate_pos (ETextModel *model, gint pos); -static gint e_text_model_uri_get_obj_count (ETextModel *model); -static const gchar *e_text_model_uri_get_nth_object (ETextModel *model, gint i, gint *len); -static void e_text_model_uri_activate_nth_object (ETextModel *model, gint); - -typedef struct _ObjInfo ObjInfo; -struct _ObjInfo { - gint offset, len; -}; - -#define PARENT_TYPE E_TYPE_TEXT_MODEL -static GtkObject *parent_class; - -E_MAKE_TYPE (e_text_model_uri, - "ETextModelURI", - ETextModelURI, - e_text_model_uri_class_init, - e_text_model_uri_init, - PARENT_TYPE) - -static void -e_text_model_uri_class_init (ETextModelURIClass *klass) -{ - GObjectClass *object_class; - ETextModelClass *model_class; - - object_class = (GObjectClass *) klass; - model_class = E_TEXT_MODEL_CLASS (klass); - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = e_text_model_uri_dispose; - - model_class->object_activated = e_text_model_uri_activate_nth_object; - - model_class->objectify = e_text_model_uri_objectify; - model_class->validate_pos = e_text_model_uri_validate_pos; - model_class->obj_count = e_text_model_uri_get_obj_count; - model_class->get_nth_obj = e_text_model_uri_get_nth_object; - -} - -static void -e_text_model_uri_init (ETextModelURI *model) -{ - -} - -static void -e_text_model_uri_dispose (GObject *object) -{ - ETextModelURI *model_uri = E_TEXT_MODEL_URI (object); - GList *iter; - - if (model_uri->objectify_idle) { - gtk_idle_remove (model_uri->objectify_idle); - model_uri->objectify_idle = 0; - } - - for (iter = model_uri->uris; iter != NULL; iter = g_list_next (iter)) - g_free (iter->data); - g_list_free (model_uri->uris); - model_uri->uris = NULL; - - if (G_OBJECT_CLASS (parent_class)->dispose) - (* G_OBJECT_CLASS (parent_class)->dispose) (object); - -} - -static const gchar *uri_regex[] = { - "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp))[-A-Za-z0-9\\.]+(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\) ,\\\"]", - "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp))[-A-Za-z0-9\\.]+[-A-Za-z0-9](:[0-9]*)?", - "mailto:[A-Za-z0-9_]+@[-A-Za-z0-9_]+\\.[-A-Za-z0-9\\.]+[-A-Za-z0-9]", - NULL -}; -static gint regex_count = 0; -static regex_t *regex_compiled = NULL; - -static void -regex_init (void) -{ - gint i; - - if (regex_count != 0) - return; - - while (uri_regex[regex_count]) ++regex_count; - - regex_compiled = g_new0 (regex_t, regex_count); - - for (i=0; i<regex_count; ++i) { - if (regcomp (®ex_compiled[i], uri_regex[i], REG_EXTENDED)) - g_error ("Bad regex?: %s", uri_regex[i]); - } -} - - -static void -objectify_uris (ETextModelURI *model_uri) -{ - static gboolean objectifying = FALSE; - - ETextModel *model = E_TEXT_MODEL (model_uri); - const gchar *txt; - GList *iter, *old_uris; - gint offset, len; - gboolean found_match; - regmatch_t match; - gboolean changed; - - if (objectifying) - return; - - objectifying = TRUE; - - if (regex_count == 0) - regex_init (); - - txt = e_text_model_get_text (model); - len = e_text_model_get_text_length (model); - - old_uris = model_uri->uris; - model_uri->uris = NULL; - - if (txt) { - offset = 0; - found_match = TRUE; - - while (offset < len && found_match) { - - gint i, so=-1, eo=-1; - - found_match = FALSE; - - for (i=0; i<regex_count; ++i) { - - if (regexec (®ex_compiled[i], txt+offset, 1, &match, 0) == 0) { - - /* Take earliest match possible. In case of a tie, take the - largest possible match. */ - if (!found_match - || match.rm_so < so - || (match.rm_so == so && match.rm_eo > eo)) { - so = match.rm_so; - eo = match.rm_eo; - } - found_match = TRUE; - } - } - - if (found_match) { - - ObjInfo *info = g_new0 (ObjInfo, 1); - info->offset = offset + so; - info->len = eo - so; - - model_uri->uris = g_list_append (model_uri->uris, info); - - offset += eo; - } - } - } - - changed = (g_list_length (old_uris) != g_list_length (model_uri->uris)); - - if (!changed) { - /* Check that there is a 1-1 correspondence between object positions. */ - GList *jter; - - for (iter = model_uri->uris; iter != NULL && !changed; iter = g_list_next (iter)) { - ObjInfo *info = (ObjInfo *) iter->data; - found_match = FALSE; - for (jter = old_uris; jter != NULL && !found_match; jter = g_list_next (jter)) { - ObjInfo *jnfo = (ObjInfo *) jter->data; - - if (info->offset == jnfo->offset && info->len == jnfo->len) - found_match = TRUE; - } - changed = !found_match; - } - } - - if (changed) - e_text_model_changed (model); - - /* Free old uris */ - for (iter = old_uris; iter != NULL; iter = g_list_next (iter)) - g_free (iter->data); - g_list_free (old_uris); - - objectifying = FALSE; -} - -static gboolean -objectify_idle_cb (gpointer ptr) -{ - ETextModelURI *model_uri = E_TEXT_MODEL_URI (ptr); - - g_assert (model_uri->objectify_idle); - objectify_uris (model_uri); - model_uri->objectify_idle = 0; - - return FALSE; -} - -static void -e_text_model_uri_objectify (ETextModel *model) -{ - ETextModelURI *model_uri = E_TEXT_MODEL_URI (model); - - if (model_uri->objectify_idle == 0) - model_uri->objectify_idle = gtk_idle_add (objectify_idle_cb, model); - - if (E_TEXT_MODEL_CLASS(parent_class)->objectify) - E_TEXT_MODEL_CLASS(parent_class)->objectify (model); -} - -static void -objectify_idle_flush (ETextModelURI *model_uri) -{ - if (model_uri->objectify_idle) { - gtk_idle_remove (model_uri->objectify_idle); - model_uri->objectify_idle = 0; - objectify_uris (model_uri); - } -} - -static gint -e_text_model_uri_validate_pos (ETextModel *model, gint pos) -{ - gint obj_num; - - /* Cause us to skip over objects */ - - obj_num = e_text_model_get_object_at_offset (model, pos); - if (obj_num != -1) { - gint pos0, pos1, mp; - e_text_model_get_nth_object_bounds (model, obj_num, &pos0, &pos1); - mp = (pos0 + pos1)/2; - if (pos0 < pos && pos < mp) - pos = pos1; - else if (mp <= pos && pos < pos1) - pos = pos0; - } - - - - if (E_TEXT_MODEL_CLASS (parent_class)->validate_pos) - pos = E_TEXT_MODEL_CLASS (parent_class)->validate_pos (model, pos); - - return pos; -} - -static gint -e_text_model_uri_get_obj_count (ETextModel *model) -{ - ETextModelURI *model_uri = E_TEXT_MODEL_URI (model); - - objectify_idle_flush (model_uri); - - return g_list_length (model_uri->uris); -} - -static const gchar * -e_text_model_uri_get_nth_object (ETextModel *model, gint i, gint *len) -{ - ETextModelURI *model_uri = E_TEXT_MODEL_URI (model); - ObjInfo *info; - const gchar *txt; - - objectify_idle_flush (model_uri); - - txt = e_text_model_get_text (model); - - info = (ObjInfo *) g_list_nth_data (model_uri->uris, i); - g_return_val_if_fail (info != NULL, NULL); - - - if (len) - *len = info->len; - return txt + info->offset; -} - -static void -e_text_model_uri_activate_nth_object (ETextModel *model, gint i) -{ - gchar *obj_str; - - objectify_idle_flush (E_TEXT_MODEL_URI (model)); - - obj_str = e_text_model_strdup_nth_object (model, i); - gnome_url_show (obj_str, NULL); - g_free (obj_str); -} - -ETextModel * -e_text_model_uri_new (void) -{ - return E_TEXT_MODEL (g_object_new (E_TYPE_TEXT_MODEL_URI, NULL)); -} - - -/* $Id$ */ diff --git a/widgets/text/e-text-model-uri.h b/widgets/text/e-text-model-uri.h deleted file mode 100644 index 2dcbddbaf6..0000000000 --- a/widgets/text/e-text-model-uri.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model-uri.h - a text model w/ clickable URIs - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Jon Trowbridge <trow@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_TEXT_MODEL_URI_H -#define E_TEXT_MODEL_URI_H - -#include <gal/e-text/e-text-model.h> - -G_BEGIN_DECLS - -#define E_TYPE_TEXT_MODEL_URI (e_text_model_get_type ()) -#define E_TEXT_MODEL_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TEXT_MODEL_URI, ETextModelURI)) -#define E_TEXT_MODEL_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TEXT_MODEL_URI, ETextModelURIClass)) -#define E_IS_TEXT_MODEL_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TEXT_MODEL_URI)) -#define E_IS_TEXT_MODEL_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_TEXT_MODEL_URI)) - -typedef struct _ETextModelURI ETextModelURI; -typedef struct _ETextModelURIClass ETextModelURIClass; - -struct _ETextModelURI { - ETextModel item; - GList *uris; - - guint objectify_idle; -}; - -struct _ETextModelURIClass { - ETextModelClass parent_class; -}; - -GtkType e_text_model_uri_get_type (void); -ETextModel *e_text_model_uri_new (void); - -G_END_DECLS - -#endif diff --git a/widgets/text/e-text-model.c b/widgets/text/e-text-model.c deleted file mode 100644 index 0233f14aa7..0000000000 --- a/widgets/text/e-text-model.c +++ /dev/null @@ -1,633 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model.c - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#undef PARANOID_DEBUGGING - -#include <config.h> -#include <ctype.h> -#include <string.h> -#include <gtk/gtksignal.h> -#include <gal/util/e-util.h> -#include "e-text-model-repos.h" -#include "e-text-model.h" -#include "gal/util/e-util.h" - -#define MAX_LENGTH (2047) - -enum { - E_TEXT_MODEL_CHANGED, - E_TEXT_MODEL_REPOSITION, - E_TEXT_MODEL_OBJECT_ACTIVATED, - E_TEXT_MODEL_CANCEL_COMPLETION, - E_TEXT_MODEL_LAST_SIGNAL -}; - -static guint e_text_model_signals[E_TEXT_MODEL_LAST_SIGNAL] = { 0 }; - -struct _ETextModelPrivate { - gchar *text; - gint len; -}; - -static void e_text_model_class_init (ETextModelClass *class); -static void e_text_model_init (ETextModel *model); -static void e_text_model_dispose (GObject *object); - -static gint e_text_model_real_validate_position (ETextModel *, gint pos); -static const gchar *e_text_model_real_get_text (ETextModel *model); -static gint e_text_model_real_get_text_length (ETextModel *model); -static void e_text_model_real_set_text (ETextModel *model, const gchar *text); -static void e_text_model_real_insert (ETextModel *model, gint postion, const gchar *text); -static void e_text_model_real_insert_length (ETextModel *model, gint postion, const gchar *text, gint length); -static void e_text_model_real_delete (ETextModel *model, gint postion, gint length); - -#define PARENT_TYPE G_TYPE_OBJECT -static GObject *parent_class; - - - -/** - * e_text_model_get_type: - * @void: - * - * Registers the &ETextModel class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &ETextModel class. - **/ -E_MAKE_TYPE (e_text_model, - "ETextModel", - ETextModel, - e_text_model_class_init, - e_text_model_init, - PARENT_TYPE) - -/* Class initialization function for the text item */ -static void -e_text_model_class_init (ETextModelClass *klass) -{ - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; - - parent_class = g_type_class_ref (PARENT_TYPE); - - e_text_model_signals[E_TEXT_MODEL_CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextModelClass, changed), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_text_model_signals[E_TEXT_MODEL_REPOSITION] = - g_signal_new ("reposition", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextModelClass, reposition), - NULL, NULL, - e_marshal_NONE__POINTER_POINTER, - G_TYPE_NONE, 2, - G_TYPE_POINTER, G_TYPE_POINTER); - - e_text_model_signals[E_TEXT_MODEL_OBJECT_ACTIVATED] = - g_signal_new ("object_activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextModelClass, object_activated), - NULL, NULL, - e_marshal_NONE__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - e_text_model_signals[E_TEXT_MODEL_CANCEL_COMPLETION] = - g_signal_new ("cancel_completion", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextModelClass, cancel_completion), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - /* No default signal handlers. */ - klass->changed = NULL; - klass->reposition = NULL; - klass->object_activated = NULL; - - klass->validate_pos = e_text_model_real_validate_position; - - klass->get_text = e_text_model_real_get_text; - klass->get_text_len = e_text_model_real_get_text_length; - klass->set_text = e_text_model_real_set_text; - klass->insert = e_text_model_real_insert; - klass->insert_length = e_text_model_real_insert_length; - klass->delete = e_text_model_real_delete; - - /* We explicitly don't define default handlers for these. */ - klass->objectify = NULL; - klass->obj_count = NULL; - klass->get_nth_obj = NULL; - - object_class->dispose = e_text_model_dispose; -} - -/* Object initialization function for the text item */ -static void -e_text_model_init (ETextModel *model) -{ - model->priv = g_new0 (struct _ETextModelPrivate, 1); - model->priv->text = g_strdup (""); - model->priv->len = 0; -} - -/* Dispose handler for the text item */ -static void -e_text_model_dispose (GObject *object) -{ - ETextModel *model; - - g_return_if_fail (object != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (object)); - - model = E_TEXT_MODEL (object); - - if (model->priv) { - g_free (model->priv->text); - - g_free (model->priv); - model->priv = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static gint -e_text_model_real_validate_position (ETextModel *model, gint pos) -{ - gint len; - - if (pos < 0) - pos = 0; - else if (pos > ( len = e_text_model_get_text_length (model) )) - pos = len; - - return pos; -} - -static const gchar * -e_text_model_real_get_text (ETextModel *model) -{ - if (model->priv->text) - return model->priv->text; - else - return ""; -} - -static gint -e_text_model_real_get_text_length (ETextModel *model) -{ - if (model->priv->len < 0) - model->priv->len = strlen (e_text_model_get_text (model)); - - return model->priv->len; -} - -static void -e_text_model_real_set_text (ETextModel *model, const gchar *text) -{ - EReposAbsolute repos; - gboolean changed = FALSE; - - if (text == NULL) { - - changed = (model->priv->text != NULL); - - g_free (model->priv->text); - model->priv->text = NULL; - model->priv->len = -1; - - } else if (model->priv->text == NULL || strcmp (model->priv->text, text)) { - - g_free (model->priv->text); - model->priv->text = g_strndup (text, MAX_LENGTH); - model->priv->len = -1; - - changed = TRUE; - } - - if (changed) { - e_text_model_changed (model); - repos.model = model; - repos.pos = -1; - e_text_model_reposition (model, e_repos_absolute, &repos); - } -} - -static void -e_text_model_real_insert (ETextModel *model, gint position, const gchar *text) -{ - EReposInsertShift repos; - gchar *new_text; - gint length; - - if (model->priv->len < 0) - e_text_model_real_get_text_length (model); - length = strlen(text); - - if (length + model->priv->len > MAX_LENGTH) - length = MAX_LENGTH - model->priv->len; - if (length <= 0) - return; - - /* Can't use g_strdup_printf here because on some systems - printf ("%.*s"); is locale dependent. */ - new_text = e_strdup_append_strings (model->priv->text, position, - text, length, - model->priv->text + position, -1, - NULL); - - if (model->priv->text) - g_free (model->priv->text); - - model->priv->text = new_text; - - if (model->priv->len >= 0) - model->priv->len += length; - - e_text_model_changed (model); - - repos.model = model; - repos.pos = position; - repos.len = length; - - e_text_model_reposition (model, e_repos_insert_shift, &repos); -} - -static void -e_text_model_real_insert_length (ETextModel *model, gint position, const gchar *text, gint length) -{ - EReposInsertShift repos; - gchar *new_text; - - if (model->priv->len < 0) - e_text_model_real_get_text_length (model); - - if (length + model->priv->len > MAX_LENGTH) - length = MAX_LENGTH - model->priv->len; - if (length <= 0) - return; - - /* Can't use g_strdup_printf here because on some systems - printf ("%.*s"); is locale dependent. */ - new_text = e_strdup_append_strings (model->priv->text, position, - text, length, - model->priv->text + position, -1, - NULL); - - if (model->priv->text) - g_free (model->priv->text); - model->priv->text = new_text; - - if (model->priv->len >= 0) - model->priv->len += length; - - e_text_model_changed (model); - - repos.model = model; - repos.pos = position; - repos.len = length; - - e_text_model_reposition (model, e_repos_insert_shift, &repos); -} - -static void -e_text_model_real_delete (ETextModel *model, gint position, gint length) -{ - EReposDeleteShift repos; - - memmove (model->priv->text + position, model->priv->text + position + length, strlen (model->priv->text + position + length) + 1); - - if (model->priv->len >= 0) - model->priv->len -= length; - - e_text_model_changed (model); - - repos.model = model; - repos.pos = position; - repos.len = length; - - e_text_model_reposition (model, e_repos_delete_shift, &repos); -} - -void -e_text_model_changed (ETextModel *model) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - /* - Objectify before emitting any signal. - While this method could, in theory, do pretty much anything, it is meant - for scanning objects and converting substrings into embedded objects. - */ - if (E_TEXT_MODEL_GET_CLASS (model)->objectify) - E_TEXT_MODEL_GET_CLASS (model)->objectify (model); - - g_signal_emit (model, - e_text_model_signals[E_TEXT_MODEL_CHANGED], 0); -} - -void -e_text_model_cancel_completion (ETextModel *model) -{ - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - g_signal_emit (model, e_text_model_signals[E_TEXT_MODEL_CANCEL_COMPLETION], 0); -} - -void -e_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer repos_data) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - g_return_if_fail (fn != NULL); - - g_signal_emit (model, - e_text_model_signals[E_TEXT_MODEL_REPOSITION], 0, - fn, repos_data); -} - -gint -e_text_model_validate_position (ETextModel *model, gint pos) -{ - g_return_val_if_fail (model != NULL, 0); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), 0); - - if (E_TEXT_MODEL_GET_CLASS (model)->validate_pos) - pos = E_TEXT_MODEL_GET_CLASS (model)->validate_pos (model, pos); - - return pos; -} - -const gchar * -e_text_model_get_text (ETextModel *model) -{ - g_return_val_if_fail (model != NULL, NULL); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), NULL); - - if (E_TEXT_MODEL_GET_CLASS (model)->get_text) - return E_TEXT_MODEL_GET_CLASS (model)->get_text (model); - - return ""; -} - -gint -e_text_model_get_text_length (ETextModel *model) -{ - g_return_val_if_fail (model != NULL, 0); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), 0); - - if (E_TEXT_MODEL_GET_CLASS (model)->get_text_len (model)) { - - gint len = E_TEXT_MODEL_GET_CLASS (model)->get_text_len (model); - -#ifdef PARANOID_DEBUGGING - const gchar *str = e_text_model_get_text (model); - gint len2 = str ? strlen (str) : 0; - if (len != len) - g_error ("\"%s\" length reported as %d, not %d.", str, len, len2); -#endif - - return len; - - } else { - /* Calculate length the old-fashioned way... */ - const gchar *str = e_text_model_get_text (model); - return str ? strlen (str) : 0; - } -} - -void -e_text_model_set_text (ETextModel *model, const gchar *text) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - if (E_TEXT_MODEL_GET_CLASS (model)->set_text) - E_TEXT_MODEL_GET_CLASS (model)->set_text (model, text); -} - -void -e_text_model_insert (ETextModel *model, gint position, const gchar *text) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - if (text == NULL) - return; - - if (E_TEXT_MODEL_GET_CLASS (model)->insert) - E_TEXT_MODEL_GET_CLASS (model)->insert (model, position, text); -} - -void -e_text_model_insert_length (ETextModel *model, gint position, const gchar *text, gint length) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - g_return_if_fail (length >= 0); - - - if (text == NULL || length == 0) - return; - - if (E_TEXT_MODEL_GET_CLASS (model)->insert_length) - E_TEXT_MODEL_GET_CLASS (model)->insert_length (model, position, text, length); -} - -void -e_text_model_prepend (ETextModel *model, const gchar *text) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - if (text == NULL) - return; - - e_text_model_insert (model, 0, text); -} - -void -e_text_model_append (ETextModel *model, const gchar *text) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - if (text == NULL) - return; - - e_text_model_insert (model, e_text_model_get_text_length (model), text); -} - -void -e_text_model_delete (ETextModel *model, gint position, gint length) -{ - gint txt_len; - - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - g_return_if_fail (length >= 0); - - txt_len = e_text_model_get_text_length (model); - if (position + length > txt_len) - length = txt_len - position; - - if (length <= 0) - return; - - if (E_TEXT_MODEL_GET_CLASS (model)->delete) - E_TEXT_MODEL_GET_CLASS (model)->delete (model, position, length); -} - -gint -e_text_model_object_count (ETextModel *model) -{ - g_return_val_if_fail (model != NULL, 0); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), 0); - - if (E_TEXT_MODEL_GET_CLASS (model)->obj_count) - return E_TEXT_MODEL_GET_CLASS (model)->obj_count (model); - - return 0; -} - -const gchar * -e_text_model_get_nth_object (ETextModel *model, gint n, gint *len) -{ - g_return_val_if_fail (model != NULL, NULL); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), NULL); - - if (n < 0 || n >= e_text_model_object_count (model)) - return NULL; - - if (E_TEXT_MODEL_GET_CLASS (model)->get_nth_obj) - return E_TEXT_MODEL_GET_CLASS (model)->get_nth_obj (model, n, len); - - return NULL; -} - -gchar * -e_text_model_strdup_nth_object (ETextModel *model, gint n) -{ - const gchar *obj; - gint len = 0; - - g_return_val_if_fail (model != NULL, NULL); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), NULL); - - obj = e_text_model_get_nth_object (model, n, &len); - - return obj ? g_strndup (obj, n) : NULL; -} - -void -e_text_model_get_nth_object_bounds (ETextModel *model, gint n, gint *start, gint *end) -{ - const gchar *txt = NULL, *obj = NULL; - gint len = 0; - - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - - txt = e_text_model_get_text (model); - obj = e_text_model_get_nth_object (model, n, &len); - - g_return_if_fail (obj != NULL); - - if (start) - *start = obj - txt; - if (end) - *end = obj - txt + len; -} - -gint -e_text_model_get_object_at_offset (ETextModel *model, gint offset) -{ - g_return_val_if_fail (model != NULL, -1); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), -1); - - if (offset < 0 || offset >= e_text_model_get_text_length (model)) - return -1; - - /* If an optimized version has been provided, we use it. */ - if (E_TEXT_MODEL_GET_CLASS (model)->obj_at_offset) { - - return E_TEXT_MODEL_GET_CLASS (model)->obj_at_offset (model, offset); - - } else { - /* If not, we fake it.*/ - - gint i, N, pos0, pos1; - - N = e_text_model_object_count (model); - - for (i = 0; i < N; ++i) { - e_text_model_get_nth_object_bounds (model, i, &pos0, &pos1); - if (pos0 <= offset && offset < pos1) - return i; - } - - } - - return -1; -} - -gint -e_text_model_get_object_at_pointer (ETextModel *model, const gchar *s) -{ - g_return_val_if_fail (model != NULL, -1); - g_return_val_if_fail (E_IS_TEXT_MODEL (model), -1); - g_return_val_if_fail (s != NULL, -1); - - return e_text_model_get_object_at_offset (model, s - e_text_model_get_text (model)); -} - -void -e_text_model_activate_nth_object (ETextModel *model, gint n) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (E_IS_TEXT_MODEL (model)); - g_return_if_fail (n >= 0); - g_return_if_fail (n < e_text_model_object_count (model)); - - g_signal_emit (model, e_text_model_signals[E_TEXT_MODEL_OBJECT_ACTIVATED], 0, n); -} - -ETextModel * -e_text_model_new (void) -{ - ETextModel *model = g_object_new (E_TYPE_TEXT_MODEL, NULL); - return model; -} diff --git a/widgets/text/e-text-model.h b/widgets/text/e-text-model.h deleted file mode 100644 index 2e472ead44..0000000000 --- a/widgets/text/e-text-model.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-model.h - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_TEXT_MODEL_H -#define E_TEXT_MODEL_H - -#include <glib.h> -#include <gtk/gtkobject.h> - -G_BEGIN_DECLS - -#define E_TYPE_TEXT_MODEL (e_text_model_get_type ()) -#define E_TEXT_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TEXT_MODEL, ETextModel)) -#define E_TEXT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TEXT_MODEL, ETextModelClass)) -#define E_IS_TEXT_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TEXT_MODEL)) -#define E_IS_TEXT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_TEXT_MODEL)) -#define E_TEXT_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_TYPE_TEXT_MODEL_TYPE, ETextModelClass)) - -typedef struct _ETextModel ETextModel; -typedef struct _ETextModelClass ETextModelClass; - -struct _ETextModelPrivate; - -typedef gint (*ETextModelReposFn) (gint, gpointer); - -struct _ETextModel { - GObject item; - - struct _ETextModelPrivate *priv; -}; - -struct _ETextModelClass { - GObjectClass parent_class; - - /* Signal */ - void (* changed) (ETextModel *model); - void (* reposition) (ETextModel *model, ETextModelReposFn fn, gpointer repos_fn_data); - void (* object_activated) (ETextModel *model, gint obj_num); - void (* cancel_completion) (ETextModel *model); - - /* Virtual methods */ - - gint (* validate_pos) (ETextModel *model, gint pos); - - const char *(* get_text) (ETextModel *model); - gint (* get_text_len) (ETextModel *model); - void (* set_text) (ETextModel *model, const gchar *text); - void (* insert) (ETextModel *model, gint position, const gchar *text); - void (* insert_length) (ETextModel *model, gint position, const gchar *text, gint length); - void (* delete) (ETextModel *model, gint position, gint length); - - void (* objectify) (ETextModel *model); - gint (* obj_count) (ETextModel *model); - const gchar *(* get_nth_obj) (ETextModel *model, gint n, gint *len); - gint (* obj_at_offset) (ETextModel *model, gint offset); -}; - -GType e_text_model_get_type (void); - -ETextModel *e_text_model_new (void); - -void e_text_model_changed (ETextModel *model); -void e_text_model_cancel_completion (ETextModel *model); - -void e_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer repos_data); -gint e_text_model_validate_position (ETextModel *model, gint pos); - - -/* Functions for manipulating the underlying text. */ - -const gchar *e_text_model_get_text (ETextModel *model); -gint e_text_model_get_text_length (ETextModel *model); -void e_text_model_set_text (ETextModel *model, const gchar *text); -void e_text_model_insert (ETextModel *model, gint position, const gchar *text); -void e_text_model_insert_length (ETextModel *model, gint position, const gchar *text, gint length); -void e_text_model_prepend (ETextModel *model, const gchar *text); -void e_text_model_append (ETextModel *model, const gchar *text); -void e_text_model_delete (ETextModel *model, gint position, gint length); - - -/* Functions for accessing embedded objects. */ - -gint e_text_model_object_count (ETextModel *model); -const gchar *e_text_model_get_nth_object (ETextModel *model, gint n, gint *len); -gchar *e_text_model_strdup_nth_object (ETextModel *model, gint n); -void e_text_model_get_nth_object_bounds (ETextModel *model, gint n, gint *start_pos, gint *end_pos); -gint e_text_model_get_object_at_offset (ETextModel *model, gint offset); -gint e_text_model_get_object_at_pointer (ETextModel *model, const gchar *c); -void e_text_model_activate_nth_object (ETextModel *model, gint n); - -G_END_DECLS - -#endif diff --git a/widgets/text/e-text-test.c b/widgets/text/e-text-test.c deleted file mode 100644 index d10a745d85..0000000000 --- a/widgets/text/e-text-test.c +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text-test.c - E-Text item test program - * Copyright 2000: Iain Holmes <ih@csd.abdn.ac.uk> - * - * Authors: - * Iain Holmes <ih@csd.abdn.ac.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include "e-text.h" -#include <gnome.h> -#include "gal/widgets/e-canvas.h" -#include "gal/widgets/e-unicode.h" - -GnomeCanvasItem *rect; - -static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, GnomeCanvasItem *item) -{ - double height; - gnome_canvas_item_set( item, - "width", (double) allocation->width, - NULL ); - g_object_get(item, - "height", &height, - NULL); - height = MAX(height, allocation->height); - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, allocation->width, height ); - gnome_canvas_item_set( rect, - "x2", (double) allocation->width, - "y2", (double) height, - NULL ); -} - -static void -reflow (GtkWidget *canvas, GnomeCanvasItem *item) -{ - double height; - g_object_get(item, - "height", &height, - NULL); - height = MAX(height, canvas->allocation.height); - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, canvas->allocation.width, height ); - gnome_canvas_item_set( rect, - "x2", (double) canvas->allocation.width, - "y2", (double) height, - NULL ); -} - -static void -quit_cb (gpointer data, GObject *where_object_was) -{ - gtk_main_quit (); -} - -static void -change_text_cb (GtkEntry *entry, - EText *text) -{ - gchar *str; - - str = e_utf8_gtk_entry_get_text (entry); - gnome_canvas_item_set (GNOME_CANVAS_ITEM (text), - "text", str, - NULL); -} - -static void -change_font_cb (GtkEntry *entry, - EText *text) -{ - gchar *font; - - font = gtk_entry_get_text (entry); - gnome_canvas_item_set (GNOME_CANVAS_ITEM (text), - "font", font, - NULL); -} - -int -main (int argc, - char **argv) -{ - GtkWidget *window, *canvas, *scroller, *vbox, *text, *font; - GtkWidget *frame; - GnomeCanvasItem *item; - - gnome_init ("ETextTest", "0.0.1", argc, argv); - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "EText Test"); - g_object_weak_ref (G_OBJECT (window), - quit_cb, NULL); - - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); - canvas = e_canvas_new (); - gtk_widget_pop_colormap (); - scroller = gtk_scrolled_window_new (NULL, NULL); - vbox = gtk_vbox_new (FALSE, 2); - - gtk_container_add (GTK_CONTAINER (window), vbox); - gtk_box_pack_start (GTK_BOX (vbox), scroller, TRUE, TRUE, 2); - gtk_container_add (GTK_CONTAINER (scroller), canvas); - - frame = gtk_frame_new ("Text"); - text = gtk_entry_new (); - gtk_entry_set_text(GTK_ENTRY(text), "Hello World! This is a really long string to test out the ellipsis stuff."); - gtk_container_add (GTK_CONTAINER (frame), text); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - frame = gtk_frame_new ("Font"); - font = gtk_entry_new (); - gtk_entry_set_text(GTK_ENTRY(font), "fixed"); - gtk_container_add (GTK_CONTAINER (frame), font); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - rect = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - - item = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), - e_text_get_type (), - "text", "Hello World! This is a really long string to test out the ellipsis stuff.", - "font", "fixed", - "fill_color", "black", - "anchor", GTK_ANCHOR_NW, - "clip", TRUE, - "use_ellipsis", TRUE, - "editable", TRUE, - "line_wrap", TRUE, - "max_lines", 2, - "width", 150.0, - NULL); - - g_signal_connect (text, "activate", - G_CALLBACK (change_text_cb), item); - g_signal_connect (font, "activate", - G_CALLBACK (change_font_cb), item); - - g_signal_connect (canvas , "size_allocate", - G_CALLBACK (allocate_callback), - item ); - g_signal_connect (canvas , "reflow", - G_CALLBACK (reflow), - item ); - gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0.0, 0.0, 400.0, 400.0); - gtk_widget_show_all (window); - gtk_main (); - - return 0; -} diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c deleted file mode 100644 index 28af5edc20..0000000000 --- a/widgets/text/e-text.c +++ /dev/null @@ -1,3876 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text.c - Text item for evolution. - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Jon Trowbridge <trow@ximian.com> - * - * A majority of code taken from: - * - * Text item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent - * canvas widget. Tk is copyrighted by the Regents of the University - * of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998 The Free Software Foundation - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <config.h> - -#include "e-text.h" - -#include <math.h> -#include <ctype.h> -#include <string.h> -#include <glib-object.h> -#include <gdk/gdkx.h> /* for BlackPixel */ -#include <gtk/gtkinvisible.h> -#include <gtk/gtkmain.h> -#include <gtk/gtkselection.h> -#include <gtk/gtkwindow.h> -#include <gtk/gtktypebuiltins.h> -#include <libgnomecanvas/gnome-canvas-rect-ellipse.h> -#include <libgnome/gnome-i18n.h> -#include "gal/util/e-util.h" -#include "gal/widgets/e-canvas.h" -#include "gal/widgets/e-canvas-utils.h" -#include "gal/widgets/e-unicode.h" -#include "gal/util/e-text-event-processor-emacs-like.h" -#include "gal/util/e-util.h" -#include <libart_lgpl/art_affine.h> -#include <libart_lgpl/art_rgb.h> -#include <libart_lgpl/art_rgb_bitmap_affine.h> - -#define PARENT_TYPE (gnome_canvas_item_get_type()) - -#define BORDER_INDENT 4 -#define d(x) - -enum { - E_TEXT_CHANGED, - E_TEXT_ACTIVATE, - E_TEXT_KEYPRESS, - E_TEXT_POPUP, - E_TEXT_STYLE_SET, - E_TEXT_LAST_SIGNAL -}; - -static GQuark e_text_signals[E_TEXT_LAST_SIGNAL] = { 0 }; - - - -/* This defines a line of text */ -struct line { - const char *text; /* Line's text, it is a pointer into the text->text string */ - int length; /* Line's length IN BYTES */ - int width; /* Line's width in pixels */ - int ellipsis_length; /* Length before adding ellipsis */ -}; - -/* Object argument IDs */ -enum { - PROP_0, - PROP_MODEL, - PROP_EVENT_PROCESSOR, - PROP_TEXT, - PROP_FONT, - PROP_FONTSET, - PROP_FONT_GDK, - PROP_FONT_E, - PROP_BOLD, - PROP_STRIKEOUT, - PROP_ANCHOR, - PROP_JUSTIFICATION, - PROP_CLIP_WIDTH, - PROP_CLIP_HEIGHT, - PROP_CLIP, - PROP_FILL_CLIP_RECTANGLE, - PROP_X_OFFSET, - PROP_Y_OFFSET, - PROP_FILL_COLOR, - PROP_FILL_COLOR_GDK, - PROP_FILL_COLOR_RGBA, - PROP_FILL_STIPPLE, - PROP_TEXT_WIDTH, - PROP_TEXT_HEIGHT, - PROP_EDITABLE, - PROP_USE_ELLIPSIS, - PROP_ELLIPSIS, - PROP_LINE_WRAP, - PROP_BREAK_CHARACTERS, - PROP_MAX_LINES, - PROP_WIDTH, - PROP_HEIGHT, - PROP_DRAW_BORDERS, - PROP_ALLOW_NEWLINES, - PROP_DRAW_BACKGROUND, - PROP_DRAW_BUTTON, - PROP_CURSOR_POS -}; - - -enum { - E_SELECTION_PRIMARY, - E_SELECTION_CLIPBOARD -}; -enum _TargetInfo { - TARGET_UTF8_STRING, - TARGET_UTF8, - TARGET_COMPOUND_TEXT, - TARGET_STRING, - TARGET_TEXT -}; - - -static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data); - -static void e_text_get_selection(EText *text, GdkAtom selection, guint32 time); -static void e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length); - -static void e_text_text_model_changed(ETextModel *model, EText *text); -static void e_text_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer repos_data, gpointer data); - -static void _get_tep(EText *text); - -static GtkWidget *e_text_get_invisible(EText *text); -static void _selection_clear_event (GtkInvisible *invisible, - GdkEventSelection *event, - EText *text); -static void _selection_get (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EText *text); -static void _selection_received (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint time, - EText *text); - -#if 0 -static ETextSuckFont *e_suck_font (GdkFont *font); -static void e_suck_font_free (ETextSuckFont *suckfont); -#endif - -static void e_text_free_lines(EText *text); - -static gint text_width_with_objects (EText *etext, - EFont *font, EFontStyle style, - const gchar *text, gint bytelen); - -static void calc_height (EText *text); -static void calc_line_widths (EText *text); -static void split_into_lines (EText *text); - -static GnomeCanvasItemClass *parent_class; -static GdkAtom clipboard_atom = GDK_NONE; - - - -/* Destroy handler for the text item */ - - -static void -e_text_style_set (EText *text, GtkStyle *previous_style) -{ - if ( text->line_wrap ) { - text->needs_split_into_lines = 1; - } else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - e_canvas_item_request_reflow (GNOME_CANVAS_ITEM (text)); -} - -static void -e_text_destroy (GtkObject *object) -{ - EText *text; - - g_return_if_fail (object != NULL); - g_return_if_fail (E_IS_TEXT (object)); - - text = E_TEXT (object); - - if (text->tooltip_owner) - e_canvas_hide_tooltip (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas)); - text->tooltip_owner = 0; - - if (text->model_changed_signal_id) - g_signal_handler_disconnect (text->model, - text->model_changed_signal_id); - text->model_changed_signal_id = 0; - - if (text->model_repos_signal_id) - g_signal_handler_disconnect (text->model, - text->model_repos_signal_id); - text->model_repos_signal_id = 0; - - if (text->model) - g_object_unref(text->model); - text->model = NULL; - - if (text->tep_command_id) - g_signal_handler_disconnect(text->tep, - text->tep_command_id); - text->tep_command_id = 0; - - if (text->tep) - g_object_unref (text->tep); - text->tep = NULL; - - if (text->invisible) - g_object_unref (text->invisible); - text->invisible = NULL; - - g_free (text->lines); - text->lines = NULL; - - g_free (text->primary_selection); - text->primary_selection = NULL; - - g_free (text->clipboard_selection); - text->clipboard_selection = NULL; - - g_free (text->revert); - text->revert = NULL; - - if (text->font) - e_font_unref (text->font); - text->font = NULL; - -#if 0 - if (text->suckfont) - e_suck_font_free (text->suckfont); -#endif - - if (text->stipple) - gdk_bitmap_unref (text->stipple); - text->stipple = NULL; - - if (text->timeout_id) { - g_source_remove(text->timeout_id); - text->timeout_id = 0; - } - - if (text->timer) { - g_timer_stop(text->timer); - g_timer_destroy(text->timer); - text->timer = NULL; - } - - if ( text->tooltip_timeout ) { - gtk_timeout_remove (text->tooltip_timeout); - text->tooltip_timeout = 0; - } - - if ( text->dbl_timeout ) { - gtk_timeout_remove (text->dbl_timeout); - text->dbl_timeout = 0; - } - - if ( text->tpl_timeout ) { - gtk_timeout_remove (text->tpl_timeout); - text->tpl_timeout = 0; - } - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - -static void -reset_layout_attrs (EText *text) -{ - PangoAttrList *attrs = NULL; - int object_count; - - if (text->layout == NULL) - return; - - object_count = e_text_model_object_count (text->model); - - if (text->bold || text->strikeout || object_count > 0) { - int length = 0; - int i; - - attrs = pango_attr_list_new (); - - for (i = 0; i < object_count; i++) { - int start_pos, end_pos; - PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - - e_text_model_get_nth_object_bounds (text->model, i, &start_pos, &end_pos); - - attr->start_index = start_pos; - attr->end_index = end_pos; - - pango_attr_list_insert (attrs, attr); - } - - if (text->bold || text->strikeout) - length = strlen (text->text); - - if (text->bold) { - PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); - attr->start_index = 0; - attr->end_index = length; - - pango_attr_list_insert_before (attrs, attr); - } - if (text->strikeout) { - PangoAttribute *attr = pango_attr_strikethrough_new (TRUE); - attr->start_index = 0; - attr->end_index = length; - - pango_attr_list_insert_before (attrs, attr); - } - } - pango_layout_set_attributes (text->layout, attrs); - if (attrs) - pango_attr_list_unref (attrs); - calc_height (text); -} - -static void -reset_layout (EText *text) -{ - if (text->layout == NULL) - return; - pango_layout_set_text (text->layout, text->text, -1); - reset_layout_attrs (text); -} - -static void -e_text_text_model_changed (ETextModel *model, EText *text) -{ - gint model_len = e_text_model_get_text_length (model); - text->text = e_text_model_get_text(model); - e_text_free_lines(text); - - /* Make sure our selection doesn't extend past the bounds of our text. */ - text->selection_start = CLAMP (text->selection_start, 0, model_len); - text->selection_end = CLAMP (text->selection_end, 0, model_len); - - text->needs_reset_layout = 1; - text->needs_split_into_lines = 1; - text->needs_redraw = 1; - e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (text)); - - g_signal_emit (text, e_text_signals[E_TEXT_CHANGED], 0); -} - -static void -e_text_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer repos_data, gpointer user_data) -{ - EText *text = E_TEXT (user_data); - gint model_len = e_text_model_get_text_length (model); - - text->selection_start = fn (text->selection_start, repos_data); - text->selection_end = fn (text->selection_end, repos_data); - - /* Our repos function should make sure we don't overrun the buffer, but it never - hurts to be paranoid. */ - text->selection_start = CLAMP (text->selection_start, 0, model_len); - text->selection_end = CLAMP (text->selection_end, 0, model_len); - - if (text->selection_start > text->selection_end) { - gint tmp = text->selection_start; - text->selection_start = text->selection_end; - text->selection_end = tmp; - } -} - -static void -get_bounds (EText *text, double *px1, double *py1, double *px2, double *py2) -{ - GnomeCanvasItem *item; - double wx, wy, clip_width, clip_height; - - item = GNOME_CANVAS_ITEM (text); - - /* Get canvas pixel coordinates for text position */ - - wx = 0; - wy = 0; - gnome_canvas_item_i2w (item, &wx, &wy); - gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy); - gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); - - if (text->clip_width < 0) - clip_width = text->width; - else - clip_width = text->clip_width; - - if ( text->clip_height < 0 ) - clip_height = text->height; - else - clip_height = text->clip_height; - - /* Get canvas pixel coordinates for clip rectangle position */ - text->clip_cwidth = clip_width * item->canvas->pixels_per_unit; - text->clip_cheight = clip_height * item->canvas->pixels_per_unit; - - /* Anchor text */ - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - text->cx -= text->width / 2; - text->clip_cx -= text->clip_cwidth / 2; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - text->cx -= text->width; - text->clip_cx -= text->clip_cwidth; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - text->cy -= text->height / 2; - text->clip_cy -= text->clip_cheight / 2; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - text->cy -= text->height; - text->clip_cy -= text->clip_cheight; - break; - } - - text->text_cx = text->cx; - text->text_cy = text->cy; - - if (text->draw_borders) { - text->text_cx += BORDER_INDENT; - text->text_cy += BORDER_INDENT; - } - - /* Bounds */ - - if (text->clip) { - *px1 = text->clip_cx; - *py1 = text->clip_cy; - *px2 = text->clip_cx + text->clip_cwidth; - *py2 = text->clip_cy + text->clip_cheight; - } else { - *px1 = text->cx; - *py1 = text->cy; - *px2 = text->cx + text->width; - *py2 = text->cy + text->height; - } -} - -static void -calc_height (EText *text) -{ - GnomeCanvasItem *item; - int old_height; - int old_width; - int width = 0; - int height = 0; - - item = GNOME_CANVAS_ITEM (text); - - /* Calculate text dimensions */ - - old_height = text->height; - old_width = text->width; - - if (text->layout) - pango_layout_get_pixel_size (text->layout, &width, &height); - - text->height = height; - text->width = width; - - if (old_height != text->height || old_width != text->width) - e_canvas_item_request_parent_reflow(item); -} - -static void -calc_ellipsis (EText *text) -{ - if (text->font) - text->ellipsis_width = - e_font_utf8_text_width (text->font, text->style, - text->ellipsis ? text->ellipsis : "...", - text->ellipsis ? strlen (text->ellipsis) : 3); -} - -/* Calculates the line widths (in pixels) of the text's splitted lines */ -static void -calc_line_widths (EText *text) -{ - struct line *lines; - int i; - gdouble clip_width; - const gchar *p; - - lines = text->lines; - text->max_width = 0; - - clip_width = text->clip_width; - if (clip_width >= 0 && text->draw_borders) { - clip_width -= 6; - if (clip_width < 0) - clip_width = 0; - } - - - if (!lines) - return; - - for (i = 0; i < text->num_lines; i++) { - if (lines->length != 0) { - if (text->font) { - lines->width = text_width_with_objects (text, - text->font, text->style, - lines->text, lines->length); - lines->ellipsis_length = 0; - } else { - lines->width = 0; - } - - if (text->clip && - text->use_ellipsis && - ! text->editing && - lines->width > clip_width && - clip_width >= 0) { - if (text->font) { - lines->ellipsis_length = 0; - for (p = lines->text; - p && *p && g_unichar_validate (g_utf8_get_char (p)) && (p - lines->text) < lines->length; - p = g_utf8_next_char (p)) { - gint text_width = text_width_with_objects (text, - text->font, text->style, - lines->text, p - lines->text); - if (clip_width >= text_width + text->ellipsis_width) - lines->ellipsis_length = p - lines->text; - else - break; - } - } - else - lines->ellipsis_length = 0; - lines->width = text_width_with_objects (text, - text->font, text->style, - lines->text, lines->ellipsis_length) + - text->ellipsis_width; - } else - lines->ellipsis_length = lines->length; - - if (lines->width > text->max_width) - text->max_width = lines->width; - } - - lines++; - } -} - -static void -e_text_free_lines(EText *text) -{ - if (text->lines) - g_free (text->lines); - - text->lines = NULL; - text->num_lines = 0; -} - -static gint -text_width_with_objects (EText *etext, - EFont *font, EFontStyle style, - const gchar *text, gint numbytes) -{ -#warning "AIEEEE FIX ME. a pango layout per refresh sucks" - PangoLayout *tmp_layout = gtk_widget_create_pango_layout (GTK_WIDGET (GNOME_CANVAS_ITEM (etext)->canvas), - text); - int width; - - pango_layout_get_pixel_size (tmp_layout, &width, NULL); - - g_object_unref (tmp_layout); - - return width; -} - -typedef void (*LineSplitterFn) (int line_num, const char *start, int length, gpointer user_data); - -#define IS_BREAK_CHAR(break_chars, c) (g_unichar_isspace (c) || ((break_chars) && g_utf8_strchr ((break_chars), -1, (c)))) - -static gint -line_splitter (EText *etext, EFont *font, EFontStyle style, - const char *break_characters, - gboolean wrap_lines, double clip_width, double clip_height, - gint max_lines, LineSplitterFn split_cb, gpointer user_data) -{ - ETextModel *model = etext->model; - const char *curr; - const char *text; - const char *linestart; - const char *last_breakpoint; - gint line_count = 0; - - gunichar unival; - - if (max_lines < 1) - max_lines = G_MAXINT; - if (clip_height != -1) - max_lines = CLAMP (max_lines, 1, clip_height / e_font_height (font)); - - text = e_text_model_get_text (model); - linestart = NULL; - last_breakpoint = text; - - for (curr = text; curr && *curr && line_count < max_lines; curr = g_utf8_next_char (curr)) { - - unival = g_utf8_get_char (curr); - - if (linestart == NULL) - linestart = curr; - - if (unival == '\n') { /* We always break on newline */ - - if (split_cb) - split_cb (line_count, linestart, curr - linestart, user_data); - ++line_count; - linestart = NULL; - - } else if (wrap_lines) { - - if (clip_width < text_width_with_objects (etext, font, style, linestart, curr - linestart) - && last_breakpoint > linestart) { - - /* Don't use break point if we are on the last usable line */ - if (split_cb && line_count < max_lines - 1) - split_cb (line_count, linestart, last_breakpoint - linestart, user_data); - else if (split_cb) - split_cb (line_count, linestart, strlen (linestart), user_data); - - ++line_count; - linestart = NULL; - curr = last_breakpoint; - - } else if (IS_BREAK_CHAR (break_characters, unival) - && e_text_model_get_object_at_pointer (model, curr) == -1) { /* don't break mid-object */ - last_breakpoint = curr; - } - } - } - - /* Handle any leftover text. */ - if (linestart) { - if (split_cb) - split_cb (line_count, linestart, strlen (linestart), user_data); - ++line_count; - - } - - if (line_count == 0) { - if (split_cb) - split_cb (0, text, strlen (text), user_data); - line_count ++; - } - - return line_count; -} - -static void -line_split_cb (int line_num, const char *start, int length, gpointer user_data) -{ - EText *text = user_data; - struct line *line = &((struct line *)text->lines)[line_num]; - - line->text = start; - line->length = length; -} - -static void -split_into_lines (EText *text) -{ - /* Free old array of lines */ - e_text_free_lines (text); - - /* First, count the number of lines */ - text->num_lines = line_splitter (text, text->font, text->style, - text->break_characters, - text->line_wrap, text->clip_width, text->clip_height, - -1, NULL, NULL); - - /* Allocate our array of lines */ - text->lines = g_new0 (struct line, text->num_lines); - - text->num_lines = line_splitter (text, text->font, text->style, - text->break_characters, - text->line_wrap, text->clip_width, text->clip_height, - text->num_lines, line_split_cb, text); -} - -/* Convenience function to set the text's GC's foreground color */ -static void -set_text_gc_foreground (EText *text) -{ - if (!text->gc) - return; - - gdk_gc_set_foreground (text->gc, &text->color); -} - -/* Sets the stipple pattern for the text */ -static void -set_stipple (EText *text, GdkBitmap *stipple, int reconfigure) -{ - if (text->stipple && !reconfigure) - gdk_bitmap_unref (text->stipple); - - text->stipple = stipple; - if (stipple && !reconfigure) - gdk_bitmap_ref (stipple); - - if (text->gc) { - if (stipple) { - gdk_gc_set_stipple (text->gc, stipple); - gdk_gc_set_fill (text->gc, GDK_STIPPLED); - } else - gdk_gc_set_fill (text->gc, GDK_SOLID); - } -} - -/* Set_arg handler for the text item */ -static void -e_text_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GnomeCanvasItem *item; - EText *text; - GdkColor color = { 0, 0, 0, 0, }; - GdkColor *pcolor; - gboolean color_changed; - int have_pixel; - - gboolean needs_update = 0; - gboolean needs_reflow = 0; - - item = GNOME_CANVAS_ITEM (object); - text = E_TEXT (object); - - color_changed = FALSE; - have_pixel = FALSE; - - switch (prop_id) { - case PROP_MODEL: - - if ( text->model_changed_signal_id ) - g_signal_handler_disconnect (text->model, - text->model_changed_signal_id); - - if ( text->model_repos_signal_id ) - g_signal_handler_disconnect (text->model, - text->model_repos_signal_id); - - g_object_unref (text->model); - text->model = E_TEXT_MODEL (g_value_get_object (value)); - g_object_ref (text->model); - - text->model_changed_signal_id = - g_signal_connect (text->model, - "changed", - G_CALLBACK (e_text_text_model_changed), - text); - - text->model_repos_signal_id = - g_signal_connect (text->model, - "reposition", - G_CALLBACK (e_text_text_model_reposition), - text); - - e_text_free_lines(text); - - text->text = e_text_model_get_text(text->model); - g_signal_emit (text, e_text_signals[E_TEXT_CHANGED], 0); - - text->needs_split_into_lines = 1; - needs_reflow = 1; - break; - - case PROP_EVENT_PROCESSOR: - if ( text->tep && text->tep_command_id ) - g_signal_handler_disconnect(text->tep, - text->tep_command_id); - if ( text->tep ) { - g_object_unref(text->tep); - } - text->tep = E_TEXT_EVENT_PROCESSOR(g_value_get_object (value)); - g_object_ref(text->tep); - text->tep_command_id = - g_signal_connect(text->tep, - "command", - G_CALLBACK(e_text_command), - text); - if (!text->allow_newlines) - g_object_set (text->tep, - "allow_newlines", FALSE, - NULL); - break; - - case PROP_TEXT: - e_text_model_set_text(text->model, g_value_get_string (value)); - break; - - case PROP_FONT: - if (text->font) - e_font_unref (text->font); - - text->font = e_font_from_gdk_name (g_value_get_string (value)); - - calc_ellipsis (text); - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_FONTSET: - if (text->font) - e_font_unref (text->font); - - text->font = e_font_from_gdk_name (g_value_get_string (value)); - - calc_ellipsis (text); - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_FONT_GDK: - /* Ref the font in case it was the font that is stored - in the e-font */ - gdk_font_ref (g_value_get_boxed (value)); - if (text->font) - e_font_unref (text->font); - - text->font = e_font_from_gdk_font (g_value_get_boxed (value)); - - calc_ellipsis (text); - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_FONT_E: - if (text->font) - e_font_unref (text->font); - - text->font = g_value_get_pointer (value); - e_font_ref (text->font); - - calc_ellipsis (text); - if (text->line_wrap) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_BOLD: - text->bold = g_value_get_boolean (value); - text->style = text->bold ? E_FONT_BOLD : E_FONT_PLAIN; - - text->needs_redraw = 1; - text->needs_recalc_bounds = 1; - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_update = 1; - needs_reflow = 1; - break; - - case PROP_STRIKEOUT: - text->strikeout = g_value_get_boolean (value); - text->needs_redraw = 1; - needs_update = 1; - break; - - case PROP_ANCHOR: - text->anchor = g_value_get_enum (value); - text->needs_recalc_bounds = 1; - needs_update = 1; - break; - - case PROP_JUSTIFICATION: - text->justification = g_value_get_enum (value); - text->needs_redraw = 1; - needs_update = 1; - break; - - case PROP_CLIP_WIDTH: - text->clip_width = fabs (g_value_get_double (value)); - calc_ellipsis (text); - if (text->layout) { - pango_layout_set_width (text->layout, text->clip_width < 0 ? -1 : text->clip_width * PANGO_SCALE); - } - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_CLIP_HEIGHT: - text->clip_height = fabs (g_value_get_double (value)); - text->needs_recalc_bounds = 1; - needs_reflow = 1; - break; - - case PROP_CLIP: - text->clip = g_value_get_boolean (value); - calc_ellipsis (text); - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_FILL_CLIP_RECTANGLE: - text->fill_clip_rectangle = g_value_get_boolean (value); - needs_update = 1; - break; - - case PROP_X_OFFSET: - text->xofs = g_value_get_double (value); - text->needs_recalc_bounds = 1; - needs_update = 1; - break; - - case PROP_Y_OFFSET: - text->yofs = g_value_get_double (value); - text->needs_recalc_bounds = 1; - needs_update = 1; - break; - - case PROP_FILL_COLOR: - if (g_value_get_string (value)) - gdk_color_parse (g_value_get_string (value), &color); - - text->rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case PROP_FILL_COLOR_GDK: - pcolor = g_value_get_boxed (value); - if (pcolor) { - color = *pcolor; - } - - text->rgba = ((color.red & 0xff00) << 16 | - (color.green & 0xff00) << 8 | - (color.blue & 0xff00) | - 0xff); - color_changed = TRUE; - break; - - case PROP_FILL_COLOR_RGBA: - text->rgba = g_value_get_uint (value); - color.red = ((text->rgba >> 24) & 0xff) * 0x101; - color.green = ((text->rgba >> 16) & 0xff) * 0x101; - color.blue = ((text->rgba >> 8) & 0xff) * 0x101; - color_changed = TRUE; - break; - - case PROP_FILL_STIPPLE: - set_stipple (text, g_value_get_object (value), FALSE); - text->needs_redraw = 1; - needs_update = 1; - break; - - case PROP_EDITABLE: - text->editable = g_value_get_boolean (value); - text->needs_redraw = 1; - needs_update = 1; - break; - - case PROP_USE_ELLIPSIS: - text->use_ellipsis = g_value_get_boolean (value); - text->needs_calc_line_widths = 1; - needs_reflow = 1; - break; - - case PROP_ELLIPSIS: - if (text->ellipsis) - g_free (text->ellipsis); - - text->ellipsis = g_strdup (g_value_get_string (value)); - calc_ellipsis (text); - text->needs_calc_line_widths = 1; - needs_reflow = 1; - break; - - case PROP_LINE_WRAP: - text->line_wrap = g_value_get_boolean (value); - text->needs_split_into_lines = 1; - needs_reflow = 1; - break; - - case PROP_BREAK_CHARACTERS: - if ( text->break_characters ) { - g_free(text->break_characters); - text->break_characters = NULL; - } - if ( g_value_get_string (value) ) - text->break_characters = g_strdup( g_value_get_string (value) ); - text->needs_split_into_lines = 1; - needs_reflow = 1; - break; - - case PROP_MAX_LINES: - text->max_lines = g_value_get_int (value); - text->needs_split_into_lines = 1; - needs_reflow = 1; - break; - - case PROP_WIDTH: - text->clip_width = fabs (g_value_get_double (value)); - calc_ellipsis (text); - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else { - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - needs_reflow = 1; - break; - - case PROP_DRAW_BORDERS: - if (text->draw_borders != g_value_get_boolean (value)) { - text->draw_borders = g_value_get_boolean (value); - text->needs_calc_height = 1; - text->needs_redraw = 1; - needs_reflow = 1; - needs_update = 1; - } - break; - - case PROP_DRAW_BACKGROUND: - if (text->draw_background != g_value_get_boolean (value)) { - text->draw_background = g_value_get_boolean (value); - text->needs_redraw = 1; - } - break; - - case PROP_DRAW_BUTTON: - if (text->draw_button != g_value_get_boolean (value)) { - text->draw_button = g_value_get_boolean (value); - text->needs_redraw = 1; - } - break; - - case PROP_ALLOW_NEWLINES: - text->allow_newlines = g_value_get_boolean (value); - _get_tep(text); - g_object_set (text->tep, - "allow_newlines", g_value_get_boolean (value), - NULL); - break; - - case PROP_CURSOR_POS: { - ETextEventProcessorCommand command; - - command.action = E_TEP_MOVE; - command.position = E_TEP_VALUE; - command.value = g_value_get_int (value); - command.time = GDK_CURRENT_TIME; - e_text_command (text->tep, &command, text); - break; - } - - default: - return; - } - - if (color_changed) { - GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas)); - - text->color = color; - gdk_rgb_find_color (colormap, &text->color); - - if (!item->canvas->aa) - set_text_gc_foreground (text); - - text->needs_redraw = 1; - needs_update = 1; - } - - if ( needs_reflow ) - e_canvas_item_request_reflow (item); - if ( needs_update ) - gnome_canvas_item_request_update (item); -} - -/* Get_arg handler for the text item */ -static void -e_text_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EText *text; - - text = E_TEXT (object); - - switch (prop_id) { - case PROP_MODEL: - g_value_set_object (value, text->model); - break; - - case PROP_EVENT_PROCESSOR: - _get_tep(text); - g_value_set_object (value, text->tep); - break; - - case PROP_TEXT: - g_value_set_string (value, g_strdup (text->text)); - break; - - case PROP_FONT_E: - g_value_set_pointer (value, text->font); - break; - - case PROP_BOLD: - g_value_set_boolean (value, text->bold); - break; - - case PROP_STRIKEOUT: - g_value_set_boolean (value, text->strikeout); - break; - - case PROP_ANCHOR: - g_value_set_enum (value, text->anchor); - break; - - case PROP_JUSTIFICATION: - g_value_set_enum (value, text->justification); - break; - - case PROP_CLIP_WIDTH: - g_value_set_double (value, text->clip_width); - break; - - case PROP_CLIP_HEIGHT: - g_value_set_double (value, text->clip_height); - break; - - case PROP_CLIP: - g_value_set_boolean (value, text->clip); - break; - - case PROP_FILL_CLIP_RECTANGLE: - g_value_set_boolean (value, text->fill_clip_rectangle); - break; - - case PROP_X_OFFSET: - g_value_set_double (value, text->xofs); - break; - - case PROP_Y_OFFSET: - g_value_set_double (value, text->yofs); - break; - - case PROP_FILL_COLOR_GDK: - g_value_set_boxed (value, &text->color); - break; - - case PROP_FILL_COLOR_RGBA: - g_value_set_uint (value, text->rgba); - break; - - case PROP_FILL_STIPPLE: - g_value_set_object (value, text->stipple); - break; - - case PROP_TEXT_WIDTH: - g_value_set_double (value, text->width / text->item.canvas->pixels_per_unit); - break; - - case PROP_TEXT_HEIGHT: - g_value_set_double (value, text->height / text->item.canvas->pixels_per_unit); - break; - - case PROP_EDITABLE: - g_value_set_boolean (value, text->editable); - break; - - case PROP_USE_ELLIPSIS: - g_value_set_boolean (value, text->use_ellipsis); - break; - - case PROP_ELLIPSIS: - g_value_set_string (value, g_strdup (text->ellipsis)); - break; - - case PROP_LINE_WRAP: - g_value_set_boolean (value, text->line_wrap); - break; - - case PROP_BREAK_CHARACTERS: - g_value_set_string (value, g_strdup (text->break_characters)); - break; - - case PROP_MAX_LINES: - g_value_set_int (value, text->max_lines); - break; - - case PROP_WIDTH: - g_value_set_double (value, text->clip_width); - break; - - case PROP_HEIGHT: - g_value_set_double (value, text->clip && text->clip_height != -1 ? text->clip_height : text->height / text->item.canvas->pixels_per_unit); - break; - - case PROP_DRAW_BORDERS: - g_value_set_boolean (value, text->draw_borders); - break; - - case PROP_DRAW_BACKGROUND: - g_value_set_boolean (value, text->draw_background); - break; - - case PROP_DRAW_BUTTON: - g_value_set_boolean (value, text->draw_button); - break; - - case PROP_ALLOW_NEWLINES: - g_value_set_boolean (value, text->allow_newlines); - break; - - case PROP_CURSOR_POS: - g_value_set_int (value, text->selection_start); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* Update handler for the text item */ -static void -e_text_reflow (GnomeCanvasItem *item, int flags) -{ - EText *text; - - text = E_TEXT (item); - - if (text->needs_reset_layout) { - reset_layout (text); - text->needs_reset_layout = 0; - text->needs_calc_height = 1; - } - - if (text->needs_split_into_lines) { - split_into_lines (text); - - text->needs_split_into_lines = 0; - text->needs_calc_line_widths = 1; - text->needs_calc_height = 1; - } - - if ( text->needs_calc_line_widths ) { - int x; - int i; - struct line *lines; - gdouble clip_width; - calc_line_widths (text); - text->needs_calc_line_widths = 0; - text->needs_redraw = 1; - - lines = text->lines; - if ( !lines ) - return; - - for (lines = text->lines, i = 0; i < text->num_lines ; i++, lines ++) { - if ((lines->text - text->text) > text->selection_end) { - break; - } - } - lines --; - i--; - x = text_width_with_objects (text, - text->font, text->style, - lines->text, - text->selection_end - (lines->text - text->text)); - - if (x < text->xofs_edit) { - text->xofs_edit = x; - } - - clip_width = text->clip_width; - if (clip_width >= 0 && text->draw_borders) { - clip_width -= 6; - if (clip_width < 0) - clip_width = 0; - } - - if (2 + x - clip_width > text->xofs_edit) { - text->xofs_edit = 2 + x - clip_width; - } - - if (e_font_height (text->font) * i < text->yofs_edit) - text->yofs_edit = e_font_height (text->font) * i; - - if ( text->needs_calc_height ) { - calc_height (text); - gnome_canvas_item_request_update(item); - text->needs_calc_height = 0; - text->needs_recalc_bounds = 1; - } - - if (e_font_height (text->font) * (i + 1) - - (text->clip_height != -1 ? text->clip_height : text->height) > text->yofs_edit) - text->yofs_edit = e_font_height (text->font) * (i + 1) - - (text->clip_height != -1 ? text->clip_height : text->height); - - gnome_canvas_item_request_update (item); - } - if ( text->needs_calc_height ) { - calc_height (text); - gnome_canvas_item_request_update(item); - text->needs_calc_height = 0; - text->needs_recalc_bounds = 1; - } -} - -/* Update handler for the text item */ -static void -e_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) -{ - EText *text; - double x1, y1, x2, y2; - - text = E_TEXT (item); - - if (parent_class->update) - (* parent_class->update) (item, affine, clip_path, flags); - - if ( text->needs_recalc_bounds - || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { - if (!item->canvas->aa) { - set_text_gc_foreground (text); - set_stipple (text, text->stipple, TRUE); - get_bounds (text, &x1, &y1, &x2, &y2); - if ( item->x1 != x1 || - item->x2 != x2 || - item->y1 != y1 || - item->y2 != y2 ) { - gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); - item->x1 = x1; - item->y1 = y1; - item->x2 = x2; - item->y2 = y2; - text->needs_redraw = 1; - item->canvas->need_repick = TRUE; - } - if (!text->fill_clip_rectangle) - item->canvas->need_repick = TRUE; - } - text->needs_recalc_bounds = 0; - } - if ( text->needs_redraw ) { - gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); - text->needs_redraw = 0; - } -} - -/* Realize handler for the text item */ -static void -e_text_realize (GnomeCanvasItem *item) -{ - EText *text; - - text = E_TEXT (item); - - if (parent_class->realize) - (* parent_class->realize) (item); - - text->layout = gtk_widget_create_pango_layout (GTK_WIDGET (item->canvas), text->text); - pango_layout_set_width (text->layout, text->clip_width < 0 ? -1 : text->clip_width * PANGO_SCALE); - reset_layout_attrs (text); - - text->gc = gdk_gc_new (item->canvas->layout.bin_window); -#ifndef NO_WARNINGS -#warning Color brokenness ... -#endif -#if 0 - gdk_color_context_query_color (item->canvas->cc, &text->color); - gdk_gc_set_foreground (text->gc, &text->color); -#endif - - text->i_cursor = gdk_cursor_new (GDK_XTERM); - text->default_cursor = gdk_cursor_new (GDK_LEFT_PTR); - if (text->font == NULL) { - gdk_font_ref (gtk_style_get_font (GTK_WIDGET (item->canvas)->style)); - text->font = e_font_from_gdk_font (gtk_style_get_font (GTK_WIDGET (item->canvas)->style)); - } -} - -/* Unrealize handler for the text item */ -static void -e_text_unrealize (GnomeCanvasItem *item) -{ - EText *text; - - text = E_TEXT (item); - - gdk_gc_unref (text->gc); - text->gc = NULL; - - gdk_cursor_destroy (text->i_cursor); - text->i_cursor = NULL; - gdk_cursor_destroy (text->default_cursor); - text->default_cursor = NULL; - g_object_unref (text->layout); - text->layout = NULL; - - if (parent_class->unrealize) - (* parent_class->unrealize) (item); -} - -static void -_get_tep(EText *text) -{ - if (!text->tep) { - text->tep = e_text_event_processor_emacs_like_new(); - text->tep_command_id = - g_signal_connect(text->tep, - "command", - G_CALLBACK(e_text_command), - text); - } -} - -static void -draw_pango_rectangle (GdkDrawable *drawable, GdkGC *gc, int x1, int y1, PangoRectangle rect) -{ - int width = rect.width / PANGO_SCALE; - int height = rect.height / PANGO_SCALE; - if (width <= 0) - width = 1; - if (height <= 0) - height = 1; - gdk_draw_rectangle (drawable, gc, TRUE, - x1 + rect.x / PANGO_SCALE, y1 + rect.y / PANGO_SCALE, width, height); -} - -static gboolean -show_pango_rectangle (EText *text, PangoRectangle rect) -{ - int x1 = rect.x / PANGO_SCALE; - int x2 = (rect.x + rect.width) / PANGO_SCALE; - - int y1 = rect.y / PANGO_SCALE; - int y2 = (rect.y + rect.height) / PANGO_SCALE; - - int new_xofs_edit = text->xofs_edit; - int new_yofs_edit = text->yofs_edit; - - int clip_width, clip_height; - - clip_width = text->clip_width; - if (clip_width >= 0 && text->draw_borders) { - clip_width -= 6; - if (clip_width < 0) - clip_width = 0; - } - - clip_height = text->clip_height; - - if (clip_height >= 0 && text->draw_borders) { - clip_height -= 6; - if (clip_height < 0) - clip_height = 0; - } - - if (x1 < new_xofs_edit) - new_xofs_edit = x1; - - if (y1 < new_yofs_edit) - new_yofs_edit = y1; - - if (clip_width >= 0) { - if (2 + x2 - clip_width > new_xofs_edit) - new_xofs_edit = 2 + x2 - clip_width; - } else { - new_xofs_edit = 0; - } - - if (clip_height >= 0) { - if (2 + y2 - clip_height > new_yofs_edit) - new_yofs_edit = 2 + y2 - clip_height; - } else { - new_yofs_edit = 0; - } - - if (new_xofs_edit < 0) - new_xofs_edit = 0; - if (new_yofs_edit < 0) - new_yofs_edit = 0; - - if (new_xofs_edit != text->xofs_edit || - new_yofs_edit != text->yofs_edit) { - text->xofs_edit = new_xofs_edit; - text->yofs_edit = new_yofs_edit; - return TRUE; - } - - return FALSE; -} - -/* Draw handler for the text item */ -static void -e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, - int x, int y, int width, int height) -{ - EText *text; - GdkRectangle rect, *clip_rect; - int xpos, ypos; - GdkGC *main_gc; - GnomeCanvas *canvas; - GtkWidget *widget; - - text = E_TEXT (item); - canvas = GNOME_CANVAS_ITEM(text)->canvas; - widget = GTK_WIDGET(canvas); - - if (text->draw_background || text->draw_button) { - main_gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)]; - } else { - main_gc = text->gc; - } - - if (text->draw_borders || text->draw_background) { - gdouble thisx = item->x1 - x; - gdouble thisy = item->y1 - y; - gdouble thiswidth, thisheight; - GtkWidget *widget = GTK_WIDGET(item->canvas); - - g_object_get(text, - "width", &thiswidth, - "height", &thisheight, - NULL); - - if (text->draw_borders){ - - if (text->editing) { - thisx += 1; - thisy += 1; - thiswidth -= 2; - thisheight -= 2; - } - - gtk_paint_shadow (widget->style, drawable, - GTK_STATE_NORMAL, GTK_SHADOW_IN, - NULL, widget, "entry", - thisx, thisy, thiswidth, thisheight); - - if (text->editing) { - thisx -= 1; - thisy -= 1; - thiswidth += 2; - thisheight += 2; - /* - * Chris: I am here "filling in" for the additions - * and substractions done in the previous if (text->editing). - * but you might have other plans for this. Please enlighten - * me as to whether it should be: - * thiswidth + 2 or thiswidth + 1. - */ - gtk_paint_focus (widget->style, drawable, GTK_STATE_NORMAL, - NULL, widget, "entry", - thisx, thisy, thiswidth - 1, thisheight - 1); - } - } - - if (text->draw_background) { - gtk_paint_flat_box (widget->style, drawable, - GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, - NULL, widget, "entry_bg", - thisx + widget->style->xthickness, - thisy + widget->style->ythickness, - thiswidth - widget->style->xthickness * 2, - thisheight - widget->style->ythickness * 2); - } - } - if (text->draw_button) { - GtkWidget *widget; - int xoff = item->x1 - x; - int yoff = item->y1 - y; - - widget = GTK_WIDGET (item->canvas); - - xoff -= widget->allocation.x; - yoff -= widget->allocation.y; - - widget = widget->parent; - - while (widget && !GTK_IS_BUTTON(widget)) { - if (!GTK_WIDGET_NO_WINDOW (widget)) { - widget = NULL; - break; - } - widget = widget->parent; - } - if (widget) { - GtkButton *button = GTK_BUTTON (widget); - GtkShadowType shadow_type; - int thisx, thisy, thisheight, thiswidth; - int default_spacing; - GdkRectangle area; - area.x = 0; - area.y = 0; - area.width = width; - area.height = height; - -#define DEFAULT_SPACING 7 -#if 0 - default_spacing = gtk_style_get_prop_experimental (widget->style, - "GtkButton::default_spacing", - DEFAULT_SPACING); -#endif - default_spacing = 7; - - thisx = 0; - thisy = 0; - thiswidth = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2; - thisheight = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2; - - if (GTK_WIDGET_HAS_DEFAULT (widget) && - GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL) - { - gtk_paint_box (widget->style, drawable, - GTK_STATE_NORMAL, GTK_SHADOW_IN, - &area, widget, "buttondefault", - thisx + xoff, thisy + yoff, thiswidth, thisheight); - } - - if (GTK_WIDGET_CAN_DEFAULT (widget)) { - thisx += widget->style->xthickness; - thisy += widget->style->ythickness; - thiswidth -= 2 * thisx + default_spacing; - thisheight -= 2 * thisy + default_spacing; - thisx += (1 + default_spacing) / 2; - thisy += (1 + default_spacing) / 2; - } - - if (GTK_WIDGET_HAS_FOCUS (widget)) { - thisx += 1; - thisy += 1; - thiswidth -= 2; - thisheight -= 2; - } - - if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE) - shadow_type = GTK_SHADOW_IN; - else - shadow_type = GTK_SHADOW_OUT; - - if ((button->relief != GTK_RELIEF_NONE) || - ((GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL) && - (GTK_WIDGET_STATE(widget) != GTK_STATE_INSENSITIVE))) - gtk_paint_box (widget->style, drawable, - GTK_WIDGET_STATE (widget), - shadow_type, &area, widget, "button", - thisx + xoff, thisy + yoff, thiswidth, thisheight); - - if (GTK_WIDGET_HAS_FOCUS (widget)) { - thisx -= 1; - thisy -= 1; - thiswidth += 2; - thisheight += 2; - - gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), - &area, widget, "button", - thisx + xoff, thisy + yoff, thiswidth - 1, thisheight - 1); - } - } - } - - if (!text->text || !text->font) - return; - - clip_rect = NULL; - if (text->clip) { - rect.x = text->clip_cx - x; - rect.y = text->clip_cy - y; - rect.width = text->clip_cwidth; - rect.height = text->clip_cheight; - - gdk_gc_set_clip_rectangle (main_gc, &rect); - clip_rect = ▭ - } - - if (text->stipple) - gnome_canvas_set_stipple_origin (item->canvas, main_gc); - - xpos = text->text_cx; - ypos = text->text_cy; - - xpos -= x; - ypos -= y; - - if (text->editing) { - xpos -= text->xofs_edit; - ypos -= text->yofs_edit; - } - - gdk_draw_layout (drawable, main_gc, - xpos, ypos, - text->layout); - - if (text->editing) { - if (text->selection_start != text->selection_end) { - int start_index, end_index; - PangoLayoutLine *line; - gint *ranges; - gint n_ranges, i; - PangoRectangle logical_rect; - GdkRegion *clip_region = gdk_region_new (); - GdkGC *selection_gc; - GdkGC *text_gc; - - start_index = MIN (text->selection_start, text->selection_end); - end_index = text->selection_start ^ text->selection_end ^ start_index; - - if (text->has_selection) { - selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; - text_gc = widget->style->text_gc[GTK_STATE_SELECTED]; - } else { - selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; - text_gc = widget->style->text_gc[GTK_STATE_ACTIVE]; - } - - gdk_gc_set_clip_rectangle (selection_gc, clip_rect); - - line = pango_layout_get_lines (text->layout)->data; - - pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges); - - pango_layout_get_extents (text->layout, NULL, &logical_rect); - - for (i=0; i < n_ranges; i++) { - GdkRectangle sel_rect; - - sel_rect.x = xpos + ranges[2*i] / PANGO_SCALE; - sel_rect.y = ypos; - sel_rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE; - sel_rect.height = logical_rect.height / PANGO_SCALE; - - gdk_draw_rectangle (drawable, selection_gc, TRUE, - sel_rect.x, sel_rect.y, sel_rect.width, sel_rect.height); - - gdk_region_union_with_rect (clip_region, &sel_rect); - } - - if (clip_rect) { - GdkRegion *rect_region = gdk_region_rectangle (clip_rect); - gdk_region_intersect (clip_region, rect_region); - gdk_region_destroy (rect_region); - } - - gdk_gc_set_clip_region (text_gc, clip_region); - gdk_draw_layout (drawable, text_gc, - xpos, ypos, - text->layout); - - gdk_gc_set_clip_region (text_gc, NULL); - gdk_gc_set_clip_region (selection_gc, NULL); - - gdk_region_destroy (clip_region); - g_free (ranges); - } else { - if (text->show_cursor) { - PangoRectangle strong_pos, weak_pos; - pango_layout_get_cursor_pos (text->layout, text->selection_start, &strong_pos, &weak_pos); - draw_pango_rectangle (drawable, main_gc, xpos, ypos, strong_pos); - if (strong_pos.x != weak_pos.x || - strong_pos.y != weak_pos.y || - strong_pos.width != weak_pos.width || - strong_pos.height != weak_pos.height) - draw_pango_rectangle (drawable, main_gc, xpos, ypos, weak_pos); - } - } - } - - - if (text->clip) { - gdk_gc_set_clip_rectangle (main_gc, NULL); - } -} - -/* Render handler for the text item */ -static void -e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) -{ -} - -/* Point handler for the text item */ -static double -e_text_point (GnomeCanvasItem *item, double x, double y, - int cx, int cy, GnomeCanvasItem **actual_item) -{ - EText *text; - double clip_width; - double clip_height; - - text = E_TEXT (item); - - *actual_item = item; - - /* The idea is to build bounding rectangles for each of the lines of - * text (clipped by the clipping rectangle, if it is activated) and see - * whether the point is inside any of these. If it is, we are done. - * Otherwise, calculate the distance to the nearest rectangle. - */ - - if (text->clip_width < 0) - clip_width = text->width; - else - clip_width = text->clip_width; - - if ( text->clip_height < 0 ) - clip_height = text->height; - else - clip_height = text->clip_height; - - /* Get canvas pixel coordinates for clip rectangle position */ - clip_width = clip_width * item->canvas->pixels_per_unit; - clip_height = clip_height * item->canvas->pixels_per_unit; - - if (cx < text->clip_cx || - cx > text->clip_cx + clip_width || - cy < text->clip_cy || - cy > text->clip_cy + clip_height) - return 1; - - if (text->fill_clip_rectangle) - return 0; - - cx -= text->cx; - - if (pango_layout_xy_to_index (text->layout, cx, cy, NULL, NULL)) - return 0; - - return 1; -} - -/* Bounds handler for the text item */ -static void -e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) -{ - EText *text; - double width, height; - - text = E_TEXT (item); - - *x1 = 0; - *y1 = 0; - - width = text->width; - height = text->height; - - if (text->clip) { - if (text->clip_width >= 0) - width = text->clip_width; - if ( text->clip_height >= 0 ) - height = text->clip_height; - } - - width = width / item->canvas->pixels_per_unit; - height = height / item->canvas->pixels_per_unit; - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - *x1 -= width / 2.0; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - *x1 -= width; - break; - } - - switch (text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - *y1 -= height / 2.0; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - *y1 -= height; - break; - } - - *x2 = *x1 + width; - *y2 = *y1 + height; -} - -static gint -get_position_from_xy (EText *text, gint x, gint y) -{ - int index; - int trailing; - - if (text->draw_borders) { - x -= BORDER_INDENT; - y -= BORDER_INDENT; - } - - x -= text->xofs; - y -= text->yofs; - - if (text->editing) { - x += text->xofs_edit; - y += text->yofs_edit; - } - - x -= text->cx; - y -= text->cy; - - pango_layout_xy_to_index (text->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); - - return g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; -} - -#define SCROLL_WAIT_TIME 30000 - -static gboolean -_blink_scroll_timeout (gpointer data) -{ - EText *text = E_TEXT(data); - gulong current_time; - gboolean scroll = FALSE; - gboolean redraw = FALSE; - - g_timer_elapsed(text->timer, ¤t_time); - - if (text->scroll_start + SCROLL_WAIT_TIME > 1000000) { - if (current_time > text->scroll_start - (1000000 - SCROLL_WAIT_TIME) && - current_time < text->scroll_start) - scroll = TRUE; - } else { - if (current_time > text->scroll_start + SCROLL_WAIT_TIME || - current_time < text->scroll_start) - scroll = TRUE; - } - if (scroll && text->button_down && text->clip) { - int old_xofs_edit = text->xofs_edit; - int old_yofs_edit = text->yofs_edit; - - if (text->clip_cwidth >= 0 && - text->lastx - text->clip_cx > text->clip_cwidth && - text->xofs_edit < text->width - text->clip_cwidth) { - text->xofs_edit += 4; - if (text->xofs_edit > text->width - text->clip_cwidth + 1) - text->xofs_edit = text->width - text->clip_cwidth + 1; - } - if (text->lastx - text->clip_cx < 0 && - text->xofs_edit > 0) { - text->xofs_edit -= 4; - if (text->xofs_edit < 0) - text->xofs_edit = 0; - } - - if (text->clip_cheight >= 0 && - text->lasty - text->clip_cy > text->clip_cheight && - text->yofs_edit < text->height - text->clip_cheight) { - text->yofs_edit += 4; - if (text->yofs_edit > text->height - text->clip_cheight + 1) - text->yofs_edit = text->height - text->clip_cheight + 1; - } - if (text->lasty - text->clip_cy < 0 && - text->yofs_edit > 0) { - text->yofs_edit -= 4; - if (text->yofs_edit < 0) - text->yofs_edit = 0; - } - - if (old_xofs_edit != text->xofs_edit || - old_yofs_edit != text->yofs_edit) { - ETextEventProcessorEvent e_tep_event; - e_tep_event.type = GDK_MOTION_NOTIFY; - e_tep_event.motion.state = text->last_state; - e_tep_event.motion.time = 0; - e_tep_event.motion.position = get_position_from_xy(text, text->lastx, text->lasty); - _get_tep(text); - e_text_event_processor_handle_event (text->tep, - &e_tep_event); - text->scroll_start = current_time; - redraw = TRUE; - } - } - - if (!((current_time / 500000) % 2)) { - if (!text->show_cursor) - redraw = TRUE; - text->show_cursor = TRUE; - } else { - if (text->show_cursor) - redraw = TRUE; - text->show_cursor = FALSE; - } - if (redraw) { - text->needs_redraw = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); - } - return TRUE; -} - -static gboolean -tooltip_event(GtkWidget *tooltip, GdkEvent *event, EText *text) -{ - gint ret_val = FALSE; - - if (!text->model) - return FALSE; - - switch (event->type) { - case GDK_LEAVE_NOTIFY: - e_canvas_hide_tooltip (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas)); - break; - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - if (event->type == GDK_BUTTON_RELEASE) { - e_canvas_hide_tooltip (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas)); - } - /* Forward events to the text item */ - g_signal_emit_by_name (text, "event", event, - &ret_val); - if (!ret_val) - gtk_propagate_event (GTK_WIDGET(GNOME_CANVAS_ITEM(text)->canvas), event); - ret_val = TRUE; - default: - break; - } - return ret_val; -} - -static void -tooltip_destroy(gpointer data, GObject *where_object_was) -{ - EText *text = data; - text->tooltip_owner = FALSE; - g_object_unref (text); -} - -static gboolean -_do_tooltip (gpointer data) -{ - EText *text = E_TEXT (data); - struct line *lines; - GtkWidget *canvas; - int i; - gdouble max_width; - gboolean cut_off; - double i2c[6]; - ArtPoint origin = {0, 0}; - ArtPoint pixel_origin; - int canvas_x, canvas_y; - GnomeCanvasItem *tooltip_text; - double tooltip_width; - double tooltip_height; - double tooltip_x; - double tooltip_y; -#if 0 - double x1, x2, y1, y2; -#endif - GnomeCanvasItem *rect; - GtkWidget *tooltip_window; /* GtkWindow for displaying the tooltip */ - - text->tooltip_count = 0; - - lines = text->lines; - - if (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas)->tooltip_window || text->editing || (!lines)) { - text->tooltip_timeout = 0; - return FALSE; - } - - cut_off = FALSE; - for ( lines = text->lines, i = 0; i < text->num_lines; lines++, i++ ) { - if (lines->length > lines->ellipsis_length) { - cut_off = TRUE; - break; - } - } - if ( ! cut_off ) { - text->tooltip_timeout = 0; - return FALSE; - } - - gnome_canvas_item_i2c_affine(GNOME_CANVAS_ITEM(text), i2c); - art_affine_point (&pixel_origin, &origin, i2c); - - gdk_window_get_origin (GTK_WIDGET(GNOME_CANVAS_ITEM(text)->canvas)->window, &canvas_x, &canvas_y); - pixel_origin.x += canvas_x; - pixel_origin.y += canvas_y; - pixel_origin.x -= (int) gtk_layout_get_hadjustment(GTK_LAYOUT(GNOME_CANVAS_ITEM(text)->canvas))->value; - pixel_origin.y -= (int) gtk_layout_get_vadjustment(GTK_LAYOUT(GNOME_CANVAS_ITEM(text)->canvas))->value; - - tooltip_window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_container_set_border_width (GTK_CONTAINER (tooltip_window), 1); - - canvas = e_canvas_new (); - - gtk_container_add (GTK_CONTAINER (tooltip_window), canvas); - - /* Get the longest line length */ - max_width = 0.0; - for (lines = text->lines, i = 0; i < text->num_lines; lines++, i++) { - gdouble line_width; - - line_width = text_width_with_objects (text, text->font, text->style, lines->text, lines->length); - max_width = MAX (max_width, line_width); - } - - rect = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), - gnome_canvas_rect_get_type (), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) max_width + 4, - "y2", (double) text->height + 4, - "fill_color", "light gray", - NULL); - - tooltip_text = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)), - e_text_get_type (), - "anchor", GTK_ANCHOR_NW, - "bold", text->bold, - "strikeout", text->strikeout, - "font_e", text->font, - "text", text->text, - "editable", FALSE, - "clip_width", text->max_lines != 1 ? text->clip_width : max_width, - "clip_height", text->max_lines != 1 ? -1 : (double)text->height, - "clip", TRUE, - "line_wrap", text->line_wrap, - "justification", text->justification, - NULL); - - - - if (text->draw_borders) - e_canvas_item_move_absolute(tooltip_text, 1 + BORDER_INDENT, 1 + BORDER_INDENT); - else - e_canvas_item_move_absolute(tooltip_text, 1, 1); - - - split_into_lines (E_TEXT(tooltip_text)); - calc_height (E_TEXT(tooltip_text)); - calc_line_widths (E_TEXT(tooltip_text)); - gnome_canvas_item_set (tooltip_text, - "clip_height", (double) E_TEXT(tooltip_text)->height, - "clip_width", (double) E_TEXT(tooltip_text)->max_width, - NULL); - tooltip_width = E_TEXT(tooltip_text)->max_width; - tooltip_height = E_TEXT(tooltip_text)->height; - tooltip_x = 0; - tooltip_y = 0; - switch(E_TEXT(tooltip_text)->justification) { - case GTK_JUSTIFY_CENTER: - tooltip_x = - tooltip_width / 2; - break; - case GTK_JUSTIFY_RIGHT: - tooltip_x = tooltip_width / 2; - break; - case GTK_JUSTIFY_FILL: - case GTK_JUSTIFY_LEFT: - tooltip_x = 0; - break; - } - switch(text->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_N: - case GTK_ANCHOR_NE: - break; - - case GTK_ANCHOR_W: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_E: - tooltip_y -= tooltip_height / 2.0; - break; - - case GTK_ANCHOR_SW: - case GTK_ANCHOR_S: - case GTK_ANCHOR_SE: - tooltip_y -= tooltip_height; - break; - } - switch(E_TEXT(tooltip_text)->anchor) { - case GTK_ANCHOR_NW: - case GTK_ANCHOR_W: - case GTK_ANCHOR_SW: - break; - - case GTK_ANCHOR_N: - case GTK_ANCHOR_CENTER: - case GTK_ANCHOR_S: - tooltip_x -= tooltip_width / 2.0; - break; - - case GTK_ANCHOR_NE: - case GTK_ANCHOR_E: - case GTK_ANCHOR_SE: - tooltip_x -= tooltip_width; - break; - } - - gnome_canvas_item_set(rect, - "x2", (double) tooltip_width + 4 + (text->draw_borders ? BORDER_INDENT * 2 : 0), - "y2", (double) tooltip_height + 4 + (text->draw_borders ? BORDER_INDENT * 2 : 0), - NULL); - - gtk_widget_set_usize (tooltip_window, - tooltip_width + 4 + (text->draw_borders ? BORDER_INDENT * 2 : 0), - tooltip_height + 4 + (text->draw_borders ? BORDER_INDENT * 2 : 0)); - gnome_canvas_set_scroll_region (GNOME_CANVAS(canvas), 0.0, 0.0, - tooltip_width + (text->draw_borders ? BORDER_INDENT * 2 : 0), - (double)tooltip_height + (text->draw_borders ? BORDER_INDENT * 2 : 0)); - gtk_widget_show (canvas); - gtk_widget_realize (tooltip_window); - g_signal_connect (tooltip_window, "event", - G_CALLBACK(tooltip_event), text); - g_object_weak_ref (G_OBJECT (tooltip_window), - tooltip_destroy, text); - g_object_ref (text); - - e_canvas_popup_tooltip (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas), - tooltip_window, - pixel_origin.x - 2 + tooltip_x, - pixel_origin.y - 2 + tooltip_y); - text->tooltip_owner = TRUE; - - text->tooltip_timeout = 0; - return FALSE; -} - -static void -start_editing (EText *text) -{ - if (text->editing) - return; - - g_free (text->revert); - text->revert = g_strdup (text->text); - - text->editing = TRUE; - if (text->pointer_in) { - if (text->default_cursor_shown && (!text->draw_borders)) { - gdk_window_set_cursor (GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas)->window, text->i_cursor); - text->default_cursor_shown = FALSE; - } - } - text->select_by_word = FALSE; - text->xofs_edit = 0; - text->yofs_edit = 0; - if (text->timeout_id == 0) - text->timeout_id = g_timeout_add(10, _blink_scroll_timeout, text); - text->timer = g_timer_new(); - g_timer_elapsed(text->timer, &(text->scroll_start)); - g_timer_start(text->timer); -} - -void -e_text_stop_editing (EText *text) -{ - if (!text->editing) - return; - - g_free (text->revert); - text->revert = NULL; - - text->editing = FALSE; - if ( (!text->default_cursor_shown) && (!text->draw_borders) ) { - gdk_window_set_cursor (GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas)->window, text->default_cursor); - text->default_cursor_shown = TRUE; - } - if (text->timer) { - g_timer_stop(text->timer); - g_timer_destroy(text->timer); - text->timer = NULL; - } -} - -void -e_text_cancel_editing (EText *text) -{ - if (text->revert) - e_text_model_set_text(text->model, text->revert); - e_text_stop_editing (text); -} - -static gboolean -_click (gpointer data) -{ - *(gint *)data = 0; - return FALSE; -} - -static gint -e_text_event (GnomeCanvasItem *item, GdkEvent *event) -{ - EText *text = E_TEXT(item); - ETextEventProcessorEvent e_tep_event; - - gint return_val = 0; - - if (!text->model) - return FALSE; - - e_tep_event.type = event->type; - switch (event->type) { - case GDK_FOCUS_CHANGE: - if (text->editable) { - GdkEventFocus *focus_event; - focus_event = (GdkEventFocus *) event; - if (focus_event->in) { - start_editing (text); - } else { - e_text_stop_editing (text); - if (text->timeout_id) { - g_source_remove(text->timeout_id); - text->timeout_id = 0; - } - } - if ( text->line_wrap ) - text->needs_split_into_lines = 1; - else - text->needs_calc_line_widths = 1; - e_canvas_item_request_reflow (GNOME_CANVAS_ITEM(text)); - } - return_val = 0; - break; - case GDK_KEY_PRESS: /* Fall Through */ - case GDK_KEY_RELEASE: - if (text->editing) { - GdkEventKey key = event->key; - gint ret; - - e_tep_event.key.time = key.time; - e_tep_event.key.state = key.state; - e_tep_event.key.keyval = key.keyval; - - /* This is probably ugly hack, but we have to handle UTF-8 input somehow */ -#if 0 - e_tep_event.key.length = key.length; - e_tep_event.key.string = key.string; -#else - e_tep_event.key.string = e_utf8_from_gtk_event_key (GTK_WIDGET (item->canvas), key.keyval, key.string); - if (e_tep_event.key.string != NULL) { - e_tep_event.key.length = strlen (e_tep_event.key.string); - } else { - e_tep_event.key.length = 0; - } -#endif - _get_tep(text); - ret = e_text_event_processor_handle_event (text->tep, &e_tep_event); - - if (event->type == GDK_KEY_PRESS) - g_signal_emit (text, e_text_signals[E_TEXT_KEYPRESS], 0, - e_tep_event.key.keyval, e_tep_event.key.state); - - - if (e_tep_event.key.string) - g_free (e_tep_event.key.string); - - - return ret; - } - else - return 0; - break; - case GDK_BUTTON_PRESS: /* Fall Through */ - case GDK_BUTTON_RELEASE: - if (text->tooltip_timeout) { - gtk_timeout_remove (text->tooltip_timeout); - text->tooltip_timeout = 0; - } - e_canvas_hide_tooltip (E_CANVAS(GNOME_CANVAS_ITEM(text)->canvas)); -#if 0 - if ((!text->editing) - && text->editable - && event->type == GDK_BUTTON_RELEASE - && event->button.button == 1) { - GdkEventButton button = event->button; - - e_canvas_item_grab_focus (item, TRUE); - - e_tep_event.type = GDK_BUTTON_RELEASE; - e_tep_event.button.time = button.time; - e_tep_event.button.state = button.state; - e_tep_event.button.button = button.button; - e_tep_event.button.position = get_position_from_xy(text, button.x, button.y); - _get_tep(text); - return_val = e_text_event_processor_handle_event (text->tep, - &e_tep_event); - e_tep_event.type = GDK_BUTTON_RELEASE; - } -#else - if ((!text->editing) - && text->editable - && (event->button.button == 1 || - event->button.button == 2)) { - e_canvas_item_grab_focus (item, TRUE); - start_editing (text); - } -#endif - - /* We follow convention and emit popup events on right-clicks. */ - if (event->type == GDK_BUTTON_PRESS && event->button.button == 3) { - g_signal_emit (text, - e_text_signals[E_TEXT_POPUP], 0, - &(event->button), - get_position_from_xy (text, event->button.x, event->button.y)); - - break; - } - - /* Create our own double and triple click events, - as gnome-canvas doesn't forward them to us */ - if (event->type == GDK_BUTTON_PRESS) { - if (text->dbl_timeout == 0 && - text->tpl_timeout == 0) { - text->dbl_timeout = gtk_timeout_add (200, - _click, - &(text->dbl_timeout)); - } else { - if (text->tpl_timeout == 0) { - e_tep_event.type = GDK_2BUTTON_PRESS; - text->tpl_timeout = gtk_timeout_add (200, _click, &(text->tpl_timeout)); - } else { - e_tep_event.type = GDK_3BUTTON_PRESS; - } - } - } - - if (text->editing) { - GdkEventButton button = event->button; - e_tep_event.button.time = button.time; - e_tep_event.button.state = button.state; - e_tep_event.button.button = button.button; - e_tep_event.button.position = get_position_from_xy(text, button.x, button.y); - _get_tep(text); - return_val = e_text_event_processor_handle_event (text->tep, - &e_tep_event); - if (event->button.button == 1) { - if (event->type == GDK_BUTTON_PRESS) - text->button_down = TRUE; - else - text->button_down = FALSE; - } - text->lastx = button.x; - text->lasty = button.y; - text->last_state = button.state; - } - break; - case GDK_MOTION_NOTIFY: - if (text->editing) { - GdkEventMotion motion = event->motion; - e_tep_event.motion.time = motion.time; - e_tep_event.motion.state = motion.state; - e_tep_event.motion.position = get_position_from_xy(text, motion.x, motion.y); - _get_tep(text); - return_val = e_text_event_processor_handle_event (text->tep, - &e_tep_event); - text->lastx = motion.x; - text->lasty = motion.y; - text->last_state = motion.state; - } - break; - case GDK_ENTER_NOTIFY: - { -#if 0 - GdkEventCrossing *crossing = (GdkEventCrossing *) event; - double x1, y1, x2, y2; - split_into_lines (text); - calc_height (text); - calc_line_widths (text); - get_bounds (text, &x1, &y1, &x2, &y2); - if (crossing->x >= x1 && - crossing->y >= y1 && - crossing->x <= x2 && - crossing->y <= y2) { -#endif - if ( text->tooltip_count == 0 && text->clip) { - if (!text->tooltip_timeout) - text->tooltip_timeout = gtk_timeout_add (1000, _do_tooltip, text); - } - text->tooltip_count ++; -#if 0 - } -#endif - } - - text->pointer_in = TRUE; - if (text->editing || text->draw_borders) { - if ( text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->i_cursor); - text->default_cursor_shown = FALSE; - } - } - break; - case GDK_LEAVE_NOTIFY: - if (text->tooltip_count > 0) - text->tooltip_count --; - if ( text->tooltip_count == 0 && text->clip) { - if ( text->tooltip_timeout ) { - gtk_timeout_remove (text->tooltip_timeout); - text->tooltip_timeout = 0; - } - } - - text->pointer_in = FALSE; - if (text->editing || text->draw_borders) { - if ( ! text->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(item->canvas)->window, text->default_cursor); - text->default_cursor_shown = TRUE; - } - } - break; - default: - break; - } - if (return_val) - return return_val; - if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event) - return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event); - else - return 0; -} - -/* fixme: */ - -static int -next_word (EText *text, int start) -{ - char *p; - int length; - - length = strlen (text->text); - - if (start >= length) { - return length; - } else { - p = g_utf8_next_char (text->text + start); - - while (p && *p && g_unichar_validate (g_utf8_get_char (p))) { - gunichar unival = g_utf8_get_char (p); - if (g_unichar_isspace (unival)) { - return p - text->text; - } else - p = g_utf8_next_char (p); - } - } - - return p - text->text; -} - -static int -_get_position(EText *text, ETextEventProcessorCommand *command) -{ - int length, obj_num; - gunichar unival; - char *p = NULL; - gint new_pos = 0; - int index, trailing; - - switch (command->position) { - - case E_TEP_VALUE: - new_pos = command->value; - break; - - case E_TEP_SELECTION: - new_pos = text->selection_end; - break; - - case E_TEP_START_OF_BUFFER: - new_pos = 0; - break; - - case E_TEP_END_OF_BUFFER: - new_pos = strlen (text->text); - break; - - case E_TEP_START_OF_LINE: - - new_pos = 0; - - if (text->selection_end >= 1) { - - p = g_utf8_find_prev_char (text->text, text->text + text->selection_end); - if (p != text->text) { - p = g_utf8_find_prev_char (text->text, p); - - while (p && p > text->text && !new_pos) { - if (*p == '\n') - new_pos = p - text->text + 1; - p = g_utf8_find_prev_char (text->text, p); - } - } - } - - break; - - case E_TEP_END_OF_LINE: - new_pos = -1; - length = strlen (text->text); - - if (text->selection_end >= length) { - new_pos = length; - } else { - - p = g_utf8_next_char (text->text + text->selection_end); - - while (p && *p && g_unichar_validate (g_utf8_get_char (p))) { - if (*p == '\n') { - new_pos = p - text->text; - p = NULL; - } else - p = g_utf8_next_char (p); - } - } - - if (new_pos == -1) - new_pos = p - text->text; - - break; - - case E_TEP_FORWARD_CHARACTER: - length = strlen (text->text); - - if (text->selection_end >= length) { - new_pos = length; - } else { - p = g_utf8_next_char (text->text + text->selection_end); - new_pos = p - text->text; - } - - break; - - case E_TEP_BACKWARD_CHARACTER: - new_pos = 0; - if (text->selection_end >= 1) { - p = g_utf8_find_prev_char (text->text, text->text + text->selection_end); - - if (p != NULL) - new_pos = p - text->text; - } - - break; - - case E_TEP_FORWARD_WORD: - new_pos = next_word (text, text->selection_end); - break; - - case E_TEP_BACKWARD_WORD: - new_pos = 0; - if (text->selection_end >= 1) { - p = g_utf8_find_prev_char (text->text, text->text + text->selection_end); - if (p != text->text) { - p = g_utf8_find_prev_char (text->text, p); - - while (p && p > text->text && g_unichar_validate (g_utf8_get_char (p))) { - unival = g_utf8_get_char (p); - if (g_unichar_isspace (unival)) { - new_pos = g_utf8_next_char (p) - text->text; - p = NULL; - } else - p = g_utf8_find_prev_char (text->text, p); - } - } - } - - break; - - case E_TEP_FORWARD_LINE: - pango_layout_move_cursor_visually (text->layout, - TRUE, - text->selection_end, 0, - 1, - &index, &trailing); - index = g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; - if (index < 0) { - new_pos = 0; - } else { - length = strlen (text->text); - if (index >= length) - new_pos = length; - else - new_pos = index; - } - break; - - case E_TEP_BACKWARD_LINE: - pango_layout_move_cursor_visually (text->layout, - TRUE, - text->selection_end, 0, - -1, - &index, &trailing); - index = g_utf8_offset_to_pointer (text->text + index, trailing) - text->text; - if (index < 0) { - new_pos = 0; - } else { - length = strlen (text->text); - if (index >= length) - new_pos = length; - else - new_pos = index; - } - break; - - case E_TEP_SELECT_WORD: - - /* This is a silly hack to cause double-clicking on an object - to activate that object. - (Normally, double click == select word, which is why this is here.) */ - - obj_num = e_text_model_get_object_at_offset (text->model, text->selection_start); - if (obj_num != -1) { - e_text_model_activate_nth_object (text->model, obj_num); - new_pos = text->selection_start; - break; - } - - - if (text->selection_end < 1) { - new_pos = 0; - break; - } - - p = g_utf8_find_prev_char (text->text, text->text + text->selection_end); - if (p == text->text) { - new_pos = 0; - break; - } - p = g_utf8_find_prev_char (text->text, p); - - while (p && p > text->text && g_unichar_validate (g_utf8_get_char (p))) { - unival = g_utf8_get_char (p); - if (g_unichar_isspace (unival)) { - p = g_utf8_next_char (p); - break; - } - p = g_utf8_find_prev_char (text->text, p); - } - - if (!p) - text->selection_start = 0; - else - text->selection_start = p - text->text; - - - text->selection_start = e_text_model_validate_position (text->model, text->selection_start); - - length = strlen (text->text); - if (text->selection_end >= length) { - new_pos = length; - break; - } - - p = g_utf8_next_char (text->text + text->selection_end); - - while (p && *p && g_unichar_validate (g_utf8_get_char (p))) { - unival = g_utf8_get_char (p); - if (g_unichar_isspace (unival)) { - new_pos = p - text->text; - p = NULL; - } else - p = g_utf8_next_char (p); - } - - if (p) - new_pos = p - text->text; - - return new_pos; - - case E_TEP_SELECT_ALL: - text->selection_start = 0; - new_pos = strlen (text->text); - break; - - case E_TEP_FORWARD_PARAGRAPH: - case E_TEP_BACKWARD_PARAGRAPH: - - case E_TEP_FORWARD_PAGE: - case E_TEP_BACKWARD_PAGE: - new_pos = text->selection_end; - break; - - default: - new_pos = text->selection_end; - break; - } - - new_pos = e_text_model_validate_position (text->model, new_pos); - - return new_pos; -} - -static void -_delete_selection(EText *text) -{ - if ( text->selection_start < text->selection_end ) { - e_text_model_delete(text->model, text->selection_start, text->selection_end - text->selection_start); -#if 0 - text->selection_end = text->selection_start; -#endif - } else { - e_text_model_delete(text->model, text->selection_end, text->selection_start - text->selection_end); -#if 0 - text->selection_start = text->selection_end; -#endif - } -} - -static void -_insert(EText *text, char *string, int value) -{ - if (value > 0) { - if (!text->allow_newlines) { - char *i; - for (i = string; *i; i++) { - if (*i == '\n') { - char *new_string = g_malloc (strlen (string) + 1); - char *j = new_string; - for (i = string; *i; i++) { - if (*i != '\n') - *(j++) = *i; - } - *j = 0; - e_text_model_insert_length(text->model, text->selection_start, new_string, j - new_string); - g_free (new_string); - return; - } - } - } - e_text_model_insert_length(text->model, text->selection_start, string, value); - -#if 0 - text->selection_start += value; - text->selection_end = text->selection_start; -#endif - } -} - -static void -capitalize (EText *text, int start, int end, ETextEventProcessorCaps type) -{ - gboolean first = TRUE; - const char *p = text->text + start; - const char *text_end = text->text + end; - char *new_text = g_new0 (char, g_utf8_strlen (text->text + start, start - end) * 6); - char *output = new_text; - - while (p && *p && p < text_end && g_unichar_validate (g_utf8_get_char (p))) { - gunichar unival = g_utf8_get_char (p); - gunichar newval = unival; - - switch (type) { - case E_TEP_CAPS_UPPER: - newval = g_unichar_toupper (unival); - break; - case E_TEP_CAPS_LOWER: - newval = g_unichar_tolower (unival); - break; - case E_TEP_CAPS_TITLE: - if (g_unichar_isalpha (unival)) { - if (first) - newval = g_unichar_totitle (unival); - else - newval = g_unichar_tolower (unival); - first = FALSE; - } else { - first = TRUE; - } - break; - } - g_unichar_to_utf8 (newval, output); - output = g_utf8_next_char (output); - - p = g_utf8_next_char (p); - } - *output = 0; - - e_text_model_delete (text->model, start, end - start); - e_text_model_insert (text->model, start, new_text); - g_free (new_text); -} - -static void -e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data) -{ - EText *text = E_TEXT(data); - int sel_start, sel_end; - gboolean changed = TRUE; - - switch (command->action) { - case E_TEP_MOVE: - text->selection_start = _get_position(text, command); - text->selection_end = text->selection_start; - if (text->timer) { - g_timer_reset(text->timer); - } - - break; - case E_TEP_SELECT: - text->selection_start = e_text_model_validate_position (text->model, text->selection_start); /* paranoia */ - text->selection_end = _get_position(text, command); - - sel_start = MIN(text->selection_start, text->selection_end); - sel_end = MAX(text->selection_start, text->selection_end); - - sel_start = e_text_model_validate_position (text->model, sel_start); - - if (sel_start != sel_end) { - e_text_supply_selection (text, command->time, GDK_SELECTION_PRIMARY, - (guchar *) text->text + sel_start, sel_end - sel_start); - } else if (text->timer) { - g_timer_reset(text->timer); - } - - break; - case E_TEP_DELETE: - if (text->selection_end == text->selection_start) { - text->selection_end = _get_position(text, command); - } - _delete_selection(text); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - - case E_TEP_INSERT: - if (text->selection_end != text->selection_start) { - _delete_selection(text); - } - _insert(text, command->string, command->value); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_COPY: - sel_start = MIN(text->selection_start, text->selection_end); - sel_end = MAX(text->selection_start, text->selection_end); - if (sel_start != sel_end) { - e_text_supply_selection (text, command->time, clipboard_atom, - (guchar *) text->text + sel_start, sel_end - sel_start); - } - if (text->timer) { - g_timer_reset(text->timer); - } - changed = FALSE; - break; - case E_TEP_PASTE: - e_text_get_selection (text, clipboard_atom, command->time); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_GET_SELECTION: - e_text_get_selection (text, GDK_SELECTION_PRIMARY, command->time); - break; - case E_TEP_ACTIVATE: - g_signal_emit (text, e_text_signals[E_TEXT_ACTIVATE], 0); - if (text->timer) { - g_timer_reset(text->timer); - } - break; - case E_TEP_SET_SELECT_BY_WORD: - text->select_by_word = command->value; - break; - case E_TEP_GRAB: - e_canvas_item_grab (E_CANVAS (GNOME_CANVAS_ITEM(text)->canvas), - GNOME_CANVAS_ITEM(text), - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, - text->i_cursor, - command->time, - NULL, - NULL); - changed = FALSE; - break; - case E_TEP_UNGRAB: - e_canvas_item_ungrab (E_CANVAS (GNOME_CANVAS_ITEM(text)->canvas), - GNOME_CANVAS_ITEM(text), - command->time); - changed = FALSE; - break; - case E_TEP_CAPS: - if (text->selection_start == text->selection_end) { - capitalize (text, text->selection_start, next_word (text, text->selection_start), command->value); - } else { - int selection_start = MIN (text->selection_start, text->selection_end); - int selection_end = text->selection_start + text->selection_end - selection_start; /* Slightly faster than MAX */ - capitalize (text, selection_start, selection_end, command->value); - } - break; - case E_TEP_NOP: - changed = FALSE; - break; - } - - - if (changed && !text->button_down) { - PangoRectangle strong_pos, weak_pos; - - pango_layout_get_cursor_pos (text->layout, text->selection_end, &strong_pos, &weak_pos); - - if (strong_pos.x != weak_pos.x || - strong_pos.y != weak_pos.y || - strong_pos.width != weak_pos.width || - strong_pos.height != weak_pos.height) - show_pango_rectangle (text, weak_pos); - - show_pango_rectangle (text, strong_pos); - } - - text->needs_redraw = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); -} - -static void -_invisible_destroy (gpointer data, GObject *where_object_was) -{ - EText *text = E_TEXT (data); - text->invisible = NULL; -} - -static GtkWidget * -e_text_get_invisible(EText *text) -{ - GtkWidget *invisible; - if (text->invisible) { - invisible = text->invisible; - } else { - static const GtkTargetEntry targets[] = { - { "UTF8_STRING", 0, TARGET_UTF8_STRING }, - { "UTF-8", 0, TARGET_UTF8 }, - { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, - { "STRING", 0, TARGET_STRING }, - { "TEXT", 0, TARGET_TEXT } - }; - static const gint n_targets = sizeof(targets) / sizeof(targets[0]); - - invisible = gtk_invisible_new(); - text->invisible = invisible; - - gtk_selection_add_targets (invisible, - GDK_SELECTION_PRIMARY, - targets, n_targets); - gtk_selection_add_targets (invisible, - clipboard_atom, - targets, n_targets); - - g_signal_connect (invisible, "selection_get", - G_CALLBACK (_selection_get), - text); - g_signal_connect (invisible, "selection_clear_event", - G_CALLBACK (_selection_clear_event), - text); - g_signal_connect (invisible, "selection_received", - G_CALLBACK (_selection_received), - text); - - g_object_weak_ref (G_OBJECT (invisible), - _invisible_destroy, text); - } - return invisible; -} - -static void -_selection_clear_event (GtkInvisible *invisible, - GdkEventSelection *event, - EText *text) -{ - if (event->selection == GDK_SELECTION_PRIMARY) { - g_free (text->primary_selection); - text->primary_selection = NULL; - text->primary_length = 0; - - text->has_selection = FALSE; - text->needs_redraw = 1; - gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text)); - - } else if (event->selection == clipboard_atom) { - g_free (text->clipboard_selection); - text->clipboard_selection = NULL; - text->clipboard_length = 0; - } -} - -static void -_selection_get (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EText *text) -{ - char *selection_string; - int selection_length; - if (selection_data->selection == GDK_SELECTION_PRIMARY) { - selection_string = text->primary_selection; - selection_length = text->primary_length; - } else /* CLIPBOARD */ { - selection_string = text->clipboard_selection; - selection_length = text->clipboard_length; - } - - if (selection_string != NULL) { - if (info == TARGET_UTF8_STRING) { - gtk_selection_data_set (selection_data, - gdk_atom_intern ("UTF8_STRING", FALSE), 8, - (const guchar *) selection_string, - selection_length); - } else if (info == TARGET_UTF8) { - gtk_selection_data_set (selection_data, - gdk_atom_intern ("UTF-8", FALSE), 8, - (const guchar *) selection_string, - selection_length); - } else if (info == TARGET_STRING || info == TARGET_TEXT || info == TARGET_COMPOUND_TEXT) { - gchar *localized_string; - - localized_string = e_utf8_to_gtk_string (GTK_WIDGET (GNOME_CANVAS_ITEM(text)->canvas), - selection_string); - - if (info == TARGET_STRING) { - gtk_selection_data_set (selection_data, - GDK_SELECTION_TYPE_STRING, 8, - (const guchar *) localized_string, - strlen (localized_string)); - } else { - guchar *text; - GdkAtom encoding; - gint format; - gint new_length; - - gdk_string_to_compound_text (localized_string, - &encoding, &format, - &text, &new_length); - - gtk_selection_data_set (selection_data, - encoding, format, - text, new_length); - gdk_free_compound_text (text); - } - g_free (localized_string); - } - } -} - -typedef struct { - guint32 time; - GdkAtom selection; -} SelectionAndTime; - -static const char *formats[] = {"UTF8_STRING", "UTF-8", "STRING"}; -#define E_STRING_ATOM 2 -static const int format_count = sizeof (formats) / sizeof (formats[0]); -static GdkAtom atoms[sizeof (formats) / sizeof (formats[0])]; -static int initialized = FALSE; - -static inline void -init_atoms (void) -{ - int type; - if (!initialized) { - for (type = 0; type < format_count; type++) - atoms[type] = gdk_atom_intern (formats[type], FALSE); - initialized = TRUE; - } -} - -static void -e_text_request_paste (EText *text) -{ - GdkAtom format_atom; - GtkWidget *invisible; - int type = text->last_type_request; - - init_atoms (); - - format_atom = GDK_NONE; - - while (format_atom == GDK_NONE) { - type ++; - - if (type >= format_count) { - if (text->queued_requests) { - guint32 *new_time = text->queued_requests->data; - text->queued_requests = g_list_remove_link (text->queued_requests, text->queued_requests); - text->last_time_request = *new_time; - g_free (new_time); - - type = -1; - continue; - } else { - text->last_type_request = -1; - d(g_print ("Setting last_type_request to %d at line %d\n", text->last_type_request, __LINE__)); - text->last_time_request = 0; - return; - } - } - - format_atom = atoms [type]; - } - - /* This must come before the gtk_selection_convert because sometimes _selection_received is called reentrantly. */ - - text->last_type_request = type; - d(g_print ("Setting last_type_request to %d at line %d\n", text->last_type_request, __LINE__)); - - /* And request the format target for the required selection */ - invisible = e_text_get_invisible(text); - gtk_selection_convert(invisible, - text->last_selection_request, - format_atom, - text->last_time_request); - - return; -} - -static void -_selection_received (GtkInvisible *invisible, - GtkSelectionData *selection_data, - guint time, - EText *text) -{ - init_atoms (); - if (selection_data->length < 0) { - d(g_print ("Calling e_text_request_paste at line %d\n", __LINE__)); - e_text_request_paste (text); - return; - } else if (selection_data->type == atoms[E_STRING_ATOM]) { - ETextEventProcessorCommand command; - char *string; - - string = e_utf8_from_gtk_string_sized (GTK_WIDGET (GNOME_CANVAS_ITEM(text)->canvas), - selection_data->data, - selection_data->length); - command.action = E_TEP_INSERT; - command.position = E_TEP_SELECTION; - command.string = string; - command.value = strlen (string); - command.time = time; - e_text_command(text->tep, &command, text); - g_free (string); - } else { - ETextEventProcessorCommand command; - command.action = E_TEP_INSERT; - command.position = E_TEP_SELECTION; - command.string = selection_data->data; - command.value = selection_data->length; - command.time = time; - e_text_command(text->tep, &command, text); - } - - text->last_type_request = -1; - d(g_print ("Setting last_type_request to %d at line %d\n", text->last_type_request, __LINE__)); - if (text->queued_requests) { - SelectionAndTime *new_request = text->queued_requests->data; - text->queued_requests = g_list_remove_link (text->queued_requests, text->queued_requests); - text->last_time_request = new_request->time; - text->last_selection_request = new_request->selection; - g_free (new_request); - d(g_print ("Calling e_text_request_paste at line %d\n", __LINE__)); - e_text_request_paste (text); - } -} - -static void -e_text_get_selection(EText *text, GdkAtom selection, guint32 time) -{ - if (text->last_type_request == -1) { - text->last_time_request = time; - text->last_selection_request = selection; - d(g_print ("Calling e_text_request_paste at line %d\n", __LINE__)); - e_text_request_paste (text); - } else { - SelectionAndTime *new_request = g_new (SelectionAndTime, 1); - new_request->time = time; - new_request->selection = selection; - /* FIXME: Queue the selection request type as well. */ - text->queued_requests = g_list_append (text->queued_requests, new_request); - } -} - -static void -e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *data, gint length) -{ - gboolean successful; - GtkWidget *invisible; - - invisible = e_text_get_invisible(text); - - if (selection == GDK_SELECTION_PRIMARY ) { - g_free (text->primary_selection); - text->primary_selection = g_strndup(data, length); - text->primary_length = length; - } else if (selection == clipboard_atom) { - g_free (text->clipboard_selection); - text->clipboard_selection = g_strndup(data, length); - text->clipboard_length = length; - } - - successful = gtk_selection_owner_set (invisible, - selection, - time); - - if (selection == GDK_SELECTION_PRIMARY) - text->has_selection = successful; -} - -#if 0 -static void -e_text_real_copy_clipboard (EText *text) -{ - guint32 time; - gint selection_start_pos; - gint selection_end_pos; - - g_return_if_fail (text != NULL); - g_return_if_fail (E_IS_TEXT (text)); - - time = gtk_text_get_event_time (text); - selection_start_pos = MIN (text->selection_start, text->selection_end); - selection_end_pos = MAX (text->selection_start, text->selection_end); - - if (selection_start_pos != selection_end_pos) - { - if (gtk_selection_owner_set (GTK_WIDGET (text->canvas), - clipboard_atom, - time)) - text->clipboard_text = ""; - } -} - -static void -e_text_real_paste_clipboard (EText *text) -{ - guint32 time; - - g_return_if_fail (text != NULL); - g_return_if_fail (E_IS_TEXT (text)); - - time = e_text_get_event_time (text); - if (text->editable) - gtk_selection_convert (GTK_WIDGET(text->widget), - clipboard_atom, - gdk_atom_intern ("COMPOUND_TEXT", FALSE), time); -} -#endif - -/* Class initialization function for the text item */ -static void -e_text_class_init (ETextClass *klass) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - gobject_class = (GObjectClass *) klass; - object_class = (GtkObjectClass *) klass; - item_class = (GnomeCanvasItemClass *) klass; - - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->destroy = e_text_destroy; - gobject_class->set_property = e_text_set_property; - gobject_class->get_property = e_text_get_property; - - item_class->update = e_text_update; - item_class->realize = e_text_realize; - item_class->unrealize = e_text_unrealize; - item_class->draw = e_text_draw; - item_class->point = e_text_point; - item_class->bounds = e_text_bounds; - item_class->render = e_text_render; - item_class->event = e_text_event; - - klass->changed = NULL; - klass->activate = NULL; - - e_text_signals[E_TEXT_CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextClass, changed), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_text_signals[E_TEXT_ACTIVATE] = - g_signal_new ("activate", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextClass, activate), - NULL, NULL, - e_marshal_NONE__NONE, - G_TYPE_NONE, 0); - - e_text_signals[E_TEXT_KEYPRESS] = - g_signal_new ("keypress", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextClass, keypress), - NULL, NULL, - e_marshal_NONE__INT_INT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - e_text_signals[E_TEXT_POPUP] = - g_signal_new ("popup", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETextClass, popup), - NULL, NULL, - e_marshal_NONE__POINTER_INT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); - - g_object_class_install_property (gobject_class, PROP_MODEL, - g_param_spec_object ("model", - _( "Model" ), - _( "Model" ), - E_TYPE_TEXT_MODEL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_EVENT_PROCESSOR, - g_param_spec_object ("event_processor", - _( "Event Processor" ), - _( "Event Processor" ), - E_TEXT_EVENT_PROCESSOR_TYPE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_TEXT, - g_param_spec_string ("text", - _( "Text" ), - _( "Text" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FONT, - g_param_spec_string ("font", - _( "Font" ), - _( "Font" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FONTSET, - g_param_spec_string ("fontset", - _( "Fontset" ), - _( "Fontset" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FONT_GDK, - g_param_spec_boxed ("font_gdk", - _( "GDKFont" ), - _( "GDKFont" ), - GDK_TYPE_FONT, - G_PARAM_WRITABLE)); - - g_object_class_install_property (gobject_class, PROP_FONT_E, - g_param_spec_pointer ("font_e", - _( "EFont" ), - _( "EFont" ), - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_BOLD, - g_param_spec_boolean ("bold", - _( "Bold" ), - _( "Bold" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_STRIKEOUT, - g_param_spec_boolean ("strikeout", - _( "Strikeout" ), - _( "Strikeout" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_ANCHOR, - g_param_spec_enum ("anchor", - _( "Anchor" ), - _( "Anchor" ), - GTK_TYPE_ANCHOR_TYPE, GTK_ANCHOR_CENTER, - G_PARAM_READWRITE)); - - - g_object_class_install_property (gobject_class, PROP_JUSTIFICATION, - g_param_spec_enum ("justification", - _( "Justification" ), - _( "Justification" ), - GTK_TYPE_JUSTIFICATION, GTK_JUSTIFY_LEFT, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_CLIP_WIDTH, - g_param_spec_double ("clip_width", - _( "Clip Width" ), - _( "Clip Width" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_CLIP_HEIGHT, - g_param_spec_double ("clip_height", - _( "Clip Height" ), - _( "Clip Height" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_CLIP, - g_param_spec_boolean ("clip", - _( "Clip" ), - _( "Clip" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FILL_CLIP_RECTANGLE, - g_param_spec_boolean ("fill_clip_rectangle", - _( "Fill clip rectangle" ), - _( "Fill clip rectangle" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_X_OFFSET, - g_param_spec_double ("x_offset", - _( "X Offset" ), - _( "X Offset" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_Y_OFFSET, - g_param_spec_double ("y_offset", - _( "Y Offset" ), - _( "Y Offset" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FILL_COLOR, - g_param_spec_string ("fill_color", - _( "Fill color" ), - _( "Fill color" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FILL_COLOR_GDK, - g_param_spec_boxed ("fill_color_gdk", - _( "GDK fill color" ), - _( "GDK fill color" ), - GDK_TYPE_COLOR, - G_PARAM_READWRITE)); - - - g_object_class_install_property (gobject_class, PROP_FILL_COLOR_RGBA, - g_param_spec_uint ("fill_color_rgba", - _( "GDK fill color" ), - _( "GDK fill color" ), - 0, G_MAXUINT, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_FILL_STIPPLE, - g_param_spec_object ("fill_stipple", - _( "Fill stipple" ), - _( "FIll stipple" ), - GDK_TYPE_DRAWABLE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_TEXT_WIDTH, - g_param_spec_double ("text_width", - _( "Text width" ), - _( "Text width" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, PROP_TEXT_HEIGHT, - g_param_spec_double ("text_height", - _( "Text height" ), - _( "Text height" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE)); - - - g_object_class_install_property (gobject_class, PROP_EDITABLE, - g_param_spec_boolean ("editable", - _( "Editable" ), - _( "Editable" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_USE_ELLIPSIS, - g_param_spec_boolean ("use_ellipsis", - _( "Use ellipsis" ), - _( "Use ellipsis" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_ELLIPSIS, - g_param_spec_string ("ellipsis", - _( "Ellipsis" ), - _( "Ellipsis" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_LINE_WRAP, - g_param_spec_boolean ("line_wrap", - _( "Line wrap" ), - _( "Line wrap" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_BREAK_CHARACTERS, - g_param_spec_string ("break_characters", - _( "Break characters" ), - _( "Break characters" ), - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_MAX_LINES, - g_param_spec_int ("max_lines", - _( "Max lines" ), - _( "Max lines" ), - 0, G_MAXINT, 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_WIDTH, - g_param_spec_double ("width", - _( "Width" ), - _( "Width" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - - g_object_class_install_property (gobject_class, PROP_HEIGHT, - g_param_spec_double ("height", - _( "Height" ), - _( "Height" ), - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_DRAW_BORDERS, - g_param_spec_boolean ("draw_borders", - _( "Draw borders" ), - _( "Draw borders" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_ALLOW_NEWLINES, - g_param_spec_boolean ("allow_newlines", - _( "Allow newlines" ), - _( "Allow newlines" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_DRAW_BACKGROUND, - g_param_spec_boolean ("draw_background", - _( "Draw background" ), - _( "Draw background" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_DRAW_BUTTON, - g_param_spec_boolean ("draw_button", - _( "Draw button" ), - _( "Draw button" ), - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_CURSOR_POS, - g_param_spec_int ("cursor_pos", - _( "Cursor position" ), - _( "Cursor position" ), - 0, G_MAXINT, 0, - G_PARAM_READWRITE)); - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); -} - -/* Object initialization function for the text item */ -static void -e_text_init (EText *text) -{ - text->model = e_text_model_new (); - text->text = e_text_model_get_text (text->model); - text->layout = NULL; - - text->revert = NULL; - - text->model_changed_signal_id = - g_signal_connect (text->model, - "changed", - G_CALLBACK (e_text_text_model_changed), - text); - text->model_repos_signal_id = - g_signal_connect (text->model, - "reposition", - G_CALLBACK (e_text_text_model_reposition), - text); - - text->anchor = GTK_ANCHOR_CENTER; - text->justification = GTK_JUSTIFY_LEFT; - text->clip_width = -1.0; - text->clip_height = -1.0; - text->xofs = 0.0; - text->yofs = 0.0; - - text->ellipsis = NULL; - text->use_ellipsis = FALSE; - text->ellipsis_width = 0; - - text->editable = FALSE; - text->editing = FALSE; - text->xofs_edit = 0; - text->yofs_edit = 0; - - text->selection_start = 0; - text->selection_end = 0; - text->select_by_word = FALSE; - - text->timeout_id = 0; - text->timer = NULL; - - text->lastx = 0; - text->lasty = 0; - text->last_state = 0; - - text->scroll_start = 0; - text->show_cursor = TRUE; - text->button_down = FALSE; - - text->tep = NULL; - text->tep_command_id = 0; - - text->has_selection = FALSE; - - text->invisible = NULL; - text->primary_selection = NULL; - text->primary_length = 0; - text->clipboard_selection = NULL; - text->clipboard_length = 0; - - text->pointer_in = FALSE; - text->default_cursor_shown = TRUE; - text->line_wrap = FALSE; - text->break_characters = NULL; - text->max_lines = -1; - text->tooltip_timeout = 0; - text->tooltip_count = 0; - text->tooltip_owner = FALSE; - text->dbl_timeout = 0; - text->tpl_timeout = 0; - - text->draw_background = FALSE; - text->draw_button = FALSE; - - text->bold = FALSE; - text->strikeout = FALSE; - - text->style = E_FONT_PLAIN; - text->allow_newlines = TRUE; - - text->last_type_request = -1; - d(g_print ("Setting last_type_request to %d at line %d\n", text->last_type_request, __LINE__)); - text->last_time_request = 0; - text->queued_requests = NULL; - - e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(text), e_text_reflow); -} - -/** - * e_text_get_type: - * @void: - * - * Registers the &EText class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the &EText class. - **/ -E_MAKE_TYPE (e_text, - "EText", - EText, - e_text_class_init, - e_text_init, - PARENT_TYPE) diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h deleted file mode 100644 index 9529962c37..0000000000 --- a/widgets/text/e-text.h +++ /dev/null @@ -1,275 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-text.h - Text item for evolution. - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * Jon Trowbridge <trow@ximian.com> - * - * A majority of code taken from: - * - * Text item type for GnomeCanvas widget - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent - * canvas widget. Tk is copyrighted by the Regents of the University - * of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998 The Free Software Foundation - * - * Author: Federico Mena <federico@nuclecu.unam.mx> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#ifndef E_TEXT_H -#define E_TEXT_H - -#include <gtk/gtkobject.h> - -#include <gal/widgets/e-font.h> -#include <gal/util/e-text-event-processor.h> -#include <gal/e-text/e-text-model.h> -#include <gal/widgets/e-canvas.h> - -G_BEGIN_DECLS - - -/* Text item for the canvas. Text items are positioned by an anchor point and an anchor direction. - * - * A clipping rectangle may be specified for the text. The rectangle is anchored at the text's anchor - * point, and is specified by clipping width and height parameters. If the clipping rectangle is - * enabled, it will clip the text. - * - * In addition, x and y offset values may be specified. These specify an offset from the anchor - * position. If used in conjunction with the clipping rectangle, these could be used to implement - * simple scrolling of the text within the clipping rectangle. - * - * The following object arguments are available: - * - * name type read/write description - * ------------------------------------------------------------------------------------------ - * text string RW The string of the text label - * font string W X logical font descriptor - * fontset string W X logical fontset descriptor - * font_gdk GdkFont* RW Pointer to a GdkFont - * bold boolean RW Bold? - * anchor GtkAnchorType RW Anchor side for the text - * justification GtkJustification RW Justification for multiline text - * fill_color string W X color specification for text - * fill_color_gdk GdkColor* RW Pointer to an allocated GdkColor - * fill_stipple GdkBitmap* RW Stipple pattern for filling the text - * clip_width double RW Width of clip rectangle - * clip_height double RW Height of clip rectangle - * clip boolean RW Use clipping rectangle? - * fill_clip_rect boolean RW Whether the text item represents itself as being the size of the clipping rectangle. - * x_offset double RW Horizontal offset distance from anchor position - * y_offset double RW Vertical offset distance from anchor position - * text_width double R Used to query the width of the rendered text - * text_height double R Used to query the rendered height of the text - * width double RW A synonym for clip_width - * height double R A synonym for text_height - * - * These are currently ignored in the AA version: - * editable boolean RW Can this item be edited - * use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false. - * ellipsis string RW The characters to use as ellipsis. NULL = "...". - * line_wrap boolean RW Line wrap when not editing. - * break_characters string RW List of characters to optionally break on. - * max_lines int RW Number of lines possible when doing line wrap. - * draw_borders boolean RW Whether to draw borders. - * draw_background boolean RW Whether to draw the background. - * draw_button boolean RW This makes EText handle being the child of a button properly and highlighting as it should. - */ - -#define E_TYPE_TEXT (e_text_get_type ()) -#define E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_TEXT, EText)) -#define E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_TEXT, ETextClass)) -#define E_IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_TEXT)) -#define E_IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_TEXT)) - - -typedef struct _EText EText; -typedef struct _ETextClass ETextClass; - -#if 0 -typedef struct _ETextSuckFont ETextSuckFont; -typedef struct _ETextSuckChar ETextSuckChar; - -struct _ETextSuckChar { - int left_sb; - int right_sb; - int width; - int ascent; - int descent; - int bitmap_offset; /* in pixels */ -}; - -struct _ETextSuckFont { - guchar *bitmap; - gint bitmap_width; - gint bitmap_height; - gint ascent; - ETextSuckChar chars[256]; -}; -#endif - -struct _EText { - GnomeCanvasItem item; - - ETextModel *model; - gint model_changed_signal_id; - gint model_repos_signal_id; - - const gchar *text; /* Text to display --- from the ETextModel */ - PangoLayout *layout; - gpointer lines; /* Text split into lines (private field) */ - int num_lines; /* Number of lines of text */ - - gchar *revert; /* Text to revert to */ - -#if 0 - GdkFont *font; /* Font for text */ -#else - EFont *font; -#endif - GtkAnchorType anchor; /* Anchor side for text */ - GtkJustification justification; /* Justification for text */ - - double clip_width; /* Width of optional clip rectangle */ - double clip_height; /* Height of optional clip rectangle */ - - double xofs, yofs; /* Text offset distance from anchor position */ - - GdkColor color; /* Fill color */ - GdkBitmap *stipple; /* Stipple for text */ - GdkGC *gc; /* GC for drawing text */ - - int cx, cy; /* Top-left canvas coordinates for text */ - int text_cx, text_cy; /* Top-left canvas coordinates for text */ - int clip_cx, clip_cy; /* Top-left canvas coordinates for clip rectangle */ - int clip_cwidth, clip_cheight; /* Size of clip rectangle in pixels */ - int max_width; /* Maximum width of text lines */ - int width; /* Rendered text width in pixels */ - int height; /* Rendered text height in pixels */ - - /* Antialiased specific stuff follows */ -#if 0 - ETextSuckFont *suckfont; /* Sucked font */ -#endif - guint32 rgba; /* RGBA color for text */ - double affine[6]; /* The item -> canvas affine */ - - char *ellipsis; /* The ellipsis characters. NULL = "...". */ - double ellipsis_width; /* The width of the ellipsis. */ - - int xofs_edit; /* Offset because of editing */ - int yofs_edit; /* Offset because of editing */ - - /* This needs to be reworked a bit once we get line wrapping. */ - int selection_start; /* Start of selection IN BYTES */ - int selection_end; /* End of selection IN BYTES */ - gboolean select_by_word; /* Current selection is by word */ - - /* This section is for drag scrolling and blinking cursor. */ - gint timeout_id; /* Current timeout id for scrolling */ - GTimer *timer; /* Timer for blinking cursor and scrolling */ - - gint lastx, lasty; /* Last x and y motion events */ - gint last_state; /* Last state */ - gulong scroll_start; /* Starting time for scroll (microseconds) */ - - gint show_cursor; /* Is cursor currently shown */ - gboolean button_down; /* Is mouse button 1 down */ - - ETextEventProcessor *tep; /* Text Event Processor */ - gint tep_command_id; - - GtkWidget *invisible; /* For selection handling */ - gboolean has_selection; /* TRUE if we have the selection */ - gchar *primary_selection; /* Primary selection text */ - gint primary_length; /* Primary selection text length */ - gchar *clipboard_selection; /* Clipboard selection text */ - gint clipboard_length; /* Clipboard selection text length*/ - - guint clip : 1; /* Use clip rectangle? */ - guint fill_clip_rectangle : 1; /* Fill the clipping rectangle. */ - - guint pointer_in : 1; /* Is the pointer currently over us? */ - guint default_cursor_shown : 1; /* Is the default cursor currently shown? */ - guint draw_borders : 1; /* Draw borders? */ - guint draw_background : 1; /* Draw background? */ - guint draw_button : 1; /* Draw button? */ - - guint line_wrap : 1; /* Do line wrap */ - - guint needs_redraw : 1; /* Needs redraw */ - guint needs_recalc_bounds : 1; /* Need recalc_bounds */ - guint needs_calc_height : 1; /* Need calc_height */ - guint needs_calc_line_widths : 1; /* Needs calc_line_widths */ - guint needs_split_into_lines : 1; /* Needs split_into_lines */ - guint needs_reset_layout : 1; /* Needs split_into_lines */ - - guint bold : 1; - guint strikeout : 1; - - guint tooltip_owner : 1; - guint allow_newlines : 1; - - guint use_ellipsis : 1; /* Whether to use the ellipsis. */ - - guint editable : 1; /* Item is editable */ - guint editing : 1; /* Item is currently being edited */ - - EFontStyle style; - - gchar *break_characters; /* Characters to optionally break after */ - - gint max_lines; /* Max number of lines (-1 = infinite) */ - - GdkCursor *default_cursor; /* Default cursor (arrow) */ - GdkCursor *i_cursor; /* I beam cursor */ - - gint tooltip_timeout; /* Timeout for the tooltip */ - gint tooltip_count; /* GDK_ENTER_NOTIFY count. */ - - gint dbl_timeout; /* Double click timeout */ - gint tpl_timeout; /* Triple click timeout */ - - gint last_type_request; /* Last selection type requested. */ - guint32 last_time_request; /* The time of the last selection request. */ - GdkAtom last_selection_request; /* The time of the last selection request. */ - GList *queued_requests; /* Queued selection requests. */ -}; - -struct _ETextClass { - GnomeCanvasItemClass parent_class; - - void (* changed) (EText *text); - void (* activate) (EText *text); - void (* keypress) (EText *text, guint keyval, guint state); - void (* popup) (EText *text, GdkEventButton *ev, gint pos); - void (* style_set) (EText *text, GtkStyle *previous_style); -}; - - -/* Standard Gtk function */ -GtkType e_text_get_type (void); -void e_text_cancel_editing (EText *text); -void e_text_stop_editing (EText *text); - -G_END_DECLS - -#endif |