]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libreadline/undo.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libreadline / 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, 2006 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 #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 the existing undo list. */
105 void
106 rl_free_undo_list ()
107 {
108   UNDO_LIST *release, *orig_list;
109
110   orig_list = rl_undo_list;
111   while (rl_undo_list)
112     {
113       release = rl_undo_list;
114       rl_undo_list = rl_undo_list->next;
115
116       if (release->what == UNDO_DELETE)
117         free (release->text);
118
119       free (release);
120     }
121   rl_undo_list = (UNDO_LIST *)NULL;
122   replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
123 }
124
125 UNDO_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
136 UNDO_LIST *
137 _rl_copy_undo_list (head)
138      UNDO_LIST *head;
139 {
140   UNDO_LIST *list, *new, *roving, *c;
141
142   list = head;
143   new = 0;
144   while (list)
145     {
146       c = _rl_copy_undo_entry (list);
147       if (new == 0)
148         roving = new = c;
149       else
150         {
151           roving->next = c;
152           roving = roving->next;
153         }
154       list = list->next;
155     }
156
157   roving->next = 0;
158   return new;
159 }
160
161 /* Undo the next thing in the list.  Return 0 if there
162    is nothing to undo, or non-zero if there was. */
163 int
164 rl_do_undo ()
165 {
166   UNDO_LIST *release;
167   int waiting_for_begin, start, end;
168
169 #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
170
171   start = end = waiting_for_begin = 0;
172   do
173     {
174       if (!rl_undo_list)
175         return (0);
176
177       _rl_doing_an_undo = 1;
178       RL_SETSTATE(RL_STATE_UNDOING);
179
180       /* To better support vi-mode, a start or end value of -1 means
181          rl_point, and a value of -2 means rl_end. */
182       if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
183         {
184           start = TRANS (rl_undo_list->start);
185           end = TRANS (rl_undo_list->end);
186         }
187
188       switch (rl_undo_list->what)
189         {
190         /* Undoing deletes means inserting some text. */
191         case UNDO_DELETE:
192           rl_point = start;
193           rl_insert_text (rl_undo_list->text);
194           free (rl_undo_list->text);
195           break;
196
197         /* Undoing inserts means deleting some text. */
198         case UNDO_INSERT:
199           rl_delete_text (start, end);
200           rl_point = start;
201           break;
202
203         /* Undoing an END means undoing everything 'til we get to a BEGIN. */
204         case UNDO_END:
205           waiting_for_begin++;
206           break;
207
208         /* Undoing a BEGIN means that we are done with this group. */
209         case UNDO_BEGIN:
210           if (waiting_for_begin)
211             waiting_for_begin--;
212           else
213             rl_ding ();
214           break;
215         }
216
217       _rl_doing_an_undo = 0;
218       RL_UNSETSTATE(RL_STATE_UNDOING);
219
220       release = rl_undo_list;
221       rl_undo_list = rl_undo_list->next;
222       replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
223
224       free (release);
225     }
226   while (waiting_for_begin);
227
228   return (1);
229 }
230 #undef TRANS
231
232 int
233 _rl_fix_last_undo_of_type (type, start, end)
234      int type, start, end;
235 {
236   UNDO_LIST *rl;
237
238   for (rl = rl_undo_list; rl; rl = rl->next)
239     {
240       if (rl->what == type)
241         {
242           rl->start = start;
243           rl->end = end;
244           return 0;
245         }
246     }
247   return 1;
248 }
249
250 /* Begin a group.  Subsequent undos are undone as an atomic operation. */
251 int
252 rl_begin_undo_group ()
253 {
254   rl_add_undo (UNDO_BEGIN, 0, 0, 0);
255   _rl_undo_group_level++;
256   return 0;
257 }
258
259 /* End an undo group started with rl_begin_undo_group (). */
260 int
261 rl_end_undo_group ()
262 {
263   rl_add_undo (UNDO_END, 0, 0, 0);
264   _rl_undo_group_level--;
265   return 0;
266 }
267
268 /* Save an undo entry for the text from START to END. */
269 int
270 rl_modifying (start, end)
271      int start, end;
272 {
273   if (start > end)
274     {
275       SWAP (start, end);
276     }
277
278   if (start != end)
279     {
280       char *temp = rl_copy_text (start, end);
281       rl_begin_undo_group ();
282       rl_add_undo (UNDO_DELETE, start, end, temp);
283       rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
284       rl_end_undo_group ();
285     }
286   return 0;
287 }
288
289 /* Revert the current line to its previous state. */
290 int
291 rl_revert_line (count, key)
292      int count, key;
293 {
294   if (!rl_undo_list)
295     rl_ding ();
296   else
297     {
298       while (rl_undo_list)
299         rl_do_undo ();
300 #if defined (VI_MODE)
301       if (rl_editing_mode == vi_mode)
302         rl_point = rl_mark = 0;         /* rl_end should be set correctly */
303 #endif
304     }
305     
306   return 0;
307 }
308
309 /* Do some undoing of things that were done. */
310 int
311 rl_undo_command (count, key)
312      int count, key;
313 {
314   if (count < 0)
315     return 0;   /* Nothing to do. */
316
317   while (count)
318     {
319       if (rl_do_undo ())
320         count--;
321       else
322         {
323           rl_ding ();
324           break;
325         }
326     }
327   return 0;
328 }