]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/undo.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / undo.c
1 /* readline.c -- a general facility for reading lines of input
2 with emacs style editing and completion. */
3
4 /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
5
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
8
9 The GNU Readline Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2, or
12 (at your option) any later version.
13
14 The GNU Readline Library is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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
52 #define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
53
54 /* Non-zero tells rl_delete_text and rl_insert_text to not add to
55 the undo list. */
56 int _rl_doing_an_undo = 0;
57
58 /* How many unclosed undo groups we currently have. */
59 int _rl_undo_group_level = 0;
60
61 /* The current undo list for THE_LINE. */
62 UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
63
64 /* **************************************************************** */
65 /* */
66 /* Undo, and Undoing */
67 /* */
68 /* **************************************************************** */
69
70 /* Remember how to undo something. Concatenate some undos if that
71 seems right. */
72 void
73 rl_add_undo (what, start, end, text)
74 enum undo_code what;
75 int start, end;
76 char *text;
77 {
78 UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
79 temp->what = what;
80 temp->start = start;
81 temp->end = end;
82 temp->text = text;
83 temp->next = rl_undo_list;
84 rl_undo_list = temp;
85 }
86
87 /* Free the existing undo list. */
88 void
89 rl_free_undo_list ()
90 {
91 while (rl_undo_list)
92 {
93 UNDO_LIST *release = rl_undo_list;
94 rl_undo_list = rl_undo_list->next;
95
96 if (release->what == UNDO_DELETE)
97 free (release->text);
98
99 free (release);
100 }
101 rl_undo_list = (UNDO_LIST *)NULL;
102 }
103
104 /* Undo the next thing in the list. Return 0 if there
105 is nothing to undo, or non-zero if there was. */
106 int
107 rl_do_undo ()
108 {
109 UNDO_LIST *release;
110 int waiting_for_begin, start, end;
111
112 #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
113
114 start = end = waiting_for_begin = 0;
115 do
116 {
117 if (!rl_undo_list)
118 return (0);
119
120 _rl_doing_an_undo = 1;
121 RL_SETSTATE(RL_STATE_UNDOING);
122
123 /* To better support vi-mode, a start or end value of -1 means
124 rl_point, and a value of -2 means rl_end. */
125 if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
126 {
127 start = TRANS (rl_undo_list->start);
128 end = TRANS (rl_undo_list->end);
129 }
130
131 switch (rl_undo_list->what)
132 {
133 /* Undoing deletes means inserting some text. */
134 case UNDO_DELETE:
135 rl_point = start;
136 rl_insert_text (rl_undo_list->text);
137 free (rl_undo_list->text);
138 break;
139
140 /* Undoing inserts means deleting some text. */
141 case UNDO_INSERT:
142 rl_delete_text (start, end);
143 rl_point = start;
144 break;
145
146 /* Undoing an END means undoing everything 'til we get to a BEGIN. */
147 case UNDO_END:
148 waiting_for_begin++;
149 break;
150
151 /* Undoing a BEGIN means that we are done with this group. */
152 case UNDO_BEGIN:
153 if (waiting_for_begin)
154 waiting_for_begin--;
155 else
156 rl_ding ();
157 break;
158 }
159
160 _rl_doing_an_undo = 0;
161 RL_UNSETSTATE(RL_STATE_UNDOING);
162
163 release = rl_undo_list;
164 rl_undo_list = rl_undo_list->next;
165 free (release);
166 }
167 while (waiting_for_begin);
168
169 return (1);
170 }
171 #undef TRANS
172
173 int
174 _rl_fix_last_undo_of_type (type, start, end)
175 int type, start, end;
176 {
177 UNDO_LIST *rl;
178
179 for (rl = rl_undo_list; rl; rl = rl->next)
180 {
181 if (rl->what == type)
182 {
183 rl->start = start;
184 rl->end = end;
185 return 0;
186 }
187 }
188 return 1;
189 }
190
191 /* Begin a group. Subsequent undos are undone as an atomic operation. */
192 int
193 rl_begin_undo_group ()
194 {
195 rl_add_undo (UNDO_BEGIN, 0, 0, 0);
196 _rl_undo_group_level++;
197 return 0;
198 }
199
200 /* End an undo group started with rl_begin_undo_group (). */
201 int
202 rl_end_undo_group ()
203 {
204 rl_add_undo (UNDO_END, 0, 0, 0);
205 _rl_undo_group_level--;
206 return 0;
207 }
208
209 /* Save an undo entry for the text from START to END. */
210 int
211 rl_modifying (start, end)
212 int start, end;
213 {
214 if (start > end)
215 {
216 SWAP (start, end);
217 }
218
219 if (start != end)
220 {
221 char *temp = rl_copy_text (start, end);
222 rl_begin_undo_group ();
223 rl_add_undo (UNDO_DELETE, start, end, temp);
224 rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
225 rl_end_undo_group ();
226 }
227 return 0;
228 }
229
230 /* Revert the current line to its previous state. */
231 int
232 rl_revert_line (count, key)
233 int count, key;
234 {
235 if (!rl_undo_list)
236 rl_ding ();
237 else
238 {
239 while (rl_undo_list)
240 rl_do_undo ();
241 }
242 return 0;
243 }
244
245 /* Do some undoing of things that were done. */
246 int
247 rl_undo_command (count, key)
248 int count, key;
249 {
250 if (count < 0)
251 return 0; /* Nothing to do. */
252
253 while (count)
254 {
255 if (rl_do_undo ())
256 count--;
257 else
258 {
259 rl_ding ();
260 break;
261 }
262 }
263 return 0;
264 }