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