[bim] Add REPLACE mode

This commit is contained in:
K. Lange 2018-08-28 17:54:22 +09:00
parent f95f495b54
commit fcbcb51ec2

View File

@ -372,6 +372,7 @@ buffer_t * env;
#define MODE_NORMAL 0
#define MODE_INSERT 1
#define MODE_LINE_SELECTION 2
#define MODE_REPLACE 3
/**
* Available buffers
@ -2015,6 +2016,11 @@ void redraw_commandline(void) {
printf("-- LINE SELECTION --");
clear_to_end();
reset();
} else if (env->mode == MODE_REPLACE) {
set_bold();
printf("-- REPLACE --");
clear_to_end();
reset();
} else {
clear_to_end();
}
@ -3658,6 +3664,25 @@ void insert_char(unsigned int c) {
set_modified();
}
/**
* Replace a single character at the current cursor point
*/
void replace_char(unsigned int c) {
if (env->col_no < 1 || env->col_no > env->lines[env->line_no-1]->actual) return;
char_t _c;
_c.codepoint = c;
_c.flags = 0;
_c.display_width = codepoint_width(c);
env->lines[env->line_no-1]->text[env->col_no-1] = _c;
recalculate_tabs(env->lines[env->line_no-1]);
recalculate_syntax(env->lines[env->line_no-1], env->line_no);
redraw_line(env->line_no - env->offset - 1, env->line_no-1);
set_modified();
}
/**
* Move the cursor the start of the previous word.
*/
@ -3817,7 +3842,7 @@ int handle_escape(int * this_buf, int * timeout, int c) {
goto_line(env->line_no - (global_config.term_height - 6));
break;
case '3':
if (env->mode == MODE_INSERT) {
if (env->mode == MODE_INSERT || env->mode == MODE_REPLACE) {
if (env->col_no < env->lines[env->line_no - 1]->actual + 1) {
line_delete(env->lines[env->line_no - 1], env->col_no, env->line_no - 1);
redraw_line(env->line_no - env->offset - 1, env->line_no-1);
@ -4103,6 +4128,49 @@ _leave_select_line:
redraw_all();
}
/**
* Backspace from the current cursor position.
*/
void delete_at_cursor(void) {
if (env->col_no > 1) {
line_delete(env->lines[env->line_no - 1], env->col_no - 1, env->line_no - 1);
env->col_no -= 1;
redraw_line(env->line_no - env->offset - 1, env->line_no-1);
set_modified();
redraw_statusbar();
place_cursor_actual();
} else if (env->line_no > 1) {
int tmp = env->lines[env->line_no - 2]->actual;
merge_lines(env->lines, env->line_no - 1);
env->line_no -= 1;
env->col_no = tmp+1;
redraw_text();
set_modified();
redraw_statusbar();
place_cursor_actual();
}
}
/**
* Break the current line in two at the current cursor position.
*/
void insert_line_feed(void) {
if (env->col_no == env->lines[env->line_no - 1]->actual + 1) {
env->lines = add_line(env->lines, env->line_no);
} else {
env->lines = split_line(env->lines, env->line_no, env->col_no - 1);
}
env->col_no = 1;
env->line_no += 1;
add_indent(env->line_no-1,env->line_no-2);
if (env->line_no > env->offset + global_config.term_height - global_config.bottom_size - 1) {
env->offset += 1;
}
redraw_text();
set_modified();
redraw_statusbar();
place_cursor_actual();
}
/**
* INSERT mode
@ -4143,41 +4211,10 @@ void insert_mode(void) {
break;
case DELETE_KEY:
case BACKSPACE_KEY:
if (env->col_no > 1) {
line_delete(env->lines[env->line_no - 1], env->col_no - 1, env->line_no - 1);
env->col_no -= 1;
redraw_line(env->line_no - env->offset - 1, env->line_no-1);
set_modified();
redraw_statusbar();
place_cursor_actual();
} else if (env->line_no > 1) {
int tmp = env->lines[env->line_no - 2]->actual;
merge_lines(env->lines, env->line_no - 1);
env->line_no -= 1;
env->col_no = tmp+1;
redraw_text();
set_modified();
redraw_statusbar();
place_cursor_actual();
}
delete_at_cursor();
break;
case ENTER_KEY:
if (env->col_no == env->lines[env->line_no - 1]->actual + 1) {
env->lines = add_line(env->lines, env->line_no);
} else {
/* oh oh god we're all gonna die */
env->lines = split_line(env->lines, env->line_no, env->col_no - 1);
}
env->col_no = 1;
env->line_no += 1;
add_indent(env->line_no-1,env->line_no-2);
if (env->line_no > env->offset + global_config.term_height - global_config.bottom_size - 1) {
env->offset += 1;
}
redraw_text();
set_modified();
redraw_statusbar();
place_cursor_actual();
insert_line_feed();
break;
case '\t':
if (env->tabs) {
@ -4209,6 +4246,80 @@ void insert_mode(void) {
}
}
/*
* REPLACE mode
*
* Like insert, but replaces characters.
*/
void replace_mode(void) {
int cin;
uint32_t c;
/* Set mode line */
env->mode = MODE_REPLACE;
redraw_commandline();
/* Place the cursor in the text area */
place_cursor_actual();
int timeout = 0;
int this_buf[20];
uint32_t istate = 0;
while ((cin = bim_getch())) {
if (cin == -1) {
if (timeout && this_buf[timeout-1] == '\033') {
leave_insert();
return;
}
timeout = 0;
continue;
}
if (!decode(&istate, &c, cin)) {
if (timeout == 0) {
switch (c) {
case '\033':
if (timeout == 0) {
this_buf[timeout] = c;
timeout++;
}
break;
case DELETE_KEY:
case BACKSPACE_KEY:
if (env->line_no > 1 && env->col_no == 1) {
env->line_no--;
env->col_no = env->lines[env->line_no-1]->actual;
place_cursor_actual();
} else {
cursor_left();
}
break;
case ENTER_KEY:
insert_line_feed();
break;
default:
if (env->col_no <= env->lines[env->line_no - 1]->actual) {
replace_char(c);
env->col_no += 1;
} else {
insert_char(c);
}
redraw_statusbar();
place_cursor_actual();
break;
}
} else {
if (handle_escape(this_buf,&timeout,c)) {
bim_unget(c);
leave_insert();
return;
}
}
} else if (istate == UTF8_REJECT) {
istate = 0;
}
}
}
static void show_usage(char * argv[]) {
printf(
"bim - Text editor\n"
@ -4358,7 +4469,13 @@ int main(int argc, char * argv[]) {
break;
case DELETE_KEY:
case BACKSPACE_KEY:
cursor_left();
if (env->line_no > 1 && env->col_no == 1) {
env->line_no--;
env->col_no = env->lines[env->line_no-1]->actual;
place_cursor_actual();
} else {
cursor_left();
}
break;
case ':':
/* Switch to command mode */
@ -4465,6 +4582,13 @@ _insert:
redraw_commandline();
timeout = 0;
break;
case 'R':
if (env->readonly) goto _readonly;
replace_mode();
redraw_statusbar();
redraw_commandline();
timeout = 0;
break;
_readonly:
render_error("Buffer is read-only");
break;