123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /* search.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"
- #define FWD_SEARCH 1
- #define REV_SEARCH 2
- void search_fwd()
- {
- search(FWD_SEARCH);
- }
- void search_rev()
- {
- search(REV_SEARCH);
- }
- void search(int initdir)
- {
- char *prompt = "Search: ";
- char *failing_prompt = "Failing Search: ";
- int cpos = 0;
- int c, dir = initdir, failed_search = FALSE;
- point_t o_point = curbp->b_point, o_page = curbp->b_page;
- point_t found = o_point;
- int start_col = strlen(prompt);
- struct tb_event ev;
- char prev_search[STRBUF_L];
- strcpy(prev_search, searchtext);
- memset(searchtext, 0, STRBUF_L);
- display_prompt_and_response(prompt, searchtext);
- cpos = strlen(searchtext);
- for (;;) {
- tb_present();
- if(execute_kbd_macro) {
- use_kbd_macro(&ev);
- } else if(tb_poll_event(&ev) != TB_OK) return;
- if(record_input) {
- record_buffer[record_buffer_index] = ev;
- record_buffer_index++;
- }
- start_col = found == -1 ? strlen(failing_prompt) : strlen(prompt);
- if(msgline_editor(ev, found == -1 ? failing_prompt : prompt, searchtext, STRBUF_L, &cpos)) {
- if(ev.key == TB_KEY_CTRL_Y) {
- if(dir == FWD_SEARCH)
- found = search_forward(curbp, o_point, searchtext);
- else
- found = search_backwards(curbp, o_point, searchtext);
- display_search_result(found, dir, prompt, searchtext, &failed_search);
- }
- continue;
- }
- if(!ev.mod)
- c = ev.ch;
- else
- c = ev.key;
- /* ignore control keys other than return, C-g, CR, C-s, C-R, ESC */
- if (c < 32 &&
- c != TB_KEY_CTRL_G &&
- c != TB_KEY_ENTER &&
- c != TB_KEY_CTRL_R &&
- c != TB_KEY_CTRL_S &&
- c != TB_KEY_ESC)
- continue;
- switch(c) {
- case TB_KEY_ENTER: /* return */
- if(found != o_point) {
- shift_pmark(TRUE, o_point);
- shift_pmark(TRUE, curbp->b_point);
- found_point = -1;
- return;
- }
- found = search_forward(curbp, curbp->b_point, searchtext);
- display_search_result(found, FWD_SEARCH, prompt, searchtext, &failed_search);
- curbp->b_pcol = curbp->b_col;
- break;
- case TB_KEY_ESC: /* esc */
- case TB_KEY_CTRL_G: /* ctrl-g */
- found_point = -1;
- curbp->b_point = o_point;
- curbp->b_page = o_page;
- return;
- case TB_KEY_CTRL_S: /* ctrl-s, do the search */
- if(searchtext[0] == '\0') {
- strcpy(searchtext, prev_search);
- }
- cpos = strlen(searchtext);
- found = search_forward(curbp, curbp->b_point, searchtext);
- if(found == -1 && failed_search)
- found = search_forward(curbp, 0, searchtext);
- display_search_result(found, FWD_SEARCH, prompt, searchtext, &failed_search);
- dir = FWD_SEARCH;
- break;
- case TB_KEY_CTRL_R: /* ctrl-r, do the search */
- if(searchtext[0] == '\0') {
- strcpy(searchtext, prev_search);
- }
- cpos = strlen(searchtext);
- found = search_backwards(curbp, curbp->b_point-1, searchtext);
- if(found == -1 && failed_search)
- found = search_backwards(curbp, pos(curbp, curbp->b_ebuf), searchtext);
- display_search_result(found, REV_SEARCH, prompt, searchtext, &failed_search);
- dir = REV_SEARCH;
- break;
- case TB_KEY_BACKSPACE2: /* del, erase */
- case TB_KEY_BACKSPACE: /* backspace */
- if (cpos == 0)
- continue;
- searchtext[--cpos] = '\0';
- tb_set_cursor(start_col + cpos, MSGLINE);
- display_prompt_and_response(prompt, searchtext);
- break;
- default:
- if (cpos < STRBUF_L - 1) {
- for(int i = strlen(searchtext); i > cpos; i--) {
- searchtext[i] = searchtext[i - 1];
- }
- searchtext[cpos] = c;
- tb_set_cursor(start_col, MSGLINE);
- addstr(searchtext);
- cpos++;
- tb_set_cursor(start_col + cpos, MSGLINE);
- if(cpos == strlen(searchtext)) {
- if(dir == FWD_SEARCH)
- found = search_forward(curbp, o_point, searchtext);
- else
- found = search_backwards(curbp, o_point, searchtext);
- display_search_result(found, dir, prompt, searchtext, &failed_search);
- }
- }
- break;
- }
- }
- }
- void display_search_result(point_t found, int dir, char *prompt, char *search, int *failed_search)
- {
- int i = curwp->w_rows / 2, found_end = FALSE, shift = 0;
- point_t new_page = 0;
- if (found != -1 ) {
- search_dir = dir;
- // tb_clear();
- found_point = found;
- curbp->b_point = dir == 2 ? found + 1 : found;
- update_display();
- msg("%s%s",prompt, search);
- new_page = curbp->b_page;
- shift = curwp->w_row - i;
- if(dir == FWD_SEARCH) {
- for(int k = shift; k > 0; k--) {
- found_end = FALSE;
- while(found_end == FALSE) {
- if(*ptr(curbp, new_page) == '\n')
- found_end = TRUE;
- new_page++;
- }
- }
- } else {
- for(int k = shift; k < 0; k++) {
- new_page = lnstart(curbp,new_page - 1);
- }
- }
- curbp->b_page = lnstart(curbp, new_page);
- update_display();
- *failed_search = FALSE;
- } else {
- found_point = -1;
- msg("Failing %s%s",prompt, search);
- dispmsg();
- *failed_search = TRUE;
- }
- }
- point_t search_forward(buffer_t *bp, point_t start_p, char *stext)
- {
- point_t end_p = pos(bp, bp->b_ebuf);
- point_t p,pp;
- char* s;
- char_t * cur;
- int case_sense = FALSE;
- if (0 == strlen(stext))
- return start_p;
- for (p=start_p; p < end_p; p++) {
- for (s=stext, pp=p; *s !='\0' && pp < end_p; s++, pp++) {
- cur = ptr(bp, pp);
- if(isupper(*s)) {
- case_sense = TRUE;
- if(*s != *cur)
- break;
- }
- else if (*s != *cur && case_sense)
- break;
- else if(*s != tolower(*cur))
- break;
- }
- if (*s == '\0')
- return pp;
- }
- return -1;
- }
- point_t search_backwards(buffer_t *bp, point_t start_p, char *stext)
- {
- point_t p,pp;
- char* s;
- char_t * cur;
- int case_sense = FALSE;
- if (0 == strlen(stext))
- return start_p;
- for (p=start_p; p >= 0; p--) {
- for (s=stext, pp=p; *s != '\0' && pp > -1; s++, pp++) {
- cur = ptr(bp, pp);
- if(isupper(*s)) {
- case_sense = TRUE;
- if(*s != *cur)
- break;
- }
- else if (*s != *cur && case_sense)
- break;
- else if(*s != tolower(*cur))
- break;
- }
- if (*s == '\0') {
- if (p > 0)
- p--;
- return p;
- }
- }
- return -1;
- }
|