replace.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* replace.c, Ait Emacs, Kevin Bloom, BSD 3-Clause, 2023 */
  2. #include <string.h>
  3. #include "header.h"
  4. #include "termbox.h"
  5. /*search for a string and replace it with another string */
  6. void query_replace(void)
  7. {
  8. point_t o_point = curbp->b_point;
  9. point_t l_point = -1;
  10. point_t found;
  11. char question[STRBUF_L];
  12. int slen, rlen; /* length of search and replace strings */
  13. int numsub = 0; /* number of substitutions */
  14. int ask = TRUE;
  15. int c;
  16. struct tb_event ev;
  17. undoset();
  18. memset(searchtext, 0, STRBUF_M);
  19. memset(replace, 0, STRBUF_M);
  20. if (!getinput("Query replace: ", (char*)searchtext, STRBUF_M, F_CLEAR, FALSE))
  21. return;
  22. if (!getinput("With: ", (char*)replace, STRBUF_M, F_CLEAR, TRUE))
  23. return;
  24. slen = strlen(searchtext);
  25. rlen = strlen(replace);
  26. /* build query replace question string */
  27. sprintf(question, "Replace '%s' with '%s' ? ", searchtext, replace);
  28. /* scan through the file, from point */
  29. numsub = 0;
  30. while(TRUE) {
  31. found = search_forward(curbp, curbp->b_point, searchtext);
  32. /* if not found set the point to the last point of replacement, or where we started */
  33. if (found == -1) {
  34. curbp->b_point = (l_point == -1 ? o_point : l_point);
  35. break;
  36. }
  37. curbp->b_point = found;
  38. /* search_forward places point at end of search, move to start of search */
  39. curbp->b_point -= slen;
  40. search_dir = 1;
  41. found_point = found;
  42. if (ask == TRUE) {
  43. msg(question);
  44. clrtoeol(question, MSGLINE);
  45. qprompt:
  46. update_display(TRUE);
  47. if(tb_poll_event(&ev) != TB_OK) return;
  48. if(!ev.mod)
  49. c = ev.ch;
  50. else
  51. c = ev.key;
  52. switch (c) {
  53. case 'y': /* yes, substitute */
  54. break;
  55. case 'n': /* no, find next */
  56. curbp->b_point = found; /* set to end of search string */
  57. continue;
  58. case '!': /* yes/stop asking, do the lot */
  59. ask = FALSE;
  60. found_point = -1;
  61. break;
  62. case TB_KEY_CTRL_G:
  63. case TB_KEY_ESC: /* esc */
  64. found_point = -1;
  65. case 'q': /* controlled exit */
  66. found_point = -1;
  67. return;
  68. default: /* help me */
  69. msg("(y)es, (n)o, (!)do the rest, (q)uit");
  70. goto qprompt;
  71. }
  72. }
  73. if (rlen > slen) {
  74. movegap(curbp, found);
  75. /*check enough space in gap left */
  76. if (rlen - slen < curbp->b_egap - curbp->b_gap)
  77. growgap(curbp, rlen - slen);
  78. /* shrink gap right by r - s */
  79. curbp->b_gap = curbp->b_gap + (rlen - slen);
  80. } else if (slen > rlen) {
  81. movegap(curbp, found);
  82. /* stretch gap left by s - r, no need to worry about space */
  83. curbp->b_gap = curbp->b_gap - (slen - rlen);
  84. } else {
  85. /* if rlen = slen, we just overwrite the chars, no need to move gap */
  86. }
  87. /* now just overwrite the chars at point in the buffer */
  88. l_point = curbp->b_point;
  89. memcpy(ptr(curbp, curbp->b_point), replace, rlen * sizeof (char_t));
  90. curbp->b_flags |= B_MODIFIED;
  91. curbp->b_point = found - (slen - rlen); /* end of replcement */
  92. numsub++;
  93. }
  94. found_point = -1;
  95. msg("%d substitutions", numsub);
  96. }