source: trunk/third/readline/undo.c @ 12992

Revision 12992, 5.7 KB checked in by kcr, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12991, which included commits to RCS files with non-trunk default branches.
Line 
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 1, 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   675 Mass Ave, Cambridge, MA 02139, 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#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
51
52/* Non-zero tells rl_delete_text and rl_insert_text to not add to
53   the undo list. */
54int _rl_doing_an_undo = 0;
55
56/* How many unclosed undo groups we currently have. */
57int _rl_undo_group_level = 0;
58
59/* The current undo list for THE_LINE. */
60UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
61
62/* **************************************************************** */
63/*                                                                  */
64/*                      Undo, and Undoing                           */
65/*                                                                  */
66/* **************************************************************** */
67
68/* Remember how to undo something.  Concatenate some undos if that
69   seems right. */
70void
71rl_add_undo (what, start, end, text)
72     enum undo_code what;
73     int start, end;
74     char *text;
75{
76  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
77  temp->what = what;
78  temp->start = start;
79  temp->end = end;
80  temp->text = text;
81  temp->next = rl_undo_list;
82  rl_undo_list = temp;
83}
84
85/* Free the existing undo list. */
86void
87free_undo_list ()
88{
89  while (rl_undo_list)
90    {
91      UNDO_LIST *release = rl_undo_list;
92      rl_undo_list = rl_undo_list->next;
93
94      if (release->what == UNDO_DELETE)
95        free (release->text);
96
97      free (release);
98    }
99  rl_undo_list = (UNDO_LIST *)NULL;
100}
101
102/* Undo the next thing in the list.  Return 0 if there
103   is nothing to undo, or non-zero if there was. */
104int
105rl_do_undo ()
106{
107  UNDO_LIST *release;
108  int waiting_for_begin = 0;
109  int start, end;
110
111#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
112
113  do
114    {
115      if (!rl_undo_list)
116        return (0);
117
118      _rl_doing_an_undo = 1;
119
120      /* To better support vi-mode, a start or end value of -1 means
121         rl_point, and a value of -2 means rl_end. */
122      if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
123        {
124          start = TRANS (rl_undo_list->start);
125          end = TRANS (rl_undo_list->end);
126        }
127
128      switch (rl_undo_list->what)
129        {
130        /* Undoing deletes means inserting some text. */
131        case UNDO_DELETE:
132          rl_point = start;
133          rl_insert_text (rl_undo_list->text);
134          free (rl_undo_list->text);
135          break;
136
137        /* Undoing inserts means deleting some text. */
138        case UNDO_INSERT:
139          rl_delete_text (start, end);
140          rl_point = start;
141          break;
142
143        /* Undoing an END means undoing everything 'til we get to a BEGIN. */
144        case UNDO_END:
145          waiting_for_begin++;
146          break;
147
148        /* Undoing a BEGIN means that we are done with this group. */
149        case UNDO_BEGIN:
150          if (waiting_for_begin)
151            waiting_for_begin--;
152          else
153            ding ();
154          break;
155        }
156
157      _rl_doing_an_undo = 0;
158
159      release = rl_undo_list;
160      rl_undo_list = rl_undo_list->next;
161      free (release);
162    }
163  while (waiting_for_begin);
164
165  return (1);
166}
167#undef TRANS
168
169int
170_rl_fix_last_undo_of_type (type, start, end)
171     int type, start, end;
172{
173  UNDO_LIST *rl;
174
175  for (rl = rl_undo_list; rl; rl = rl->next)
176    {
177      if (rl->what == type)
178        {
179          rl->start = start;
180          rl->end = end;
181          return 0;
182        }
183    }
184  return 1;
185}
186
187/* Begin a group.  Subsequent undos are undone as an atomic operation. */
188int
189rl_begin_undo_group ()
190{
191  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
192  _rl_undo_group_level++;
193  return 0;
194}
195
196/* End an undo group started with rl_begin_undo_group (). */
197int
198rl_end_undo_group ()
199{
200  rl_add_undo (UNDO_END, 0, 0, 0);
201  _rl_undo_group_level--;
202  return 0;
203}
204
205/* Save an undo entry for the text from START to END. */
206int
207rl_modifying (start, end)
208     int start, end;
209{
210  if (start > end)
211    {
212      SWAP (start, end);
213    }
214
215  if (start != end)
216    {
217      char *temp = rl_copy_text (start, end);
218      rl_begin_undo_group ();
219      rl_add_undo (UNDO_DELETE, start, end, temp);
220      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
221      rl_end_undo_group ();
222    }
223  return 0;
224}
225
226/* Revert the current line to its previous state. */
227int
228rl_revert_line (count, key)
229     int count, key;
230{
231  if (!rl_undo_list)
232    ding ();
233  else
234    {
235      while (rl_undo_list)
236        rl_do_undo ();
237    }
238  return 0;
239}
240
241/* Do some undoing of things that were done. */
242int
243rl_undo_command (count, key)
244     int count, key;
245{
246  if (count < 0)
247    return 0;   /* Nothing to do. */
248
249  while (count)
250    {
251      if (rl_do_undo ())
252        count--;
253      else
254        {
255          ding ();
256          break;
257        }
258    }
259  return 0;
260}
Note: See TracBrowser for help on using the repository browser.