search.c 5.5 KB

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