-/* $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.
#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>
return islower((unsigned char)ch) != 0;
}
+static bool
+ch_isspace(char ch)
+{
+ return isspace((unsigned char)ch) != 0;
+}
+
static bool
ch_isupper(char ch)
{
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)
{
return false;
}
- char och = lines.v[cursor_y].s[cursor_x];
+ char och = char_at_cursor();
if (!ch_isalpha(och)) {
beep();
return false;
return true;
}
-////////////////////////////////////////////////////////////
-
static bool
is_solved(void)
{
return true;
}
+////////////////////////////////////////////////////////////
+
static void
redraw(void)
{
refresh();
}
-static void
-opencurses(void)
-{
- initscr();
- cbreak();
- noecho();
- keypad(stdscr, true);
-}
-
-static void
-closecurses(void)
-{
- endwin();
-}
-
////////////////////////////////////////////////////////////
static 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)
{
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
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:
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();
srandom((unsigned int)time(NULL));
readquote();
encode();
- opencurses();
+
+ initscr();
+ cbreak();
+ noecho();
+ keypad(stdscr, true);
}
static void
static void
clean_up(void)
{
- closecurses();
+ endwin();
+
stringarray_cleanup(&sollines);
stringarray_cleanup(&lines);
}