aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/text/e-text-model.c
diff options
context:
space:
mode:
authorJon Trowbridge <trow@ximian.com>2001-02-20 06:47:23 +0800
committerJon Trowbridge <trow@src.gnome.org>2001-02-20 06:47:23 +0800
commit0e3e3e99143b969db1e40d72a0806f5dec5f329b (patch)
tree48dc3b060dae38c762ab0b766efd972e74261c0c /widgets/text/e-text-model.c
parentd6a9790072afc82d29e046f98b7223dc618bf9a6 (diff)
downloadgsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar.gz
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar.bz2
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar.lz
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar.xz
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.tar.zst
gsoc2013-evolution-0e3e3e99143b969db1e40d72a0806f5dec5f329b.zip
Added. Allows you to attach an ECompletion to an EEntry, and have that
2001-02-19 Jon Trowbridge <trow@ximian.com> * gal/e-text/e-entry.c (e_entry_enable_completion_full): Added. Allows you to attach an ECompletion to an EEntry, and have that ECompletion be used for (obviously enough) completions. * gal/e-text/e-completion-view.h, gal/e-text/e-completion-view.c: Added. ECompletionView is a widget for displaying the results of a completion request in a format that is appropriate for a drop-down window. * gal/e-text/e-completion.h, gal/e-text/e-completion.c: Added. ECompletion is a "pure virtual base class" for completion-type operations. It is implemented so that completions can be either synchronous or asynchronous. * gal/e-text/e-text.c: Lots of changes to accomodate the ETextModel changes. First of all, we render embedded text objects as being underlined. We also cause the model to emit the appropriate object activation signal when an embedded object is double-clicked. Also, all of the code that moves the cursor in response to user input has been removed. Instead, the EText now listens for "reposition" events from the underlying model, and bases all cursor motions on those. (get_bounds_item_relative): Fixed bug in the handling of differently-anchored text. Being differently-anchored is not a crime or a perversion --- it is an alternative lifestyle that we have to respect. * gal/e-text/e-text-model-uri.h, gal/e-text/e-text-model-uri.c: A sample ETextModel that converts URIs into embedded objects that get opened in the browser when you double-click them. * gal/e-text/e-text-model-repos.h, gal/e-text/e-text-model-repos.c: Added. A group of simple structures & functions for handling various cursor movement rules. These are the sorts of things that are passed as arguments to ETextModel "reposition" event handlers. * gal/e-text/e-text-model.h, gal/e-text/e-text-model.c: Privitized the ETextModel struct and "methodized" all of the operations, so that derived classes can do arbitrarily respond to get/set requests in arbitrarily strange ways. Also added the concept of declaring regions of the text as "embedded text objects". Finally, caused operations that change the text to emit a "reposition" signal that passes information that can be used by a view (like an EText) to move the cursor or selection in an intelligent way in response to those changes. This means that you can now open two ETexts that look at the same ETextModel, and have the cursor in one do the right thing when you edit the other. (As opposed to producing a lot of potential segfaults, as it was before.) svn path=/trunk/; revision=8280
Diffstat (limited to 'widgets/text/e-text-model.c')
-rw-r--r--widgets/text/e-text-model.c520
1 files changed, 366 insertions, 154 deletions
diff --git a/widgets/text/e-text-model.c b/widgets/text/e-text-model.c
index acd08ecb04..5eccaff9fb 100644
--- a/widgets/text/e-text-model.c
+++ b/widgets/text/e-text-model.c
@@ -16,31 +16,40 @@
*
* Author: Federico Mena <federico@nuclecu.unam.mx> */
+#undef PARANOID_DEBUGGING
+
#include <config.h>
#include <ctype.h>
+#include "e-text-model-repos.h"
#include "e-text-model.h"
+#define CLASS(obj) (E_TEXT_MODEL_CLASS (GTK_OBJECT (obj)->klass))
+
enum {
E_TEXT_MODEL_CHANGED,
+ E_TEXT_MODEL_REPOSITION,
+ E_TEXT_MODEL_OBJECT_ACTIVATED,
E_TEXT_MODEL_LAST_SIGNAL
};
static guint e_text_model_signals[E_TEXT_MODEL_LAST_SIGNAL] = { 0 };
-static void e_text_model_class_init (ETextModelClass *class);
-static void e_text_model_init (ETextModel *model);
-static void e_text_model_destroy (GtkObject *object);
-
-static gchar *e_text_model_real_get_text(ETextModel *model);
-static void e_text_model_real_set_text(ETextModel *model, gchar *text);
-static void e_text_model_real_insert(ETextModel *model, gint postion, gchar *text);
-static void e_text_model_real_insert_length(ETextModel *model, gint postion, gchar *text, gint length);
-static void e_text_model_real_delete(ETextModel *model, gint postion, gint length);
+struct _ETextModelPrivate {
+ gchar *text;
+ gint len;
+};
-static gint e_text_model_real_object_count(ETextModel *model);
-static const gchar *e_text_model_real_get_nth_object(ETextModel *model, gint n);
-static void e_text_model_real_activate_nth_object(ETextModel *mode, gint n);
+static void e_text_model_class_init (ETextModelClass *class);
+static void e_text_model_init (ETextModel *model);
+static void e_text_model_destroy (GtkObject *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);
static GtkObject *parent_class;
@@ -95,18 +104,45 @@ e_text_model_class_init (ETextModelClass *klass)
GTK_SIGNAL_OFFSET (ETextModelClass, changed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
+
+ e_text_model_signals[E_TEXT_MODEL_REPOSITION] =
+ gtk_signal_new ("reposition",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETextModelClass, reposition),
+ gtk_marshal_NONE__POINTER_POINTER,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_POINTER, GTK_TYPE_POINTER);
+
+ e_text_model_signals[E_TEXT_MODEL_OBJECT_ACTIVATED] =
+ gtk_signal_new ("object_activated",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (ETextModelClass, object_activated),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, e_text_model_signals, E_TEXT_MODEL_LAST_SIGNAL);
- klass->changed = NULL;
- klass->get_text = e_text_model_real_get_text;
- klass->set_text = e_text_model_real_set_text;
- klass->insert = e_text_model_real_insert;
+ /* 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;
- klass->obj_count = e_text_model_real_object_count;
- klass->get_nth_obj = e_text_model_real_get_nth_object;
- klass->activate_nth_obj = e_text_model_real_activate_nth_object;
+ 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->destroy = e_text_model_destroy;
}
@@ -115,7 +151,9 @@ e_text_model_class_init (ETextModelClass *klass)
static void
e_text_model_init (ETextModel *model)
{
- model->text = NULL;
+ model->priv = g_new0 (struct _ETextModelPrivate, 1);
+ model->priv->text = g_strdup ("");
+ model->priv->len = 0;
}
/* Destroy handler for the text item */
@@ -129,250 +167,424 @@ e_text_model_destroy (GtkObject *object)
model = E_TEXT_MODEL (object);
- if (model->text)
- g_free (model->text);
+ g_free (model->priv->text);
+
+ g_free (model->priv);
+ model->priv = NULL;
if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
-static gchar *
-e_text_model_real_get_text(ETextModel *model)
+static gint
+e_text_model_real_validate_position (ETextModel *model, gint pos)
{
- if (model->text)
- return model->text;
+ 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 void
-e_text_model_real_set_text(ETextModel *model, gchar *text)
+static gint
+e_text_model_real_get_text_length (ETextModel *model)
{
- if (model->text)
- g_free(model->text);
- model->text = g_strdup(text);
- e_text_model_changed(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_insert(ETextModel *model, gint position, gchar *text)
+e_text_model_real_set_text (ETextModel *model, const gchar *text)
{
- gchar *temp = g_strdup_printf("%.*s%s%s", position, model->text, text, model->text + position);
- if (model->text)
- g_free(model->text);
- model->text = temp;
- e_text_model_changed(model);
+ 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_strdup (text);
+ 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_length(ETextModel *model, gint position, gchar *text, gint length)
+e_text_model_real_insert (ETextModel *model, gint position, const gchar *text)
{
- gchar *temp = g_strdup_printf("%.*s%.*s%s", position, model->text, length, text, model->text + position);
- if (model->text)
- g_free(model->text);
- model->text = temp;
- e_text_model_changed(model);
+ EReposInsertShift repos;
+ gchar *temp;
+ gint ins_len;
+
+ temp = g_strdup_printf ("%.*s%s%s", position, model->priv->text, text, model->priv->text + position);
+ ins_len = strlen (text);
+
+ if (model->priv->text)
+ g_free (model->priv->text);
+
+ model->priv->text = temp;
+
+ if (model->priv->len >= 0)
+ model->priv->len += ins_len;
+
+ e_text_model_changed (model);
+
+ repos.model = model;
+ repos.pos = position;
+ repos.len = ins_len;
+
+ e_text_model_reposition (model, e_repos_insert_shift, &repos);
}
static void
-e_text_model_real_delete(ETextModel *model, gint position, gint length)
+e_text_model_real_insert_length (ETextModel *model, gint position, const gchar *text, gint length)
{
- memmove(model->text + position, model->text + position + length, strlen(model->text + position + length) + 1);
- e_text_model_changed(model);
-}
+ EReposInsertShift repos;
+ gchar *temp = g_strdup_printf ("%.*s%.*s%s", position, model->priv->text, length, text, model->priv->text + position);
-static gint
-e_text_model_real_object_count(ETextModel *model)
-{
- gint count = 0;
- gchar *c = model->text;
-
- if (c) {
- while (*c) {
- if (*c == '\1')
- ++count;
- ++c;
- }
- }
- return count;
+ if (model->priv->text)
+ g_free (model->priv->text);
+ model->priv->text = temp;
+
+ 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 const gchar *
-e_text_model_real_get_nth_object(ETextModel *model, gint n)
+static void
+e_text_model_real_delete (ETextModel *model, gint position, gint length)
{
- return "";
+ 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);
}
-static void
-e_text_model_real_activate_nth_object(ETextModel *model, gint n)
+void
+e_text_model_changed (ETextModel *model)
{
- /* By default, do nothing */
+ 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 (CLASS (model)->objectify)
+ CLASS (model)->objectify (model);
+
+ gtk_signal_emit (GTK_OBJECT (model),
+ e_text_model_signals[E_TEXT_MODEL_CHANGED]);
}
void
-e_text_model_changed(ETextModel *model)
+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);
gtk_signal_emit (GTK_OBJECT (model),
- e_text_model_signals [E_TEXT_MODEL_CHANGED]);
+ e_text_model_signals[E_TEXT_MODEL_REPOSITION],
+ fn, repos_data);
}
-gchar *
-e_text_model_get_text(ETextModel *model)
+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 (CLASS (model)->validate_pos)
+ pos = 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_CLASS(GTK_OBJECT(model)->klass)->get_text )
- return E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->get_text(model);
- else
- return "";
+ if (CLASS (model)->get_text)
+ return 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 (CLASS (model)->get_text_len (model)) {
+
+ gint len = 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 (CLASS (model)->set_text)
+ 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 (CLASS (model)->insert)
+ CLASS (model)->insert (model, position, text);
}
void
-e_text_model_set_text(ETextModel *model, gchar *text)
+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_CLASS(GTK_OBJECT(model)->klass)->set_text )
- E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->set_text(model, text);
+ if (CLASS (model)->insert_length)
+ CLASS (model)->insert_length (model, position, text, length);
}
void
-e_text_model_insert(ETextModel *model, gint position, gchar *text)
+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 ( E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->insert )
- E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->insert(model, position, text);
+ if (text == NULL)
+ return;
+
+ e_text_model_insert (model, 0, text);
}
void
-e_text_model_insert_length(ETextModel *model, gint position, gchar *text, gint length)
+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 ( E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->insert_length )
- E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->insert_length(model, position, text, length);
+ 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)
+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_CLASS(GTK_OBJECT(model)->klass)->delete )
- E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->delete(model, position, length);
+ if (CLASS (model)->delete)
+ CLASS (model)->delete (model, position, length);
}
gint
-e_text_model_object_count(ETextModel *model)
+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_CLASS(GTK_OBJECT(model)->klass)->obj_count)
- return E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->obj_count(model);
- else
- return 0;
+ if (CLASS (model)->obj_count)
+ return CLASS (model)->obj_count (model);
+
+ return 0;
}
const gchar *
-e_text_model_get_nth_object(ETextModel *model, gint n)
+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);
- g_return_val_if_fail (n >= 0, NULL);
- if ( E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->get_nth_obj )
- return E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->get_nth_obj(model, n);
- else
- return "";
-}
+ if (n < 0 || n >= e_text_model_object_count (model))
+ return NULL;
-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);
+ if (CLASS (model)->get_nth_obj)
+ return CLASS (model)->get_nth_obj (model, n, len);
- if ( E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->activate_nth_obj )
- E_TEXT_MODEL_CLASS(GTK_OBJECT(model)->klass)->activate_nth_obj(model, n);
+ return NULL;
}
gchar *
-e_text_model_strdup_expanded_text(ETextModel *model)
+e_text_model_strdup_nth_object (ETextModel *model, gint n)
{
- gint len = 0, i, N;
- gchar *expanded, *dest;
- const gchar *src;
+ 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);
- if (model->text == NULL)
- return NULL;
+ obj = e_text_model_get_nth_object (model, n, &len);
+
+ return obj ? g_strndup (obj, n) : NULL;
+}
- N = e_text_model_object_count (model);
- if (N == 0)
- return g_strdup (model->text);
+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;
- /* First, compute the length of the expanded string. */
+ g_return_if_fail (model != NULL);
+ g_return_if_fail (E_IS_TEXT_MODEL (model));
- len = strlen (model->text);
- len -= N; /* Subtract out the \1s that signify the objects. */
+ txt = e_text_model_get_text (model);
+ obj = e_text_model_get_nth_object (model, n, &len);
- for (i=0; i<N; ++i)
- len += strlen (e_text_model_get_nth_object (model ,i));
-
+ g_return_if_fail (obj != NULL);
- /* Next, allocate and build the expanded string. */
- expanded = g_new0 (gchar, len+1);
+ if (start)
+ *start = obj - txt;
+ if (end)
+ *end = obj - txt + len;
+}
- src = model->text;
- dest = expanded;
- i = 0;
- while (*src) {
- if (*src == '\1') {
- const gchar *src_obj;
-
- g_assert (i < N);
- src_obj = e_text_model_get_nth_object (model, i);
-
- if (src_obj) {
- while (*src_obj) {
- *dest = *src_obj;
- ++src_obj;
- ++dest;
- }
- }
-
- ++src;
- ++i;
+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 (CLASS (model)->obj_at_offset) {
+
+ return CLASS (model)->obj_at_offset (model, offset);
+
+ } else {
+ /* If not, we fake it.*/
- } else {
+ gint i, N, pos0, pos1;
- *dest = *src;
- ++src;
- ++dest;
+ 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 expanded;
+ 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));
+
+ gtk_signal_emit (GTK_OBJECT (model), e_text_model_signals[E_TEXT_MODEL_OBJECT_ACTIVATED], n);
}
ETextModel *
-e_text_model_new(void)
+e_text_model_new (void)
{
ETextModel *model = gtk_type_new (e_text_model_get_type ());
- model->text = g_strdup("");
return model;
}