search.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* search.c, Ait, BSD 3-Clause, Kevin Bloom, 2023,
  2. Derived from: Atto January 2017
  3. Derived from: Anthony's Editor January 93
  4. */
  5. #include "header.h"
  6. #include "termbox.h"
  7. #define FWD_SEARCH 1
  8. #define REV_SEARCH 2
  9. void search_fwd()
  10. {
  11. search(FWD_SEARCH);
  12. }
  13. void search_rev()
  14. {
  15. search(REV_SEARCH);
  16. }
  17. void search(int initdir)
  18. {
  19. char *prompt = "Search: ";
  20. char *failing_prompt = "Failing Search: ";
  21. int cpos = 0;
  22. int c, dir = initdir, failed_search = FALSE;
  23. point_t o_point = curbp->b_point;
  24. point_t found = o_point;
  25. int start_col = strlen(prompt);
  26. struct tb_event ev;
  27. char prev_search[STRBUF_M];
  28. strcpy(prev_search, searchtext);
  29. // searchtext[0] = '\0';
  30. memset(searchtext, 0, STRBUF_M);
  31. display_prompt_and_response(prompt, searchtext);
  32. cpos = strlen(searchtext);
  33. for (;;) {
  34. tb_present();
  35. if(tb_poll_event(&ev) != TB_OK) return;
  36. start_col = found == -1 ? strlen(failing_prompt) : strlen(prompt);
  37. if(msgline_editor(ev, found == -1 ? failing_prompt : prompt, searchtext, &cpos)) {
  38. // if(dir == FWD_SEARCH)
  39. // found = search_forward(curbp, o_point, searchtext);
  40. // else
  41. // found = search_backwards(curbp, o_point, searchtext);
  42. // display_search_result(found, dir, prompt, searchtext, &failed_search);
  43. continue;
  44. }
  45. if(!ev.mod)
  46. c = ev.ch;
  47. else
  48. c = ev.key;
  49. /* ignore control keys other than return, C-g, CR, C-s, C-R, ESC */
  50. if (c < 32 &&
  51. c != TB_KEY_CTRL_G &&
  52. c != TB_KEY_ENTER &&
  53. c != TB_KEY_CTRL_R &&
  54. c != TB_KEY_CTRL_S &&
  55. c != TB_KEY_ESC)
  56. continue;
  57. switch(c) {
  58. case TB_KEY_ENTER: /* return */
  59. if(found != o_point) {
  60. found_point = -1;
  61. return;
  62. }
  63. found = search_forward(curbp, curbp->b_point, searchtext);
  64. display_search_result(found, FWD_SEARCH, prompt, searchtext, &failed_search);
  65. break;
  66. case TB_KEY_ESC: /* esc */
  67. case TB_KEY_CTRL_G: /* ctrl-g */
  68. found_point = -1;
  69. curbp->b_point = o_point;
  70. return;
  71. case TB_KEY_CTRL_S: /* ctrl-s, do the search */
  72. if(searchtext[0] == '\0') {
  73. strcpy(searchtext, prev_search);
  74. }
  75. cpos = strlen(searchtext);
  76. found = search_forward(curbp, curbp->b_point, searchtext);
  77. if(found == -1 && failed_search)
  78. found = search_forward(curbp, 0, searchtext);
  79. display_search_result(found, FWD_SEARCH, prompt, searchtext, &failed_search);
  80. dir = FWD_SEARCH;
  81. break;
  82. case TB_KEY_CTRL_R: /* ctrl-r, do the search */
  83. if(searchtext[0] == '\0') {
  84. strcpy(searchtext, prev_search);
  85. }
  86. cpos = strlen(searchtext);
  87. found = search_backwards(curbp, curbp->b_point-1, searchtext);
  88. if(found == -1 && failed_search)
  89. found = search_backwards(curbp, pos(curbp, curbp->b_ebuf), searchtext);
  90. display_search_result(found, REV_SEARCH, prompt, searchtext, &failed_search);
  91. dir = REV_SEARCH;
  92. break;
  93. case TB_KEY_BACKSPACE2: /* del, erase */
  94. case TB_KEY_BACKSPACE: /* backspace */
  95. if (cpos == 0)
  96. continue;
  97. searchtext[--cpos] = '\0';
  98. tb_set_cursor(start_col + cpos, MSGLINE);
  99. display_prompt_and_response(prompt, searchtext);
  100. break;
  101. default:
  102. if (cpos < STRBUF_M - 1) {
  103. for(int i = strlen(searchtext); i > cpos; i--) {
  104. searchtext[i] = searchtext[i - 1];
  105. }
  106. searchtext[cpos] = c;
  107. tb_set_cursor(start_col, MSGLINE);
  108. addstr(searchtext);
  109. cpos++;
  110. tb_set_cursor(start_col + cpos, MSGLINE);
  111. if(cpos == strlen(searchtext)) {
  112. if(dir == FWD_SEARCH)
  113. found = search_forward(curbp, o_point, searchtext);
  114. else
  115. found = search_backwards(curbp, o_point, searchtext);
  116. display_search_result(found, dir, prompt, searchtext, &failed_search);
  117. }
  118. }
  119. break;
  120. }
  121. }
  122. }
  123. void display_search_result(point_t found, int dir, char *prompt, char *search, int *failed_search)
  124. {
  125. int i = curwp->w_rows / 2, found_end = FALSE, shift = 0;
  126. point_t new_page = 0;
  127. if (found != -1 ) {
  128. search_dir = dir;
  129. tb_clear();
  130. found_point = found;
  131. curbp->b_point = dir == 2 ? found + 1 : found;
  132. update_display(2);
  133. msg("%s%s",prompt, search);
  134. new_page = curbp->b_page;
  135. shift = curwp->w_row - i;
  136. if(dir == FWD_SEARCH) {
  137. for(int k = shift; k > 0; k--) {
  138. found_end = FALSE;
  139. while(found_end == FALSE) {
  140. if(*ptr(curbp, new_page) == '\n')
  141. found_end = TRUE;
  142. new_page++;
  143. }
  144. }
  145. } else {
  146. for(int k = shift; k < 0; k++) {
  147. new_page = lnstart(curbp,new_page - 1);
  148. }
  149. }
  150. curbp->b_page = lnstart(curbp, new_page);
  151. update_display(2);
  152. *failed_search = FALSE;
  153. } else {
  154. found_point = -1;
  155. msg("Failing %s%s",prompt, search);
  156. dispmsg();
  157. *failed_search = TRUE;
  158. }
  159. }
  160. point_t search_forward(buffer_t *bp, point_t start_p, char *stext)
  161. {
  162. point_t end_p = pos(bp, bp->b_ebuf);
  163. point_t p,pp;
  164. char* s;
  165. char_t * cur;
  166. int case_sense = FALSE;
  167. if (0 == strlen(stext))
  168. return start_p;
  169. for (p=start_p; p < end_p; p++) {
  170. for (s=stext, pp=p; *s !='\0' && pp < end_p; s++, pp++) {
  171. cur = ptr(bp, pp);
  172. if(isupper(*s)) {
  173. case_sense = TRUE;
  174. if(*s != *cur)
  175. break;
  176. }
  177. else if (*s != *cur && case_sense)
  178. break;
  179. else if(*s != tolower(*cur))
  180. break;
  181. }
  182. if (*s == '\0')
  183. return pp;
  184. }
  185. return -1;
  186. }
  187. point_t search_backwards(buffer_t *bp, point_t start_p, char *stext)
  188. {
  189. point_t p,pp;
  190. char* s;
  191. char_t * cur;
  192. int case_sense = FALSE;
  193. if (0 == strlen(stext))
  194. return start_p;
  195. for (p=start_p; p >= 0; p--) {
  196. for (s=stext, pp=p; *s != '\0' && pp > -1; s++, pp++) {
  197. cur = ptr(bp, pp);
  198. if(isupper(*s)) {
  199. case_sense = TRUE;
  200. if(*s != *cur)
  201. break;
  202. }
  203. else if (*s != *cur && case_sense)
  204. break;
  205. else if(*s != tolower(*cur))
  206. break;
  207. }
  208. if (*s == '\0') {
  209. if (p > 0)
  210. p--;
  211. return p;
  212. }
  213. }
  214. return -1;
  215. }