aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/text/e-text.c
diff options
context:
space:
mode:
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));