#include #include #include #include #include #include #include #include #include <_string.h> #include "editing.h" #include "buffer.h" #include "core.h" #include "editor.h" #include "killring.h" #include "term.h" #include "process.h" void process_kcommand(const int16_t c) { char *buf = NULL; size_t len = 0; int jumpx = 0; int jumpy = 0; int reps = 0; switch (c) { case BACKSPACE: while (ECURX > 0) { process_normal(BACKSPACE); } break; case '=': if (EMARK_SET) { indent_region(); } else { editor_set_status("Mark not set."); } break; case '-': if (EMARK_SET) { unindent_region(); } else { editor_set_status("Mark not set."); } break; case CTRL_KEY('\\'): /* sometimes it's nice to dump core */ disable_termraw(); abort(); case '@': if (!dump_pidfile()) { break; } /* FALLTHRU */ case '!': /* useful for debugging */ editor_set_status("PID: %ld", (long) getpid()); break; case ' ': toggle_markset(); break; case CTRL_KEY(' '): jumpx = EMARK_CURX; jumpy = EMARK_CURY; EMARK_CURX = ECURX; EMARK_CURY = ECURY; jump_to_position(jumpx, jumpy); editor_set_status("Jumped to mark"); break; case 'c': buffer_close_current(); break; case 'd': if (ECURX == 0 && cursor_at_eol()) { delete_row(ECURY); return; } reps = uarg_get(); while (reps--) { while ((EROW[ECURY].size - ECURX) > 0) { process_normal(DEL_KEY); } if (reps) { newline(); } } break; case DEL_KEY: case CTRL_KEY('d'): reps = uarg_get(); while (reps--) { delete_row(ECURY); } break; case 'e': case CTRL_KEY('e'): if (EDIRTY && editor.dirtyex) { editor_set_status( "File not saved - C-k e again to open a new file anyways."); editor.dirtyex = 0; return; } editor_openfile(); break; case 'f': if (editor.killring == NULL || editor.killring->size == 0) { editor_set_status("The kill ring is empty."); break; } len = editor.killring ? editor.killring->size : 0; killring_flush(); editor_set_status("Kill ring cleared (%lu characters)", len); break; case 'n': buffer_next(); break; case 'p': buffer_prev(); break; case 'b': buffer_switch_by_name(); break; case 'g': goto_line(); break; case 'j': if (!EMARK_SET) { editor_set_status("Mark not set."); break; } jumpx = EMARK_CURX; jumpy = EMARK_CURY; EMARK_CURX = ECURX; EMARK_CURY = ECURY; jump_to_position(jumpx, jumpy); editor_set_status("Jumped to mark; mark is now the previous location."); break; case 'l': buf = get_cloc_code_lines(EFILENAME); editor_set_status("Lines of code: %s", buf); free(buf); break; case 'm': /* todo: fix the process failed: success issue */ if (system("make") != 0) { editor_set_status( "process failed: %s", strerror(errno)); } else { editor_set_status("make: ok"); } break; case 'q': if (EDIRTY && editor.dirtyex) { editor_set_status( "File not saved - C-k q again to quit."); editor.dirtyex = 0; return; } exit(0); case CTRL_KEY('q'): exit(0); case CTRL_KEY('r'): if (EDIRTY && editor.dirtyex) { editor_set_status("File not saved - C-k C-r again to reload."); editor.dirtyex = 0; return; } jumpx = ECURX; jumpy = ECURY; buf = strdup(EFILENAME); reset_editor(); open_file(buf); display_refresh(); free(buf); jump_to_position(jumpx, jumpy); editor_set_status("file reloaded"); break; case CTRL_KEY('s'): case 's': save_file(); break; case CTRL_KEY('x'): case 'x': exit(save_file()); case 'u': reps = uarg_get(); while (reps--) {} editor_set_status("Undo not implemented."); break; case 'U': reps = uarg_get(); while (reps--) {} editor_set_status("Redo not implemented."); break; case 'y': reps = uarg_get(); while (reps--) { killring_yank(); } break; case ESC_KEY: case CTRL_KEY('g'): break; default: if (isprint(c)) { editor_set_status("unknown kcommand '%c'", c); break; } editor_set_status("unknown kcommand: %04x", c); return; } editor.dirtyex = 1; } void process_normal(int16_t c) { size_t cols = 0; size_t rows = 0; int reps = 0; /* C-u handling – must be the very first thing */ if (c == CTRL_KEY('u')) { uarg_start(); return; } /* digits after a C-u are part of the argument */ if (editor.uarg && c >= '0' && c <= '9') { uarg_digit(c - '0'); return; } if (is_arrow_key(c)) { /* moving the cursor breaks a delete sequence */ editor.kill = 0; move_cursor(c, 1); return; } switch (c) { case '\r': newline(); break; case CTRL_KEY('k'): editor.mode = MODE_KCOMMAND; return; case BACKSPACE: case CTRL_KEY('h'): case CTRL_KEY('d'): case DEL_KEY: if (c == DEL_KEY || c == CTRL_KEY('d')) { reps = uarg_get(); while (reps-- > 0) { move_cursor(ARROW_RIGHT, 1); deletech(KILLRING_APPEND); } } else { reps = uarg_get(); while (reps-- > 0) { deletech(KILLRING_PREPEND); } } break; case CTRL_KEY('a'): /* beginning of line */ case HOME_KEY: move_cursor(CTRL_KEY('a'), 1); break; case CTRL_KEY('e'): /* end of line */ case END_KEY: move_cursor(CTRL_KEY('e'), 1); break; case CTRL_KEY('g'): break; case CTRL_KEY('l'): if (get_winsz(&rows, &cols) == 0) { editor.rows = rows; editor.cols = cols; } else { editor_set_status("Couldn't update window size."); } display_refresh(); break; case CTRL_KEY('s'): editor_find(); break; case CTRL_KEY('w'): kill_region(); delete_region(); toggle_markset(); break; case CTRL_KEY('y'): reps = uarg_get(); while (reps-- > 0) { killring_yank(); } break; case ESC_KEY: editor.mode = MODE_ESCAPE; break; default: if (c == TAB_KEY) { reps = uarg_get(); while (reps-- > 0) { insertch(c); } } else if (c >= 0x20 && c != 0x7f) { reps = uarg_get(); while (reps-- > 0) { insertch(c); } } break; } editor.dirtyex = 1; } void process_escape(const int16_t c) { int reps = 0; editor_set_status("hi"); switch (c) { case '>': ECURY = ENROWS; ECURX = 0; break; case '<': ECURY = 0; ECURX = 0; break; case 'b': reps = uarg_get(); while (reps--) { find_prev_word(); } break; case 'd': reps = uarg_get(); while (reps--) { delete_next_word(); } break; case 'f': reps = uarg_get(); while (reps--) { find_next_word(); } break; case 'm': toggle_markset(); break; case 'w': if (!EMARK_SET) { editor_set_status("mark isn't set"); break; } kill_region(); toggle_markset(); break; case BACKSPACE: reps = uarg_get(); while (reps--) { delete_prev_word(); } break; case ESC_KEY: case CTRL_KEY('g'): break; /* escape from escape-mode the movie */ default: editor_set_status("unknown ESC key: %04x", c); } uarg_clear(); } int process_keypress(void) { const int16_t c = get_keypress(); if (c <= 0) { return 0; } switch (editor.mode) { case MODE_KCOMMAND: process_kcommand(c); editor.mode = MODE_NORMAL; break; case MODE_NORMAL: process_normal(c); break; case MODE_ESCAPE: process_escape(c); editor.mode = MODE_NORMAL; break; default: editor_set_status("we're in the %d-D space now cap'n", editor.mode); editor.mode = MODE_NORMAL; } return 1; }