aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/text/e-text.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.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.c')
-rw-r--r--widgets/text/e-text.c570
1 files changed, 314 insertions, 256 deletions
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c
index 8edd06ca07..73cffd8579 100644
--- a/widgets/text/e-text.c
+++ b/widgets/text/e-text.c
@@ -46,11 +46,10 @@ static guint e_text_signals[E_TEXT_LAST_SIGNAL] = { 0 };
/* This defines a line of text */
struct line {
- char *text; /* Line's text, it is a pointer into the text->text string */
+ 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 */
- gint first_obj; /* First embedded object number */
};
/* Object argument IDs */
@@ -128,6 +127,7 @@ 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);
@@ -152,9 +152,9 @@ static void e_suck_font_free (ETextSuckFont *suckfont);
static void e_text_free_lines(EText *text);
-static gint text_width_with_objects (ETextModel *model, gint first_object,
+static gint text_width_with_objects (ETextModel *model,
EFont *font, EFontStyle style,
- gchar *text, gint bytelen);
+ const gchar *text, gint bytelen);
static void calc_height (EText *text);
static void calc_line_widths (EText *text);
@@ -321,16 +321,22 @@ e_text_class_init (ETextClass *klass)
static void
e_text_init (EText *text)
{
- text->model = e_text_model_new();
+ text->model = e_text_model_new ();
text->text = e_text_model_get_text (text->model);
- gtk_object_ref (GTK_OBJECT(text->model));
- gtk_object_sink (GTK_OBJECT(text->model));
+ gtk_object_ref (GTK_OBJECT (text->model));
+ gtk_object_sink (GTK_OBJECT (text->model));
+
text->model_changed_signal_id =
- gtk_signal_connect(GTK_OBJECT(text->model),
+ gtk_signal_connect (GTK_OBJECT (text->model),
"changed",
- GTK_SIGNAL_FUNC(e_text_text_model_changed),
- text);
+ GTK_SIGNAL_FUNC (e_text_text_model_changed),
+ text);
+ text->model_repos_signal_id =
+ gtk_signal_connect (GTK_OBJECT (text->model),
+ "reposition",
+ GTK_SIGNAL_FUNC (e_text_text_model_reposition),
+ text);
text->anchor = GTK_ANCHOR_CENTER;
text->justification = GTK_JUSTIFY_LEFT;
@@ -404,8 +410,12 @@ e_text_destroy (GtkObject *object)
text = E_TEXT (object);
if (text->model_changed_signal_id)
- gtk_signal_disconnect(GTK_OBJECT(text->model),
- text->model_changed_signal_id);
+ gtk_signal_disconnect (GTK_OBJECT (text->model),
+ text->model_changed_signal_id);
+
+ if (text->model_repos_signal_id)
+ gtk_signal_disconnect (GTK_OBJECT (text->model),
+ text->model_repos_signal_id);
if (text->model)
gtk_object_unref(GTK_OBJECT(text->model));
@@ -475,6 +485,41 @@ e_text_text_model_changed (ETextModel *model, EText *text)
}
static void
+e_text_text_model_reposition (ETextModel *model, ETextModelReposFn fn, gpointer repos_data, gpointer user_data)
+{
+ EText *text = E_TEXT (user_data);
+#if 0
+ gint org_start = text->selection_start, org_end = text->selection_end;
+#endif
+ 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;
+ }
+
+#if 0
+ if (org_start != text->selection_start || org_end != text->selection_end) {
+ /*
+ In general we shouldn't need to do anything to refresh the
+ canvas to redraw the (moved) selection, since "reposition" events
+ will only be generated in association with ETextModel-changing
+ activities.
+ */
+ }
+#endif
+}
+
+static void
get_bounds_item_relative (EText *text, double *px1, double *py1, double *px2, double *py2)
{
GnomeCanvasItem *item;
@@ -714,7 +759,7 @@ calc_line_widths (EText *text)
struct line *lines;
int i;
gdouble clip_width;
- gchar *p;
+ const gchar *p;
/* Make sure line has been split */
if (text->text && text->num_lines == 0)
@@ -737,7 +782,7 @@ calc_line_widths (EText *text)
for (i = 0; i < text->num_lines; i++) {
if (lines->length != 0) {
if (text->font) {
- lines->width = text_width_with_objects (text->model, lines->first_obj,
+ lines->width = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, lines->length);
lines->ellipsis_length = 0;
@@ -753,7 +798,7 @@ calc_line_widths (EText *text)
if (text->font) {
lines->ellipsis_length = 0;
for (p = lines->text; p && *p && (p - lines->text) < lines->length; p = unicode_next_utf8 (p)) {
- gint text_width = text_width_with_objects (text->model, lines->first_obj,
+ gint text_width = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, p - lines->text);
if (clip_width >= text_width + text->ellipsis_width)
@@ -764,7 +809,7 @@ calc_line_widths (EText *text)
}
else
lines->ellipsis_length = 0;
- lines->width = text_width_with_objects (text->model, lines->first_obj,
+ lines->width = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, lines->ellipsis_length) +
text->ellipsis_width;
@@ -791,135 +836,74 @@ e_text_free_lines(EText *text)
}
static gint
-text_width_with_objects (ETextModel *model, gint object_num,
+text_width_with_objects (ETextModel *model,
EFont *font, EFontStyle style,
- gchar *text, gint numbytes)
+ const gchar *text, gint numbytes)
{
- gchar *c;
- gint width = 0;
-
- while (*text && numbytes > 0) {
-
- c = text;
-
- while (*c && *c != '\1' && numbytes > 0) {
- ++c;
- --numbytes;
- }
-
- width += e_font_utf8_text_width (font, style, text, c-text);
-
- if (*c == '\1' && numbytes > 0) {
- const gchar *obj_str;
- g_assert (object_num < e_text_model_object_count (model));
- obj_str = e_text_model_get_nth_object (model, object_num);
- width += e_font_utf8_text_width (font, E_FONT_BOLD, obj_str, strlen (obj_str));
- ++object_num;
- ++c;
- --numbytes;
- }
-
- text = c;
- }
-
- return width;
-}
-
-static gint
-unicode_strlen_with_objects(ETextModel *model, gint object_num, gchar *s)
-{
- gint unival;
- gint len=0;
- gchar *p;
-
- for (p = unicode_get_utf8 (s, &unival); (unival && p); p = unicode_get_utf8 (p, &unival)) {
- if (unival == '\1') {
- const gchar *obj_str = e_text_model_get_nth_object (model, object_num);
- len += unicode_strlen (obj_str, -1);
- ++object_num;
- } else {
- ++len;
- }
- }
-
- return len;
+ return e_font_utf8_text_width (font, style, text, numbytes);
}
static void
-text_draw_with_objects (ETextModel *model, gint object_num,
+text_draw_with_objects (ETextModel *model,
GdkDrawable *drawable,
EFont *font, EFontStyle style,
GdkGC *gc,
gint x, gint y,
- gchar *text, gint numbytes)
+ const gchar *text, gint numbytes)
{
- gchar *c;
+ const gchar *c;
while (*text && numbytes > 0) {
+ gint obj_num = -1;
c = text;
- while (*c && *c != '\1' && numbytes > 0) {
+ while (*c
+ && (obj_num = e_text_model_get_object_at_pointer (model, c)) == -1
+ && numbytes > 0) {
++c;
--numbytes;
}
e_font_draw_utf8_text (drawable, font, style, gc, x, y, text, c-text);
x += e_font_utf8_text_width (font, style, text, c-text);
-
- if (*c == '\1' && numbytes > 0) {
- const gchar *obj_str;
- gint start_x = x;
+
+ if (obj_num != -1 && numbytes > 0) {
gint len;
- g_assert (object_num < e_text_model_object_count (model));
+ gint start_x = x;
- obj_str = e_text_model_get_nth_object (model, object_num);
+ e_text_model_get_nth_object (model, obj_num, &len);
- len = strlen (obj_str);
- e_font_draw_utf8_text (drawable, font, style, gc, x, y, obj_str, len);
- x += e_font_utf8_text_width (font, style, obj_str, len);
+ if (len > numbytes)
+ len = numbytes;
+ e_font_draw_utf8_text (drawable, font, style, gc, x, y, c, len);
+ x += e_font_utf8_text_width (font, style, c, len);
/* We underline our objects. */
gdk_draw_line (drawable, gc, start_x, y+1, x, y+1);
- ++object_num;
- ++c;
- --numbytes;
+ c += len;
+ numbytes -= len;
}
text = c;
}
}
-static gint
-object_number_advance (gint object_num, gchar *start, gint numbytes)
-{
- while (*start && numbytes > 0) {
- if (*start == '\1')
- ++object_num;
- ++start;
- --numbytes;
- }
-
- return object_num;
-}
-
-
#define IS_BREAKCHAR(text,c) ((text)->break_characters && unicode_strchr ((text)->break_characters, (c)))
/* Splits the text of the text item into lines */
static void
split_into_lines (EText *text)
{
- char *p, *cp;
+ const char *p, *cp;
struct line *lines;
int len;
int line_num;
- char *laststart;
- char *lastend;
- char *linestart;
+ const char *laststart;
+ const char *lastend;
+ const char *linestart;
double clip_width;
unicode_char_t unival;
- int object_num;
/* Free old array of lines */
e_text_free_lines(text);
@@ -941,18 +925,17 @@ split_into_lines (EText *text)
}
cp = text->text;
- object_num = 0;
for (p = unicode_get_utf8 (cp, &unival); (unival && p); cp = p, p = unicode_get_utf8 (p, &unival)) {
- if (text->line_wrap && (unicode_isspace (unival) || unival == '\n')) {
+ if (text->line_wrap
+ && (unicode_isspace (unival) || unival == '\n')
+ && e_text_model_get_object_at_pointer (text->model, cp) == -1) { /* don't break mid-object */
if (laststart != lastend
- && clip_width < text_width_with_objects (text->model, object_num,
+ && clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
linestart, cp - linestart)) {
text->num_lines ++;
-
- object_num = object_number_advance (object_num, linestart, lastend-linestart);
-
+
linestart = laststart;
laststart = p;
lastend = cp;
@@ -960,17 +943,16 @@ split_into_lines (EText *text)
laststart = p;
lastend = cp;
}
- } else if (text->line_wrap && (IS_BREAKCHAR(text, unival) || unival == '\1')) {
-
- if ((unival == '\1' || laststart != lastend)
- && (unival == '\1' || unicode_index_to_offset (linestart, cp - linestart) != 1)
- && clip_width < text_width_with_objects (text->model, object_num,
+ } else if (text->line_wrap
+ && IS_BREAKCHAR (text, unival)) {
+
+ if (laststart != lastend
+ && unicode_index_to_offset (linestart, cp - linestart) != 1
+ && clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
linestart, p - linestart)) {
text->num_lines ++;
-
- object_num = object_number_advance (object_num, linestart, lastend-linestart);
-
+
linestart = laststart;
laststart = p;
lastend = p;
@@ -979,11 +961,10 @@ split_into_lines (EText *text)
lastend = p;
}
}
+
if (unival == '\n') {
text->num_lines ++;
- object_num = object_number_advance (object_num, linestart, lastend-linestart);
-
lastend = p;
laststart = p;
linestart = p;
@@ -993,11 +974,10 @@ split_into_lines (EText *text)
if ( text->line_wrap
&& p
&& laststart != lastend
- && clip_width < text_width_with_objects (text->model, object_num,
+ && clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
linestart, cp - linestart)) {
text->num_lines ++;
- object_num = object_number_advance (object_num, linestart, lastend-linestart);
}
text->num_lines++;
@@ -1015,22 +995,21 @@ split_into_lines (EText *text)
laststart = text->text;
cp = text->text;
- object_num = 0;
for (p = unicode_get_utf8 (cp, &unival); p && unival && line_num < text->num_lines; cp = p, p = unicode_get_utf8 (p, &unival)) {
gboolean handled = FALSE;
if (len == 0)
lines->text = cp;
- if (text->line_wrap && (unicode_isspace (unival) || unival == '\n')) {
- if (clip_width < text_width_with_objects (text->model, object_num,
+ if (text->line_wrap
+ && (unicode_isspace (unival) || unival == '\n')
+ && e_text_model_get_object_at_pointer (text->model, cp) == -1) { /* don't break mid-object */
+ if (clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, cp - lines->text)
&& laststart != lastend) {
lines->length = lastend - lines->text;
- lines->first_obj = object_num;
- object_num = object_number_advance (object_num, lines->text, lines->length);
lines++;
line_num++;
@@ -1044,16 +1023,16 @@ split_into_lines (EText *text)
len ++;
}
handled = TRUE;
- } else if (text->line_wrap && (IS_BREAKCHAR(text, unival) || unival == '\1')) {
- if ((unival == '\1' || laststart != lastend)
- && (unival == '\1' || unicode_index_to_offset (lines->text, cp - lines->text) != 1)
- && clip_width < text_width_with_objects (text->model, object_num,
+ } else if (text->line_wrap
+ && IS_BREAKCHAR(text, unival)
+ && e_text_model_get_object_at_pointer (text->model, cp) == -1) {
+ if (laststart != lastend
+ && unicode_index_to_offset (lines->text, cp - lines->text) != 1
+ && clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, p - lines->text)) {
lines->length = lastend - lines->text;
- lines->first_obj = object_num;
- object_num = object_number_advance (object_num, lines->text, lines->length);
lines++;
line_num++;
@@ -1072,8 +1051,6 @@ split_into_lines (EText *text)
if (unival == '\n') {
lines->length = cp - lines->text;
- lines->first_obj = object_num;
- object_num = object_number_advance (object_num, lines->text, lines->length);
lines++;
line_num++;
@@ -1087,14 +1064,12 @@ split_into_lines (EText *text)
}
if ( line_num < text->num_lines && text->line_wrap ) {
- if (clip_width < text_width_with_objects (text->model, object_num,
+ if (clip_width < text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text, cp - lines->text)
&& laststart != lastend ) {
lines->length = lastend - lines->text;
- lines->first_obj = object_num;
- object_num = object_number_advance (object_num, lines->text, lines->length);
lines++;
line_num++;
@@ -1108,7 +1083,6 @@ split_into_lines (EText *text)
if (len == 0)
lines->text = cp;
lines->length = strlen (lines->text);
- lines->first_obj = object_num;
}
/* Convenience function to set the text's GC's foreground color */
@@ -1163,18 +1137,30 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
switch (arg_id) {
case ARG_MODEL:
+
if ( text->model_changed_signal_id )
- gtk_signal_disconnect(GTK_OBJECT(text->model),
- text->model_changed_signal_id);
- gtk_object_unref(GTK_OBJECT(text->model));
- text->model = E_TEXT_MODEL(GTK_VALUE_OBJECT (*arg));
- gtk_object_ref(GTK_OBJECT(text->model));
+ gtk_signal_disconnect (GTK_OBJECT (text->model),
+ text->model_changed_signal_id);
+
+ if ( text->model_repos_signal_id )
+ gtk_signal_disconnect (GTK_OBJECT (text->model),
+ text->model_repos_signal_id);
+
+ gtk_object_unref (GTK_OBJECT (text->model));
+ text->model = E_TEXT_MODEL (GTK_VALUE_OBJECT (*arg));
+ gtk_object_ref (GTK_OBJECT (text->model));
text->model_changed_signal_id =
- gtk_signal_connect(GTK_OBJECT(text->model),
- "changed",
- GTK_SIGNAL_FUNC(e_text_text_model_changed),
- text);
+ gtk_signal_connect (GTK_OBJECT (text->model),
+ "changed",
+ GTK_SIGNAL_FUNC (e_text_text_model_changed),
+ text);
+
+ text->model_repos_signal_id =
+ gtk_signal_connect (GTK_OBJECT (text->model),
+ "reposition",
+ GTK_SIGNAL_FUNC (e_text_text_model_reposition),
+ text);
e_text_free_lines(text);
@@ -1672,7 +1658,7 @@ e_text_reflow (GnomeCanvasItem *item, int flags)
}
lines --;
i--;
- x = text_width_with_objects (text->model, lines->first_obj,
+ x = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
text->selection_end - (lines->text - text->text));
@@ -2050,12 +2036,12 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
if ( sel_end > end_char )
sel_end = end_char;
if ( sel_start < sel_end ) {
- sel_rect.x = xpos - x + text_width_with_objects (text->model, lines->first_obj,
+ sel_rect.x = xpos - x + text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
sel_start - start_char);
sel_rect.y = ypos - y - e_font_ascent (text->font);
- sel_rect.width = text_width_with_objects (text->model, lines->first_obj,
+ sel_rect.width = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text + sel_start - start_char,
sel_end - sel_start);
@@ -2073,7 +2059,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
sel_rect.y,
sel_rect.width,
sel_rect.height);
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
text->gc,
@@ -2081,22 +2067,22 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
ypos - y,
lines->text,
sel_start - start_char);
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
fg_gc,
- xpos - x + text_width_with_objects (text->model, lines->first_obj,
+ xpos - x + text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
sel_start - start_char),
ypos - y,
lines->text + sel_start - start_char,
sel_end - sel_start);
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
text->gc,
- xpos - x + text_width_with_objects (text->model, lines->first_obj,
+ xpos - x + text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
sel_end - start_char),
@@ -2104,7 +2090,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
lines->text + sel_end - start_char,
end_char - sel_end);
} else {
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
text->gc,
@@ -2120,7 +2106,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
gdk_draw_rectangle (drawable,
text->gc,
TRUE,
- xpos - x + text_width_with_objects (text->model, lines->first_obj,
+ xpos - x + text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
sel_start - start_char),
@@ -2130,7 +2116,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
}
} else {
if (text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) {
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
text->gc,
@@ -2146,7 +2132,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
text->ellipsis ? text->ellipsis : "...",
text->ellipsis ? strlen (text->ellipsis) : 3);
} else
- text_draw_with_objects (text->model, lines->first_obj,
+ text_draw_with_objects (text->model,
drawable,
text->font, E_FONT_PLAIN,
text->gc,
@@ -2450,7 +2436,7 @@ _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp)
lines --;
y -= e_font_descent (text->font);
- x += text_width_with_objects (text->model, lines->first_obj,
+ x += text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
position - (lines->text - text->text));
@@ -2474,9 +2460,8 @@ _get_position_from_xy (EText *text, gint x, gint y)
int ypos = text->yofs;
int xpos;
double xd, yd;
- char *p;
+ const char *p;
unicode_char_t unival;
- gint object_num;
gint font_ht, adjust=0;
struct line *lines;
@@ -2526,13 +2511,13 @@ _get_position_from_xy (EText *text, gint x, gint y)
x += text->xofs_edit;
xpos = get_line_xpos_item_relative (text, lines);
- object_num = lines->first_obj;
for (i = 0, p = lines->text; p && i < lines->length; i++, p = unicode_get_utf8 (p, &unival)) {
int charwidth;
int step1, step2;
+#if 0
if (unival == '\1') {
- const gchar *obj_str = e_text_model_get_nth_object (text->model, object_num);
+ const gchar *obj_str = NULL; /*e_text_model_get_nth_object (text->model, object_num);*/
charwidth = e_font_utf8_text_width (text->font, E_FONT_PLAIN, obj_str, strlen (obj_str));
++object_num;
@@ -2541,12 +2526,15 @@ _get_position_from_xy (EText *text, gint x, gint y)
adjust = -1;
} else {
- charwidth = e_font_utf8_char_width (text->font, E_FONT_PLAIN, p);
+#endif
+ charwidth = e_font_utf8_char_width (text->font, E_FONT_PLAIN, (gchar *) p);
step1 = charwidth / 2;
step2 = (charwidth + 1) / 2;
adjust = 0;
+#if 0
}
+#endif
xpos += step1;
if (xpos > x) {
@@ -2734,8 +2722,7 @@ _do_tooltip (gpointer data)
for (lines = text->lines, i = 0; i < text->num_lines; lines++, i++) {
gdouble line_width;
- line_width = text_width_with_objects (text->model, lines->first_obj,
- text->font, E_FONT_PLAIN, lines->text, lines->length);
+ line_width = text_width_with_objects (text->model, text->font, E_FONT_PLAIN, lines->text, lines->length);
max_width = MAX (max_width, line_width);
}
@@ -2944,6 +2931,8 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event)
e_tep_event.key.state = key.state;
e_tep_event.key.keyval = key.keyval;
+ // g_print ("etext got keyval \"%s\"\n", gdk_keyval_name (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;
@@ -3114,139 +3103,178 @@ e_text_event (GnomeCanvasItem *item, GdkEvent *event)
static int
_get_position(EText *text, ETextEventProcessorCommand *command)
{
- int length;
+ int length, obj_num;
int x, y;
unicode_char_t unival;
- char *p;
+ char *p = NULL;
+ gint new_pos = 0;
switch (command->position) {
case E_TEP_VALUE:
- return command->value;
+ new_pos = command->value;
+ break;
case E_TEP_SELECTION:
- return text->selection_end;
+ new_pos = text->selection_end;
+ break;
case E_TEP_START_OF_BUFFER:
- return 0;
+ new_pos = 0;
+ break;
+
case E_TEP_END_OF_BUFFER:
- return unicode_strlen_with_objects (text->model, 0, text->text);
+ new_pos = unicode_strlen (text->text, -1);
+ break;
case E_TEP_START_OF_LINE:
- if (text->selection_end < 1) return 0;
- p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
- if (p == text->text) return 0;
- p = unicode_previous_utf8 (text->text, p);
-
- while (p && p > text->text) {
- if (*p == '\n') return p - text->text + 1;
- p = unicode_previous_utf8 (text->text, p);
+ new_pos = 0;
+
+ if (text->selection_end >= 1) {
+
+ p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
+ if (p != text->text) {
+ p = unicode_previous_utf8 (text->text, p);
+
+ while (p && p > text->text && !new_pos) {
+ if (*p == '\n')
+ new_pos = p - text->text + 1;
+ p = unicode_previous_utf8 (text->text, p);
+ }
+ }
}
- return 0;
+ break;
case E_TEP_END_OF_LINE:
+ new_pos = -1;
length = strlen (text->text);
- if (text->selection_end >= length) return length;
+
+ if (text->selection_end >= length) {
+ new_pos = length;
+ } else {
- p = unicode_next_utf8 (text->text + text->selection_end);
+ p = unicode_next_utf8 (text->text + text->selection_end);
- while (*p) {
- if (*p == '\n') return p - text->text;
- p = unicode_next_utf8 (p);
+ while (p && *p) {
+ if (*p == '\n') {
+ new_pos = p - text->text;
+ p = NULL;
+ } else
+ p = unicode_next_utf8 (p);
+ }
}
- return p - text->text;
+ if (new_pos == -1)
+ new_pos = p - text->text;
+
+ break;
case E_TEP_FORWARD_CHARACTER:
length = strlen (text->text);
- if (text->selection_end >= length) return length;
- p = unicode_next_utf8 (text->text + text->selection_end);
+ if (text->selection_end >= length) {
+ new_pos = length;
+ } else {
+ p = unicode_next_utf8 (text->text + text->selection_end);
+ new_pos = p - text->text;
+ }
- return p - text->text;
+ break;
case E_TEP_BACKWARD_CHARACTER:
- if (text->selection_end < 1) return 0;
- p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
+ new_pos = 0;
+ if (text->selection_end >= 1) {
+ p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
- if (p == NULL) return 0;
+ if (p != NULL)
+ new_pos = p - text->text;
+ }
- return p - text->text;
+ break;
case E_TEP_FORWARD_WORD:
+ new_pos = -1;
length = strlen (text->text);
- if (text->selection_end >= length) return length;
- p = unicode_next_utf8 (text->text + text->selection_end);
+ if (text->selection_end >= length) {
+ new_pos = length;
+ } else {
- while (*p) {
- unicode_get_utf8 (p, &unival);
- if (unicode_isspace (unival)) return p - text->text;
- p = unicode_next_utf8 (p);
+ p = unicode_next_utf8 (text->text + text->selection_end);
+
+ while (p && *p) {
+ unicode_get_utf8 (p, &unival);
+ if (unicode_isspace (unival)) {
+ new_pos = p - text->text;
+ p = NULL;
+ } else
+ p = unicode_next_utf8 (p);
+ }
}
+
+ if (new_pos == -1)
+ new_pos = p - text->text;
- return p - text->text;
+ break;
case E_TEP_BACKWARD_WORD:
-
- if (text->selection_end < 1) return 0;
- p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
- if (p == text->text) return 0;
- p = unicode_previous_utf8 (text->text, p);
-
- while (p && p > text->text) {
- unicode_get_utf8 (p, &unival);
- if (unicode_isspace (unival)) return (unicode_next_utf8 (p) - text->text);
- p = unicode_previous_utf8 (text->text, p);
+ new_pos = 0;
+ if (text->selection_end >= 1) {
+ p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
+ if (p != text->text) {
+ p = unicode_previous_utf8 (text->text, p);
+
+ while (p && p > text->text) {
+ unicode_get_utf8 (p, &unival);
+ if (unicode_isspace (unival)) {
+ new_pos = unicode_next_utf8 (p) - text->text;
+ p = NULL;
+ } else
+ p = unicode_previous_utf8 (text->text, p);
+ }
+ }
}
-
- return 0;
+
+ break;
case E_TEP_FORWARD_LINE:
_get_xy_from_position(text, text->selection_end, &x, &y);
y += e_font_height (text->font);
- return _get_position_from_xy(text, x, y);
+ new_pos = _get_position_from_xy(text, x, y);
+ break;
+
case E_TEP_BACKWARD_LINE:
_get_xy_from_position(text, text->selection_end, &x, &y);
y -= e_font_height (text->font);
- return _get_position_from_xy(text, x, y);
+ new_pos = _get_position_from_xy(text, x, y);
+ 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.) */
-
- gchar c = text->text[text->selection_start];
- gint i;
- gint obj_num=0;
-
- if (c == '\0'
- && text->selection_start > 0
- && text->text[text->selection_start-1] == '\1') {
- c = '\1';
- --text->selection_start;
- }
-
- if (c == '\1') {
+ /* 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;
+ }
- for (i=0; i<text->selection_start; ++i)
- if (text->text[i] == '\1')
- ++obj_num;
- e_text_model_activate_nth_object (text->model, obj_num);
-
- return text->selection_start;
- }
+ if (text->selection_end < 1) {
+ new_pos = 0;
+ break;
}
-
- if (text->selection_end < 1) return 0;
p = unicode_previous_utf8 (text->text, text->text + text->selection_end);
- if (p == text->text) return 0;
+ if (p == text->text) {
+ new_pos = 0;
+ break;
+ }
p = unicode_previous_utf8 (text->text, p);
while (p && p > text->text) {
@@ -3263,34 +3291,51 @@ _get_position(EText *text, ETextEventProcessorCommand *command)
else
text->selection_start = p - text->text;
- length = strlen (text->text);
- if (text->selection_end >= length) return length;
+ 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 = unicode_next_utf8 (text->text + text->selection_end);
- while (*p) {
+ while (p && *p) {
unicode_get_utf8 (p, &unival);
- if (unicode_isspace (unival)) return p - text->text;
- p = unicode_next_utf8 (p);
+ if (unicode_isspace (unival)) {
+ new_pos = p - text->text;
+ p = NULL;
+ } else
+ p = unicode_next_utf8 (p);
}
- return p - text->text;
+ if (p)
+ new_pos = p - text->text;
+
+ return new_pos;
case E_TEP_SELECT_ALL:
text->selection_start = 0;
- length = strlen (text->text);
- return length;
+ 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:
- return text->selection_end;
+ new_pos = text->selection_end;
+ break;
+
default:
- return text->selection_end;
- }
+ new_pos = text->selection_end;
+ }
+
+ new_pos = e_text_model_validate_position (text->model, new_pos);
+
+ return new_pos;
}
static void
@@ -3298,10 +3343,14 @@ _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
}
}
@@ -3311,8 +3360,10 @@ _insert(EText *text, char *string, int value)
if (value > 0) {
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
}
}
@@ -3321,6 +3372,7 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp
{
EText *text = E_TEXT(data);
int sel_start, sel_end;
+
switch (command->action) {
case E_TEP_MOVE:
text->selection_start = _get_position(text, command);
@@ -3330,15 +3382,21 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp
}
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_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,
- text->text + sel_start, sel_end - sel_start);
+ (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) {
@@ -3364,7 +3422,7 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp
sel_end = MAX(text->selection_start, text->selection_end);
if (sel_start != sel_end) {
e_text_supply_selection (text, command->time, clipboard_atom,
- text->text + sel_start, sel_end - sel_start);
+ (guchar *) text->text + sel_start, sel_end - sel_start);
}
if (text->timer) {
g_timer_reset(text->timer);
@@ -3416,7 +3474,7 @@ e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gp
}
lines --;
i --;
- x = text_width_with_objects (text->model, lines->first_obj,
+ x = text_width_with_objects (text->model,
text->font, E_FONT_PLAIN,
lines->text,
text->selection_end - (lines->text - text->text));