summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrillig <rillig@NetBSD.org>2021-02-22 17:36:42 +0000
committerCameron Katri <me@cameronkatri.com>2021-04-13 15:28:33 -0400
commitb651ad4a8509e0f72f9c8f416dc02f3669672b35 (patch)
tree9db3447a5b19d44a2a63385729cbe1bfbb30c0a9
parentc6dcb4c432995d92e9e40b8dfce534fa4e47dd0b (diff)
downloadbsdgames-darwin-b651ad4a8509e0f72f9c8f416dc02f3669672b35.tar.gz
bsdgames-darwin-b651ad4a8509e0f72f9c8f416dc02f3669672b35.tar.zst
bsdgames-darwin-b651ad4a8509e0f72f9c8f416dc02f3669672b35.zip
cgram: add advanced cursor movement with tab, shift+tab, return
-rw-r--r--cgram/cgram.c166
1 files changed, 117 insertions, 49 deletions
diff --git a/cgram/cgram.c b/cgram/cgram.c
index 3d33d85a..93ebddd9 100644
--- a/cgram/cgram.c
+++ b/cgram/cgram.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cgram.c,v 1.12 2021/02/22 16:28:20 rillig Exp $ */
+/* $NetBSD: cgram.c,v 1.13 2021/02/22 17:36:42 rillig Exp $ */
/*-
* Copyright (c) 2013, 2021 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: cgram.c,v 1.12 2021/02/22 16:28:20 rillig Exp $");
+__RCSID("$NetBSD: cgram.c,v 1.13 2021/02/22 17:36:42 rillig Exp $");
#endif
#include <assert.h>
@@ -73,6 +73,12 @@ ch_islower(char ch)
}
static bool
+ch_isspace(char ch)
+{
+ return isspace((unsigned char)ch) != 0;
+}
+
+static bool
ch_isupper(char ch)
{
return isupper((unsigned char)ch) != 0;
@@ -193,6 +199,23 @@ cur_max_y(void)
return extent_y - 1;
}
+static char
+char_left_of_cursor(void)
+{
+ if (cursor_x > 0)
+ return lines.v[cursor_y].s[cursor_x - 1];
+ assert(cursor_y > 0);
+ return '\n'; /* eol of previous line */
+}
+
+static char
+char_at_cursor(void)
+{
+ if (cursor_x == cur_max_x())
+ return '\n';
+ return lines.v[cursor_y].s[cursor_x];
+}
+
static void
readquote(void)
{
@@ -266,7 +289,7 @@ substitute(char ch)
return false;
}
- char och = lines.v[cursor_y].s[cursor_x];
+ char och = char_at_cursor();
if (!ch_isalpha(och)) {
beep();
return false;
@@ -292,8 +315,6 @@ substitute(char ch)
return true;
}
-////////////////////////////////////////////////////////////
-
static bool
is_solved(void)
{
@@ -303,6 +324,8 @@ is_solved(void)
return true;
}
+////////////////////////////////////////////////////////////
+
static void
redraw(void)
{
@@ -342,21 +365,6 @@ redraw(void)
refresh();
}
-static void
-opencurses(void)
-{
- initscr();
- cbreak();
- noecho();
- keypad(stdscr, true);
-}
-
-static void
-closecurses(void)
-{
- endwin();
-}
-
////////////////////////////////////////////////////////////
static void
@@ -383,6 +391,72 @@ scroll_into_view(void)
offset_y = cursor_y - (LINES - 2);
}
+static bool
+can_go_left(void)
+{
+ return cursor_y > 0 ||
+ (cursor_y == 0 && cursor_x > 0);
+}
+
+static bool
+can_go_right(void)
+{
+ return cursor_y < cur_max_y() ||
+ (cursor_y == cur_max_y() && cursor_x < cur_max_x());
+}
+
+static void
+go_to_prev_line(void)
+{
+ cursor_y--;
+ cursor_x = cur_max_x();
+}
+
+static void
+go_to_next_line(void)
+{
+ cursor_x = 0;
+ cursor_y++;
+}
+
+static void
+go_left(void)
+{
+ if (cursor_x > 0)
+ cursor_x--;
+ else if (cursor_y > 0)
+ go_to_prev_line();
+}
+
+static void
+go_right(void)
+{
+ if (cursor_x < cur_max_x())
+ cursor_x++;
+ else if (cursor_y < cur_max_y())
+ go_to_next_line();
+}
+
+static void
+go_to_prev_word(void)
+{
+ while (can_go_left() && ch_isspace(char_left_of_cursor()))
+ go_left();
+
+ while (can_go_left() && !ch_isspace(char_left_of_cursor()))
+ go_left();
+}
+
+static void
+go_to_next_word(void)
+{
+ while (can_go_right() && !ch_isspace(char_at_cursor()))
+ go_right();
+
+ while (can_go_right() && ch_isspace(char_at_cursor()))
+ go_right();
+}
+
static void
handle_char_input(int ch)
{
@@ -390,23 +464,13 @@ handle_char_input(int ch)
if (substitute((char)ch)) {
if (cursor_x < cur_max_x())
cursor_x++;
- if (cursor_x == cur_max_x() &&
- cursor_y < cur_max_y()) {
- cursor_x = 0;
- cursor_y++;
- }
- }
- } else if (cursor_x < cur_max_x() &&
- ch == lines.v[cursor_y].s[cursor_x]) {
- cursor_x++;
- if (cursor_x == cur_max_x() &&
- cursor_y < cur_max_y()) {
- cursor_x = 0;
- cursor_y++;
+ if (cursor_x == cur_max_x())
+ go_to_next_line();
}
- } else {
+ } else if (ch == char_at_cursor())
+ go_right();
+ else
beep();
- }
}
static bool
@@ -421,12 +485,7 @@ handle_key(void)
break;
case 2: /* ^B */
case KEY_LEFT:
- if (cursor_x > 0) {
- cursor_x--;
- } else if (cursor_y > 0) {
- cursor_y--;
- cursor_x = cur_max_x();
- }
+ go_left();
break;
case 5: /* ^E */
case KEY_END:
@@ -434,12 +493,16 @@ handle_key(void)
break;
case 6: /* ^F */
case KEY_RIGHT:
- if (cursor_x < cur_max_x()) {
- cursor_x++;
- } else if (cursor_y < cur_max_y()) {
- cursor_y++;
- cursor_x = 0;
- }
+ go_right();
+ break;
+ case '\t':
+ go_to_next_word();
+ break;
+ case KEY_BTAB:
+ go_to_prev_word();
+ break;
+ case '\n':
+ go_to_next_line();
break;
case 12: /* ^L */
clear();
@@ -478,7 +541,11 @@ init(void)
srandom((unsigned int)time(NULL));
readquote();
encode();
- opencurses();
+
+ initscr();
+ cbreak();
+ noecho();
+ keypad(stdscr, true);
}
static void
@@ -496,7 +563,8 @@ loop(void)
static void
clean_up(void)
{
- closecurses();
+ endwin();
+
stringarray_cleanup(&sollines);
stringarray_cleanup(&lines);
}