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