undo.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /* readline.c -- a general facility for reading lines of input
  2. with emacs style editing and completion. */
  3. /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
  4. This file is part of the GNU Readline Library (Readline), a library
  5. for reading lines of text with interactive input and history editing.
  6. Readline is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Readline is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Readline. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #define READLINE_LIBRARY
  18. #if defined (HAVE_CONFIG_H)
  19. # include <config.h>
  20. #endif
  21. #include <sys/types.h>
  22. #if defined (HAVE_UNISTD_H)
  23. # include <unistd.h> /* for _POSIX_VERSION */
  24. #endif /* HAVE_UNISTD_H */
  25. #if defined (HAVE_STDLIB_H)
  26. # include <stdlib.h>
  27. #else
  28. # include "ansi_stdlib.h"
  29. #endif /* HAVE_STDLIB_H */
  30. #include <stdio.h>
  31. /* System-specific feature definitions and include files. */
  32. #include "rldefs.h"
  33. /* Some standard library routines. */
  34. #include "readline.h"
  35. #include "history.h"
  36. #include "rlprivate.h"
  37. #include "xmalloc.h"
  38. extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
  39. /* Non-zero tells rl_delete_text and rl_insert_text to not add to
  40. the undo list. */
  41. int _rl_doing_an_undo = 0;
  42. /* How many unclosed undo groups we currently have. */
  43. int _rl_undo_group_level = 0;
  44. /* The current undo list for THE_LINE. */
  45. UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
  46. /* **************************************************************** */
  47. /* */
  48. /* Undo, and Undoing */
  49. /* */
  50. /* **************************************************************** */
  51. static UNDO_LIST *
  52. alloc_undo_entry (what, start, end, text)
  53. enum undo_code what;
  54. int start, end;
  55. char *text;
  56. {
  57. UNDO_LIST *temp;
  58. temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
  59. temp->what = what;
  60. temp->start = start;
  61. temp->end = end;
  62. temp->text = text;
  63. temp->next = (UNDO_LIST *)NULL;
  64. return temp;
  65. }
  66. /* Remember how to undo something. Concatenate some undos if that
  67. seems right. */
  68. void
  69. rl_add_undo (what, start, end, text)
  70. enum undo_code what;
  71. int start, end;
  72. char *text;
  73. {
  74. UNDO_LIST *temp;
  75. temp = alloc_undo_entry (what, start, end, text);
  76. temp->next = rl_undo_list;
  77. rl_undo_list = temp;
  78. }
  79. /* Free the existing undo list. */
  80. void
  81. rl_free_undo_list ()
  82. {
  83. UNDO_LIST *release, *orig_list;
  84. orig_list = rl_undo_list;
  85. while (rl_undo_list)
  86. {
  87. release = rl_undo_list;
  88. rl_undo_list = rl_undo_list->next;
  89. if (release->what == UNDO_DELETE)
  90. xfree (release->text);
  91. xfree (release);
  92. }
  93. rl_undo_list = (UNDO_LIST *)NULL;
  94. replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
  95. }
  96. UNDO_LIST *
  97. _rl_copy_undo_entry (entry)
  98. UNDO_LIST *entry;
  99. {
  100. UNDO_LIST *new;
  101. new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
  102. new->text = entry->text ? savestring (entry->text) : 0;
  103. return new;
  104. }
  105. UNDO_LIST *
  106. _rl_copy_undo_list (head)
  107. UNDO_LIST *head;
  108. {
  109. UNDO_LIST *list, *new, *roving, *c;
  110. if (head == 0)
  111. return head;
  112. list = head;
  113. new = 0;
  114. while (list)
  115. {
  116. c = _rl_copy_undo_entry (list);
  117. if (new == 0)
  118. roving = new = c;
  119. else
  120. {
  121. roving->next = c;
  122. roving = roving->next;
  123. }
  124. list = list->next;
  125. }
  126. roving->next = 0;
  127. return new;
  128. }
  129. /* Undo the next thing in the list. Return 0 if there
  130. is nothing to undo, or non-zero if there was. */
  131. int
  132. rl_do_undo ()
  133. {
  134. UNDO_LIST *release;
  135. int waiting_for_begin, start, end;
  136. #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
  137. start = end = waiting_for_begin = 0;
  138. do
  139. {
  140. if (rl_undo_list == 0)
  141. return (0);
  142. _rl_doing_an_undo = 1;
  143. RL_SETSTATE(RL_STATE_UNDOING);
  144. /* To better support vi-mode, a start or end value of -1 means
  145. rl_point, and a value of -2 means rl_end. */
  146. if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
  147. {
  148. start = TRANS (rl_undo_list->start);
  149. end = TRANS (rl_undo_list->end);
  150. }
  151. switch (rl_undo_list->what)
  152. {
  153. /* Undoing deletes means inserting some text. */
  154. case UNDO_DELETE:
  155. rl_point = start;
  156. rl_insert_text (rl_undo_list->text);
  157. xfree (rl_undo_list->text);
  158. break;
  159. /* Undoing inserts means deleting some text. */
  160. case UNDO_INSERT:
  161. rl_delete_text (start, end);
  162. rl_point = start;
  163. break;
  164. /* Undoing an END means undoing everything 'til we get to a BEGIN. */
  165. case UNDO_END:
  166. waiting_for_begin++;
  167. break;
  168. /* Undoing a BEGIN means that we are done with this group. */
  169. case UNDO_BEGIN:
  170. if (waiting_for_begin)
  171. waiting_for_begin--;
  172. else
  173. rl_ding ();
  174. break;
  175. }
  176. _rl_doing_an_undo = 0;
  177. RL_UNSETSTATE(RL_STATE_UNDOING);
  178. release = rl_undo_list;
  179. rl_undo_list = rl_undo_list->next;
  180. replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
  181. xfree (release);
  182. }
  183. while (waiting_for_begin);
  184. return (1);
  185. }
  186. #undef TRANS
  187. int
  188. _rl_fix_last_undo_of_type (type, start, end)
  189. int type, start, end;
  190. {
  191. UNDO_LIST *rl;
  192. for (rl = rl_undo_list; rl; rl = rl->next)
  193. {
  194. if (rl->what == type)
  195. {
  196. rl->start = start;
  197. rl->end = end;
  198. return 0;
  199. }
  200. }
  201. return 1;
  202. }
  203. /* Begin a group. Subsequent undos are undone as an atomic operation. */
  204. int
  205. rl_begin_undo_group ()
  206. {
  207. rl_add_undo (UNDO_BEGIN, 0, 0, 0);
  208. _rl_undo_group_level++;
  209. return 0;
  210. }
  211. /* End an undo group started with rl_begin_undo_group (). */
  212. int
  213. rl_end_undo_group ()
  214. {
  215. rl_add_undo (UNDO_END, 0, 0, 0);
  216. _rl_undo_group_level--;
  217. return 0;
  218. }
  219. /* Save an undo entry for the text from START to END. */
  220. int
  221. rl_modifying (start, end)
  222. int start, end;
  223. {
  224. if (start > end)
  225. {
  226. SWAP (start, end);
  227. }
  228. if (start != end)
  229. {
  230. char *temp = rl_copy_text (start, end);
  231. rl_begin_undo_group ();
  232. rl_add_undo (UNDO_DELETE, start, end, temp);
  233. rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
  234. rl_end_undo_group ();
  235. }
  236. return 0;
  237. }
  238. /* Revert the current line to its previous state. */
  239. int
  240. rl_revert_line (count, key)
  241. int count, key;
  242. {
  243. if (rl_undo_list == 0)
  244. rl_ding ();
  245. else
  246. {
  247. while (rl_undo_list)
  248. rl_do_undo ();
  249. #if defined (VI_MODE)
  250. if (rl_editing_mode == vi_mode)
  251. rl_point = rl_mark = 0; /* rl_end should be set correctly */
  252. #endif
  253. }
  254. return 0;
  255. }
  256. /* Do some undoing of things that were done. */
  257. int
  258. rl_undo_command (count, key)
  259. int count, key;
  260. {
  261. if (count < 0)
  262. return 0; /* Nothing to do. */
  263. while (count)
  264. {
  265. if (rl_do_undo ())
  266. count--;
  267. else
  268. {
  269. rl_ding ();
  270. break;
  271. }
  272. }
  273. return 0;
  274. }