cgram: add advanced cursor movement with tab, shift+tab, return
This commit is contained in:
parent
47c6585f93
commit
f7c85ecb67
@ -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>
|
||||
@ -72,6 +72,12 @@ ch_islower(char ch)
|
||||
return islower((unsigned char)ch) != 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
ch_isspace(char ch)
|
||||
{
|
||||
return isspace((unsigned char)ch) != 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
ch_isupper(char ch)
|
||||
{
|
||||
@ -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++;
|
||||
}
|
||||
if (cursor_x == cur_max_x())
|
||||
go_to_next_line();
|
||||
}
|
||||
} 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++;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user