[2684] in BarnOwl Developers
[PATCH 5/5] Cache the current column to avoid repeatly recomputing it
daemon@ATHENA.MIT.EDU (David Benjamin)
Wed Sep 29 16:08:12 2010
From: David Benjamin <davidben@MIT.EDU>
To: barnowl-dev@mit.edu
Date: Wed, 29 Sep 2010 16:06:00 -0400
In-Reply-To: <1285790760-10916-1-git-send-email-davidben@mit.edu>
In particular, we appropriately update it when inserting characters.
---
editwin.c | 45 ++++++++++++++++++++++++++++++++++++---------
tester.c | 13 +++++++++++++
2 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/editwin.c b/editwin.c
index 8ad0807..62600e1 100644
--- a/editwin.c
+++ b/editwin.c
@@ -26,6 +26,7 @@ struct _owl_editwin { /*noproto*/
char *killbuf;
int goal_column;
int topindex;
+ int column;
int winlines, wincols, fillcol, wrapcol;
owl_window *win;
gulong repaint_id;
@@ -49,7 +50,8 @@ static void oe_release_excursion(owl_editwin *e, oe_excursion *x);
static void oe_restore_excursion(owl_editwin *e, oe_excursion *x);
static void oe_restore_mark_only(owl_editwin *e, oe_excursion *x);
static int oe_char_width(gunichar c, int column);
-static int oe_region_width(owl_editwin *e, int start, int end, int width);
+static int oe_region_column(owl_editwin *e, int start, int end, int offset);
+static int oe_region_width(owl_editwin *e, int start, int end, int offset);
static int oe_find_display_line(owl_editwin *e, int *x, int index, int *hard);
static void oe_insert_char(owl_editwin *e, gunichar c);
static int owl_editwin_limit_maxcols(int width, int cols);
@@ -99,6 +101,7 @@ static inline void oe_set_index(owl_editwin *e, int index)
{
if (index != e->index) {
e->goal_column = -1;
+ e->column = -1;
}
e->index = index;
oe_dirty(e);
@@ -132,6 +135,7 @@ static void _owl_editwin_init(owl_editwin *e,
owl_free(e->killbuf);
e->killbuf = NULL;
e->goal_column = -1;
+ e->column = -1;
e->topindex = 0;
e->excursions = NULL;
e->style=style;
@@ -645,7 +649,7 @@ int owl_editwin_replace(owl_editwin *e, int replace, const char *s)
static int owl_editwin_replace_internal(owl_editwin *e, int replace, const char *s)
{
- int start, end, free, need, size, change;
+ int start, end, free, need, size, change, oldindex;
oe_excursion *x;
start = e->index;
@@ -664,7 +668,10 @@ static int owl_editwin_replace_internal(owl_editwin *e, int replace, const char
memcpy(e->buff + start, s, strlen(s));
change = start - end + strlen(s);
e->bufflen += change;
+ oldindex = e->index;
e->index += strlen(s);
+ if (e->column != -1)
+ e->column = oe_region_column(e, oldindex, e->index, e->column);
/* fix up the mark */
oe_fixup(&e->mark, start, end, change);
@@ -1145,14 +1152,17 @@ void owl_editwin_forward_paragraph(owl_editwin *e)
int owl_editwin_current_column(owl_editwin *e)
{
- oe_excursion x;
- int lineindex;
+ if (e->column == -1) {
+ oe_excursion x;
+ int lineindex;
- oe_save_excursion(e, &x);
- owl_editwin_move_to_beginning_of_line(e);
- lineindex = e->index;
- oe_restore_excursion(e, &x);
- return oe_region_width(e, lineindex, e->index, 0);
+ oe_save_excursion(e, &x);
+ owl_editwin_move_to_beginning_of_line(e);
+ lineindex = e->index;
+ oe_restore_excursion(e, &x);
+ e->column = oe_region_width(e, lineindex, e->index, 0);
+ }
+ return e->column;
}
void owl_editwin_fill_paragraph(owl_editwin *e)
@@ -1273,6 +1283,23 @@ void owl_editwin_post_process_char(owl_editwin *e, owl_input j)
}
}
+static int oe_region_column(owl_editwin *e, int start, int end, int offset)
+{
+ const char *p;
+ int column = offset;
+
+ for(p = e->buff + start;
+ p < e->buff + end;
+ p = g_utf8_find_next_char(p, NULL)) {
+ gunichar c = g_utf8_get_char(p);
+ if (c == '\n')
+ column = 0;
+ else
+ column += oe_char_width(c, column);
+ }
+ return column;
+}
+
static int oe_region_width(owl_editwin *e, int start, int end, int offset)
{
const char *p;
diff --git a/tester.c b/tester.c
index e14fe2c..b00cc35 100644
--- a/tester.c
+++ b/tester.c
@@ -449,6 +449,19 @@ int owl_editwin_regtest(void) {
owl_editwin_unref(oe); oe = NULL;
owl_global_set_edit_maxwrapcols(&g, 70);
+ /* Test owl_editwin_current_column. */
+ oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
+ FAIL_UNLESS("initial column zero", owl_editwin_current_column(oe) == 0);
+ owl_editwin_insert_string(oe, "abcdef");
+ FAIL_UNLESS("simple insert", owl_editwin_current_column(oe) == 6);
+ owl_editwin_insert_string(oe, "\t");
+ FAIL_UNLESS("insert tabs", owl_editwin_current_column(oe) == 8);
+ owl_editwin_insert_string(oe, "123\n12\t3");
+ FAIL_UNLESS("newline with junk", owl_editwin_current_column(oe) == 9);
+ owl_editwin_move_to_beginning_of_line(oe);
+ FAIL_UNLESS("beginning of line", owl_editwin_current_column(oe) == 0);
+ owl_editwin_unref(oe); oe = NULL;
+
printf("# END testing owl_editwin (%d failures)\n", numfailed);
return numfailed;
--
1.7.3.1.g716de