123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /* main.c, Ait, BSD 3-Clause, Kevin Bloom, 2023-2024,
- Derived from: Atto January 2017
- Derived from: Anthony's Editor January 93
- */
- #include "header.h"
- #include "termbox.h"
- #include "util.h"
- int done;
- kill_t scrap = { NULL, 0 };
- kill_t kill_ring[KILLRING_SIZE];
- char_t input[K_BUFFER_LENGTH];
- char_t *tinput;
- int msgflag;
- char msgline[TEMPBUF];
- char temp[TEMPBUF];
- char *gtemp = NULL;
- char searchtext[STRBUF_L];
- char replace[STRBUF_L];
- int found_point = -1;
- int search_dir = 1;
- int universal_argument = 0;
- int numeric_argument = 0;
- int negated = FALSE;
- int submatch = 0;
- uint32_t input_char = 0;
- int undoset_flag = FALSE;
- char editor_dir[PATH_MAX+1];
- int record_input = FALSE;
- int record_buffer_index = 0;
- int run_buffer_index = 0;
- struct tb_event record_buffer[256];
- int execute_kbd_macro = FALSE;
- int undo_index = -1;
- char unicode_buf[7];
- char character[1];
- int lastcommand = KBD_DEFAULT;
- int currentcommand = KBD_DEFAULT;
- int window_mode = WINDOW_DEFAULT;
- int ignorenotbound = FALSE;
- char *backup_dir = NULL;
- char *switch_command = NULL;
- int lastcol = 0;
- int lastline = 0;
- char lastchar = 0;
- char lastsymb = 0;
- point_t recentbracket = -1;
- const char* term;
- dyna_t dynaex;
- keymap_t *key_return;
- keymap_t *key_map;
- buffer_t *curbp; /* current buffer */
- buffer_t *bheadp; /* head of list of buffers */
- window_t *curwp;
- window_t *wheadp;
- buffer_t *lastbp = NULL; /* last active buffer */
- int LINES;
- int COLS;
- int MSGLINE; /* */
- static void graceful_exit()
- {
- tb_shutdown();
- exit(1);
- }
- static void cont()
- {
- int ol = LINES, oc = COLS;
- tb_init();
- LINES = tb_height();
- COLS = tb_width();
- MSGLINE = LINES-1;
- tb_set_input_mode(TB_INPUT_ALT);
- tb_clear();
- if(ol != LINES || oc != COLS)
- resize();
- update_display();
- redraw();
- }
- static void setup_signal_handlers()
- {
- struct sigaction action;
- memset(&action, 0, sizeof(struct sigaction));
- action.sa_handler = graceful_exit;
- sigaction(SIGTERM, &action, NULL);
- sigaction(SIGINT, &action, NULL);
- sigaction(SIGQUIT, &action, NULL);
- sigaction(SIGHUP, &action, NULL);
- action.sa_handler = cont;
- sigaction(SIGCONT, &action, NULL);
- signal(SIGPIPE, SIG_IGN);
- }
- void check_flags(char **argv, int idx)
- {
- if(!strcmp(argv[idx], "-v")) {
- fprintf(stderr, "%s\n", VERSION);
- exit(0);
- }
- if(!strcmp(argv[idx], "-h")) {
- fprintf(stderr, "%s\n\nUsage: ait [vh] [file]... +/-line...\n ait [-b backup_dir] [file]... +/-line...\n\n-h Print help and exit\n-v Print version and exit\n-b backup_dir Set the backup directory\n\n", VERSION);
- exit(0);
- }
- return;
- }
- int main(int argc, char **argv)
- {
- int ret, u, buffers = 0;
- int line = 0, current = 0, lastln = 0;
- int args = 0, v = 1;
- point_t p;
- if(1 < argc) {
- for(int i = argc - 1; i > 1; i--)
- check_flags(argv, i);
- if(!strcmp(argv[1], "-b") && argc >= 2) {
- if((backup_dir = strdup(argv[2])) == NULL) {
- fatal("%s: Failed to allocate required memory.\n");
- }
- }
- if(argc >= 2 && !strcmp(argv[1], "-s") && backup_dir == NULL) {
- if((switch_command = strdup(argv[2])) == NULL) {
- fatal("%s: Failed to allocate required memory.\n");
- }
- }
- if(argc >= 4 && !strcmp(argv[3], "-s")) {
- if((switch_command = strdup(argv[4])) == NULL) {
- fatal("%s: Failed to allocate required memory.\n");
- }
- }
- }
- ret = tb_init();
- LINES = tb_height();
- COLS = tb_width();
- MSGLINE = LINES-1;
- character[0] = '\0';
- term = getenv("LANG");
- dynaex.query = NULL;
- dynaex.nquery = -1;
- dynaex.nresult = -1;
- dynaex.start = -1;
- dynaex.end = -1;
- dynaex.sp = -1;
- if (ret) {
- fprintf(stderr, "Failed with error code %d", ret);
- exit(1);
- }
- getcwd(editor_dir, sizeof(editor_dir));
- strcat(editor_dir, "/");
- tb_set_input_mode(TB_INPUT_ALT);
- // tb_set_output_mode(TB_OUTPUT_216);
- tb_clear();
- setup_signal_handlers();
- // initialize the kill-ring
- for(int i = KILLRING_SIZE-1; i > 0; i--) {
- struct kill_t k;
- k.data = NULL;
- k.len = 0;
- kill_ring[i] = k;
- }
- /* TODO: this is really dumb... */
- if(backup_dir == NULL && switch_command == NULL) {
- args = 1 < argc;
- v = 1;
- } else if(backup_dir != NULL && switch_command != NULL) {
- args = 5 < argc;
- v = 5;
- } else if(backup_dir != NULL || switch_command != NULL) {
- args = 3 < argc;
- v = 3;
- }
- if (args) {
- for(; v < argc; v++) {
- buffers++;
- curbp = find_buffer(argv[v], TRUE, TRUE);
- (void) insert_file(argv[v], FALSE);
- /* Save filename regardless of load() success. */
- if(argv[v][0] == '/') {
- strncpy(curbp->b_fname, argv[v], PATH_MAX);
- } else if(argv[v][0] == '-') {
- check_flags(argv, v);
- } else {
- strncpy(curbp->b_fname, editor_dir, PATH_MAX);
- strcat(curbp->b_fname, argv[v]);
- cleanup_path(curbp->b_fname, curbp->b_fname);
- }
- curbp->b_fname[PATH_MAX] = '\0'; /* force truncation */
- curbp->b_path = TRUE;
- curbp->b_line = 1;
- curbp->b_pcol = 0;
- if (!growgap(curbp, CHUNK))
- fatal("%s: Failed to allocate required memory.\n");
- movegap(curbp, 0);
- if(argv[v+1]) {
- if(argv[v+1][0] == '-' || argv[v+1][0] == '+') {
- if(argv[v+1][0] == '+') {
- argv[v+1]++;
- line = atoi(argv[v+1]);
- } else {
- argv[v+1]++;
- get_line_stats(¤t, &lastln, curbp);
- line = lastln - atoi(argv[v+1]);
- if(line < 0)
- line = 0;
- }
- p = line_to_point(line);
- if (p != -1) {
- curbp->b_point = p;
- curbp->b_opoint = p;
- curbp->b_cpoint = p;
- if (curbp->b_epage < pos(curbp, curbp->b_ebuf)) curbp->b_reframe = 1;
- curbp->b_line = line;
- msg("Line %d", line);
- } else {
- msg("Line %d, not found", line);
- }
- v++;
- }
- }
- }
- } else {
- curbp = find_buffer("*scratch*", TRUE, TRUE);
- strncpy(curbp->b_bname, "*scratch*", STRBUF_S);
- curbp->b_path = FALSE;
- }
- key_map = keymap;
- submatch = 0;
- wheadp = curwp = new_window();
- associate_b2w(curbp, curwp);
- one_window(curwp);
- if(buffers > 1) {
- chop_window();
- if(curbp->b_next == NULL)
- next_buffer();
- }
- while (!done) {
- update_display();
- if(curwp->w_recenter) {
- recenter();
- curwp->w_recenter = FALSE;
- update_display();
- }
- recentbracket = -1;
- curbp->b_opoint = curbp->b_point;
- curbp->b_opage = curbp->b_page;
- tinput = get_key(key_map, &key_return);
- strcpy((char *)input, (const char *)tinput);
- if (key_return != NULL) {
- /* TODO: a better way to figure out editing commands */
- if(key_return->key_desc[2] == 'd' || key_return->key_desc[4] == '%' ||
- key_return->key_desc[2] == 'i' || key_return->key_desc[2] == 'k' ||
- key_return->key_desc[2] == '/' || key_return->key_desc[2] == 'm' ||
- key_return->key_desc[2] == 't' || key_return->key_desc[2] == 'y' ||
- key_return->key_desc[4] == 'd' || key_return->key_desc[4] == 'i' ||
- key_return->key_desc[4] == 't' || key_return->key_desc[4] == '\\' ||
- key_return->key_desc[4] == 'k' || key_return->key_desc[4] == '/' ||
- key_return->key_desc[4] == 'l' || key_return->key_desc[4] == 'c' ||
- key_return->key_desc[4] == 'z' ||
- key_return->key_desc[4] == 'Z' || (key_return->key_desc[4] == 'b'
- && key_return->key_desc[5] == 'k') || key_return->key_desc[2] == 'h') {
- if(key_return->key_bytes[0] != TB_KEY_CTRL_W && key_return->key_bytes[0] != TB_KEY_PGDN)
- curbp->b_mark = NOMARK;
- if(is_file_modified(curbp->b_fname) && !file_was_modified_prompt()) {
- continue;
- }
- }
- submatch = 0;
- if(execute_kbd_macro) {
- (key_return->func)();
- } else {
- u = numeric_argument > 0 ? numeric_argument : power(4, universal_argument);
- if(numeric_argument > 0 &&
- key_return->universal_argument_action != UA_PREVENT)
- key_return->universal_argument_action = UA_REPEAT;
- switch(key_return->universal_argument_action) {
- case UA_REPEAT:
- if(u > 1)
- shift_pmark(TRUE, curbp->b_point);
- for(; u > 0; u--)
- (key_return->func)();
- universal_argument = 0;
- numeric_argument = 0;
- /* For gotochar */
- character[0] = '\0';
- if(curbp->b_point > curbp->b_epage || curbp->b_point < curbp->b_page)
- curbp->b_reframe = TRUE;
- break;
- default:
- (key_return->func)();
- break;
- }
- }
- if(temp[0] != 0)
- memset(temp, 0, TEMPBUF);
- if(key_return->key_desc[2] != 'u')
- universal_argument = 0;
- } else if(submatch > 0) {
- // do nothing
- } else {
- submatch = 0;
- if(unicode_buf[0] != '\0' || *input > 31 || *input == 13 || *input == 9) {
- curbp->b_mark = NOMARK;
- if(is_file_modified(curbp->b_fname) && !file_was_modified_prompt()) {
- continue;
- }
- }
- if(unicode_buf[0] != '\0') {
- if(!execute_kbd_macro)
- u = numeric_argument > 0 ? numeric_argument : power(4, universal_argument);
- else
- u = 1;
- char tempbuf[7];
- strncpy(tempbuf, unicode_buf, 7);
- for(; u > 0; u--) {
- unicode_buf[0] = tempbuf[0];
- insert_unicode();
- }
- if(is_bracket(input[0], FALSE, NULL)) {
- int dir = (input[0] == '}' || input[0] == ']' || input[0] == ')' || input[0] == '>');
- curbp->b_point--;
- recentbracket = find_matching_bracket(curbp, curwp, dir ? -1 : 1, TRUE);
- curbp->b_point++;
- }
- }
- else if(!ignorenotbound)
- msg("Not bound");
- else if(ignorenotbound) {
- msg("");
- ignorenotbound = FALSE;
- }
- if(!execute_kbd_macro) {
- universal_argument = 0;
- numeric_argument = 0;
- }
- }
- /* For gotochar */
- character[0] = '\0';
- if(currentcommand != KBD_DELETE_CHAR &&
- currentcommand != KBD_DELETE_WORD &&
- currentcommand != KBD_CUT &&
- currentcommand != KBD_EXPAND &&
- currentcommand != KBD_UNDO
- ) {
- if(curbp->b_opoint > curbp->b_point) {
- curbp->b_opoint--;
- while(curbp->b_opoint >= curbp->b_point) {
- if(*ptr(curbp, curbp->b_opoint) == '\n')
- curbp->b_line--;
- curbp->b_opoint--;
- }
- } else if(curbp->b_opoint < curbp->b_point) { /* */
- while(curbp->b_opoint < curbp->b_point) {
- if(*ptr(curbp, curbp->b_opoint) == '\n')
- curbp->b_line++;
- curbp->b_opoint++;
- }
- }
- }
- if(currentcommand != lastcommand) {
- if(lastcommand == KBD_EXPAND) {
- if(dynaex.query != NULL) {
- free(dynaex.query);
- dynaex.query = NULL;
- }
- dynaex.nquery = -1;
- dynaex.nresult = -1;
- dynaex.start = -1;
- dynaex.end = -1;
- dynaex.sp = -1;
- dynars_t *dr;
- dr = dynaex.results;
- while(dynaex.results != NULL) {
- dr = dynaex.results;
- dynaex.results = dynaex.results->d_next;
- if(dr->result != NULL) {
- free(dr->result);
- dr->result = NULL;
- }
- if(dr != NULL) {
- free(dr);
- dr = NULL;
- }
- }
- }
- lastcommand = currentcommand;
- }
- currentcommand = KBD_DEFAULT;
- }
- if (scrap.data != NULL) free(scrap.data);
- tb_set_cursor(0, LINES-1);
- tb_present();
- tb_shutdown();
- return 0;
- }
- void fatal(char *msg)
- {
- tb_present();
- fprintf(stderr, msg, PROG_NAME);
- exit(1);
- }
- void msg(char *msg, ...)
- {
- va_list args;
- va_start(args, msg);
- (void)vsprintf(msgline, msg, args);
- va_end(args);
- msgflag = TRUE;
- if(strlen(msgline) > COLS) {
- msgline[COLS] = '\0';
- }
- }
|