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