[2684] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[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


home help back first fref pref prev next nref lref last post