Fix last entry in ChangeLog.gdb (unnecessary dir name).
[deliverable/binutils-gdb.git] / readline / undo.c
CommitLineData
d60d9f65
SS
1/* readline.c -- a general facility for reading lines of input
2 with emacs style editing and completion. */
3
cc88a640 4/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
d60d9f65 5
cc88a640
JK
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.
d60d9f65 8
cc88a640
JK
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
d60d9f65
SS
12 (at your option) any later version.
13
cc88a640
JK
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
d60d9f65
SS
17 GNU General Public License for more details.
18
cc88a640
JK
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
d60d9f65
SS
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
1b17e766 50#include "rlprivate.h"
9255ee31 51#include "xmalloc.h"
d60d9f65 52
cc88a640
JK
53extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
54
d60d9f65
SS
55/* Non-zero tells rl_delete_text and rl_insert_text to not add to
56 the undo list. */
57int _rl_doing_an_undo = 0;
58
59/* How many unclosed undo groups we currently have. */
60int _rl_undo_group_level = 0;
61
62/* The current undo list for THE_LINE. */
63UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
64
65/* **************************************************************** */
66/* */
67/* Undo, and Undoing */
68/* */
69/* **************************************************************** */
70
cc88a640
JK
71static UNDO_LIST *
72alloc_undo_entry (what, start, end, text)
d60d9f65
SS
73 enum undo_code what;
74 int start, end;
75 char *text;
76{
cc88a640
JK
77 UNDO_LIST *temp;
78
79 temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
d60d9f65
SS
80 temp->what = what;
81 temp->start = start;
82 temp->end = end;
83 temp->text = text;
cc88a640
JK
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. */
91void
92rl_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);
d60d9f65
SS
100 temp->next = rl_undo_list;
101 rl_undo_list = temp;
102}
103
104/* Free the existing undo list. */
105void
9255ee31 106rl_free_undo_list ()
d60d9f65 107{
cc88a640
JK
108 UNDO_LIST *release, *orig_list;
109
110 orig_list = rl_undo_list;
d60d9f65
SS
111 while (rl_undo_list)
112 {
cc88a640 113 release = rl_undo_list;
d60d9f65
SS
114 rl_undo_list = rl_undo_list->next;
115
116 if (release->what == UNDO_DELETE)
cc88a640 117 xfree (release->text);
d60d9f65 118
cc88a640 119 xfree (release);
d60d9f65
SS
120 }
121 rl_undo_list = (UNDO_LIST *)NULL;
cc88a640
JK
122 replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
123}
124
125UNDO_LIST *
126_rl_copy_undo_entry (entry)
127 UNDO_LIST *entry;
128{
129 UNDO_LIST *new;
130
131 new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
132 new->text = entry->text ? savestring (entry->text) : 0;
133 return new;
134}
135
136UNDO_LIST *
137_rl_copy_undo_list (head)
138 UNDO_LIST *head;
139{
140 UNDO_LIST *list, *new, *roving, *c;
141
142 if (head == 0)
143 return head;
144
145 list = head;
146 new = 0;
147 while (list)
148 {
149 c = _rl_copy_undo_entry (list);
150 if (new == 0)
151 roving = new = c;
152 else
153 {
154 roving->next = c;
155 roving = roving->next;
156 }
157 list = list->next;
158 }
159
160 roving->next = 0;
161 return new;
d60d9f65
SS
162}
163
164/* Undo the next thing in the list. Return 0 if there
165 is nothing to undo, or non-zero if there was. */
166int
167rl_do_undo ()
168{
169 UNDO_LIST *release;
9255ee31 170 int waiting_for_begin, start, end;
d60d9f65
SS
171
172#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
173
9255ee31 174 start = end = waiting_for_begin = 0;
d60d9f65
SS
175 do
176 {
cc88a640 177 if (rl_undo_list == 0)
d60d9f65
SS
178 return (0);
179
180 _rl_doing_an_undo = 1;
9255ee31 181 RL_SETSTATE(RL_STATE_UNDOING);
d60d9f65
SS
182
183 /* To better support vi-mode, a start or end value of -1 means
184 rl_point, and a value of -2 means rl_end. */
185 if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
186 {
187 start = TRANS (rl_undo_list->start);
188 end = TRANS (rl_undo_list->end);
189 }
190
191 switch (rl_undo_list->what)
192 {
193 /* Undoing deletes means inserting some text. */
194 case UNDO_DELETE:
195 rl_point = start;
196 rl_insert_text (rl_undo_list->text);
cc88a640 197 xfree (rl_undo_list->text);
d60d9f65
SS
198 break;
199
200 /* Undoing inserts means deleting some text. */
201 case UNDO_INSERT:
202 rl_delete_text (start, end);
203 rl_point = start;
204 break;
205
206 /* Undoing an END means undoing everything 'til we get to a BEGIN. */
207 case UNDO_END:
208 waiting_for_begin++;
209 break;
210
211 /* Undoing a BEGIN means that we are done with this group. */
212 case UNDO_BEGIN:
213 if (waiting_for_begin)
214 waiting_for_begin--;
215 else
9255ee31 216 rl_ding ();
d60d9f65
SS
217 break;
218 }
219
220 _rl_doing_an_undo = 0;
9255ee31 221 RL_UNSETSTATE(RL_STATE_UNDOING);
d60d9f65
SS
222
223 release = rl_undo_list;
224 rl_undo_list = rl_undo_list->next;
cc88a640
JK
225 replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
226
227 xfree (release);
d60d9f65
SS
228 }
229 while (waiting_for_begin);
230
231 return (1);
232}
233#undef TRANS
234
235int
236_rl_fix_last_undo_of_type (type, start, end)
237 int type, start, end;
238{
239 UNDO_LIST *rl;
240
241 for (rl = rl_undo_list; rl; rl = rl->next)
242 {
243 if (rl->what == type)
244 {
245 rl->start = start;
246 rl->end = end;
247 return 0;
248 }
249 }
250 return 1;
251}
252
253/* Begin a group. Subsequent undos are undone as an atomic operation. */
254int
255rl_begin_undo_group ()
256{
257 rl_add_undo (UNDO_BEGIN, 0, 0, 0);
258 _rl_undo_group_level++;
259 return 0;
260}
261
262/* End an undo group started with rl_begin_undo_group (). */
263int
264rl_end_undo_group ()
265{
266 rl_add_undo (UNDO_END, 0, 0, 0);
267 _rl_undo_group_level--;
268 return 0;
269}
270
271/* Save an undo entry for the text from START to END. */
272int
273rl_modifying (start, end)
274 int start, end;
275{
276 if (start > end)
277 {
278 SWAP (start, end);
279 }
280
281 if (start != end)
282 {
283 char *temp = rl_copy_text (start, end);
284 rl_begin_undo_group ();
285 rl_add_undo (UNDO_DELETE, start, end, temp);
286 rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
287 rl_end_undo_group ();
288 }
289 return 0;
290}
291
292/* Revert the current line to its previous state. */
293int
294rl_revert_line (count, key)
295 int count, key;
296{
cc88a640 297 if (rl_undo_list == 0)
9255ee31 298 rl_ding ();
d60d9f65
SS
299 else
300 {
301 while (rl_undo_list)
302 rl_do_undo ();
5bdf8622
DJ
303#if defined (VI_MODE)
304 if (rl_editing_mode == vi_mode)
305 rl_point = rl_mark = 0; /* rl_end should be set correctly */
306#endif
d60d9f65 307 }
5bdf8622 308
d60d9f65
SS
309 return 0;
310}
311
312/* Do some undoing of things that were done. */
313int
314rl_undo_command (count, key)
315 int count, key;
316{
317 if (count < 0)
318 return 0; /* Nothing to do. */
319
320 while (count)
321 {
322 if (rl_do_undo ())
323 count--;
324 else
325 {
9255ee31 326 rl_ding ();
d60d9f65
SS
327 break;
328 }
329 }
330 return 0;
331}
This page took 0.805782 seconds and 4 git commands to generate.