From 6f425dc1fad44b1ea878d314e539ddbc7bbde94f Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <calcurse@cryptocrack.de>
Date: Sat, 5 Mar 2011 17:13:37 +0100
Subject: Clean up and simplify line editing functions.

This greatly simplifies all line editing functions - especially
getstring() and showstring(). showcursor() is removed and integrated
into showstring(). del_char() and add_char() are simplified as well.
add_char() is renamed to ins_char().

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
---
 src/utils.c | 258 +++++++++++++++++++++++-------------------------------------
 1 file changed, 100 insertions(+), 158 deletions(-)

(limited to 'src')

diff --git a/src/utils.c b/src/utils.c
index a5adec1..bee5e55 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -228,77 +228,51 @@ print_in_middle (WINDOW *win, int starty, int startx, int width, char *string)
   custom_remove_attr (win, ATTR_HIGHEST);
 }
 
-/* 
- * Draw the cursor at the correct position in string.
- * As echoing is not set, we need to know the string we are working on to 
- * handle display correctly.
- */
+/* Print the string at the desired position. */
 static void
-showcursor (WINDOW *win, int y, int pos, char *str, int l, int offset)
+showstring (WINDOW *win, int x, int y, char *str, int len, int scroff,
+            int curpos)
 {
-  char *nc;
-
-  nc = str + pos;
-  wmove (win, y, pos - offset);
-  (pos >= l) ? waddch (win, SPACE | A_REVERSE) : waddch (win, *nc | A_REVERSE);
-}
+  char c = 0;
 
-/* Print the string at the desired position. */
-static void
-showstring (WINDOW *win, int y, int x, char *str, int len, int pos)
-{
-  const int rec = 30, border = 3;
-  const int max_col = col - border, max_len = max_col - rec;
-  int page, max_page, offset, c = 0;
-  char *orig;
-
-  orig = str;
-  max_page = (len - rec) / max_len;
-  page = (pos - rec) / max_len;
-  offset = page * max_len;
-  str += offset;
-  mvwaddnstr (win, y, x, str, MIN (len, max_col));
+  /* print string */
+  mvwaddnstr (win, y, x, &str[scroff], -1);
   wclrtoeol (win);
-  if (page > 0 && page < max_page)
-    {
-      c = '*';
-    }
-  else if (page > 0)
-    {
-      c = '<';
-    }
-  else if (page < max_page)
-    {
-      c = '>';
-    }
-  else
-    c = 0;
+
+  /* print scrolling indicator */
+  if (scroff > 0 && scroff < len - col) c = '*';
+  else if (scroff > 0) c = '<';
+  else if (scroff < len - col) c = '>';
   mvwprintw (win, y, col - 1, "%c", c);
-  showcursor (win, y, pos, orig, len, offset);
+
+  /* print cursor */
+  wmove (win, y, curpos - scroff);
+
+  if (curpos >= len) waddch (win, SPACE | A_REVERSE);
+  else waddch (win, str[curpos] | A_REVERSE);
 }
 
 /* Delete a character at the given position in string. */
 static void
 del_char (int pos, char *str)
 {
-  int len;
-
   str += pos;
-  len = strlen (str) + 1;
-  memmove (str, str + 1, len);
+  memmove (str, str + 1, strlen (str) + 1);
 }
 
 /* Add a character at the given position in string. */
-static char *
-add_char (int pos, int ch, char *str)
+static void
+ins_char (int pos, int ch, char *str)
 {
-  int len;
-
   str += pos;
-  len = strlen (str) + 1;
-  memmove (str + 1, str, len);
+  memmove (str + 1, str, strlen (str) + 1);
   *str = ch;
-  return (str += len);
+}
+
+void
+bell (void)
+{
+  printf ("\a");
 }
 
 /* 
@@ -312,117 +286,85 @@ add_char (int pos, int ch, char *str)
 enum getstr
 getstring (WINDOW *win, char *str, int l, int x, int y)
 {
-  int ch, newpos, len = 0;
-  char *orig;
+  const int pgsize = col / 3;
+
+  int len = strlen (str);
+  int curpos = len;
+  int scroff = 0;
+  int ch;
 
-  orig = str;
   custom_apply_attr (win, ATTR_HIGHEST);
-  for (; *str; ++str, ++len)
-    ;
-  newpos = x + len;
-  showstring (win, y, x, orig, len, newpos);
 
-  while ((ch = wgetch (win)) != '\n')
-    {
-      switch (ch)
-	{
-	case KEY_BACKSPACE:	/* delete one character */
-	case 330:
-	case 127:
-	case CTRL ('H'):
-	  if (len > 0 && newpos > x)
-	    {
-	      --newpos;
-	      --len;
-	      if (newpos >= x + len)
-		--str;
-	      else		/* to be deleted inside string */
-		del_char (newpos, orig);
-	    }
-	  break;
-
-	case CTRL ('D'):	/* delete next character */
-	  if (newpos != (x + len))
-	    {
-	      --len;
-	      if (newpos >= x + len)
-		--str;
-	      else
-		del_char (newpos, orig);
-	    }
-	  else
-	    printf ("\a");
-	  break;
-
-  case CTRL ('W'):	/* delete a word */
-    while (len > 0 && newpos > x && *(orig + newpos - 1) == ' ') {
-      --newpos;
-      --len;
-      if (newpos >= x + len)
-        --str;
-      else
-        del_char (newpos, orig);
-    }
-    while (len > 0 && newpos > x && *(orig + newpos - 1) != ' ') {
-      --newpos;
-      --len;
-      if (newpos >= x + len)
-        --str;
-      else
-        del_char (newpos, orig);
+  for (;;) {
+    while (curpos < scroff) scroff -= pgsize;
+    while (curpos >= scroff + col - 1) scroff += pgsize;
+
+    showstring (win, x, y, str, len, scroff, curpos);
+    wins_doupdate ();
+
+    if ((ch = wgetch (win)) == '\n') break;
+    switch (ch) {
+      case KEY_BACKSPACE:     /* delete one character */
+      case 330:
+      case 127:
+      case CTRL ('H'):
+        if (curpos > 0) {
+          del_char ((--curpos), str);
+          len--;
+        }
+        else bell ();
+        break;
+      case CTRL ('D'):        /* delete next character */
+        if (curpos < len) {
+          del_char (curpos, str);
+          len--;
+        }
+	      else bell ();
+        break;
+      case CTRL ('W'):        /* delete a word */
+        if (curpos > 0) {
+          while (curpos && str[curpos - 1] == ' ') {
+            del_char ((--curpos), str);
+            len--;
+          }
+          while (curpos && str[curpos - 1] != ' ') {
+            del_char ((--curpos), str);
+            len--;
+          }
+        }
+        else bell ();
+        break;
+      case CTRL ('K'):        /* delete to end-of-line */
+        str[curpos] = 0;
+        len = curpos;
+        break;
+      case CTRL ('A'):        /* go to begginning of string */
+        curpos = 0;
+        break;
+      case CTRL ('E'):        /* go to end of string */
+        curpos = len;
+        break;
+      case KEY_LEFT:          /* move one char backward  */
+      case CTRL ('B'):
+        if (curpos > 0) curpos--;
+        break;
+      case KEY_RIGHT:         /* move one char forward */
+      case CTRL ('F'):
+        if (curpos < len) curpos++;
+        break;
+      case ESCAPE:            /* cancel editing */
+        return (GETSTRING_ESC);
+        break;
+      default:                /* insert one character */
+        if (len < l - 1) {
+          ins_char ((curpos++), ch, str);
+          len++;
+        }
     }
-    break;
-
-	case CTRL ('K'):	/* delete to end-of-line */
-	  str = orig + newpos;
-	  *str = 0;
-	  len -= (len - newpos);
-	  break;
-
-	case CTRL ('A'):	/* go to begginning of string */
-	  newpos = x;
-	  break;
-
-	case CTRL ('E'):	/* go to end of string */
-	  newpos = x + len;
-	  break;
-
-	case KEY_LEFT:		/* move one char backward  */
-	case CTRL ('B'):
-	  if (newpos > x)
-	    newpos--;
-	  break;
-
-	case KEY_RIGHT:	/* move one char forward */
-	case CTRL ('F'):
-	  if (newpos < len)
-	    newpos++;
-	  break;
-
-	case ESCAPE:	/* cancel editing */
-	  return (GETSTRING_ESC);
-	  break;
-
-	default:		/* insert one character */
-	  if (len < l - 1)
-	    {
-	      if (newpos >= len)
-		{
-		  str = orig + newpos;
-		  *str++ = ch;
-		}
-	      else		// char is to be inserted inside string 
-		str = add_char (newpos, ch, orig);
-	      ++len;
-	      ++newpos;
-	    }
+  }
 
-	}
-      showstring (win, y, x, orig, len, newpos);
-      wins_doupdate ();
-    }
-  *str = 0;
   custom_remove_attr (win, ATTR_HIGHEST);
+
   return (len == 0 ? GETSTRING_RET : GETSTRING_VALID);
 }
 
-- 
cgit v1.2.3-70-g09d2