~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to lib/readline/undo.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* readline.c -- a general facility for reading lines of input
 
2
   with emacs style editing and completion. */
 
3
 
 
4
/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
 
5
 
 
6
   This file is part of the GNU Readline Library (Readline), a library
 
7
   for reading lines of text with interactive input and history editing.      
 
8
 
 
9
   Readline is free software: you can redistribute it and/or modify
 
10
   it under the terms of the GNU General Public License as published by
 
11
   the Free Software Foundation, either version 3 of the License, or
 
12
   (at your option) any later version.
 
13
 
 
14
   Readline is distributed in the hope that it will be useful,
 
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
   GNU General Public License for more details.
 
18
 
 
19
   You should have received a copy of the GNU General Public License
 
20
   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
 
21
*/
 
22
 
 
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 an UNDO_LIST */
 
105
void
 
106
_rl_free_undo_list (ul)
 
107
     UNDO_LIST *ul;
 
108
{
 
109
  UNDO_LIST *release;
 
110
 
 
111
  while (ul)
 
112
    {
 
113
      release = ul;
 
114
      ul = ul->next;
 
115
 
 
116
      if (release->what == UNDO_DELETE)
 
117
        xfree (release->text);
 
118
 
 
119
      xfree (release);
 
120
    }
 
121
}
 
122
 
 
123
/* Free the existing undo list. */
 
124
void
 
125
rl_free_undo_list ()
 
126
{
 
127
  UNDO_LIST *release, *orig_list;
 
128
 
 
129
  orig_list = rl_undo_list;
 
130
  _rl_free_undo_list (rl_undo_list);
 
131
  rl_undo_list = (UNDO_LIST *)NULL;
 
132
  replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
 
133
}
 
134
 
 
135
UNDO_LIST *
 
136
_rl_copy_undo_entry (entry)
 
137
     UNDO_LIST *entry;
 
138
{
 
139
  UNDO_LIST *new;
 
140
 
 
141
  new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
 
142
  new->text = entry->text ? savestring (entry->text) : 0;
 
143
  return new;
 
144
}
 
145
 
 
146
UNDO_LIST *
 
147
_rl_copy_undo_list (head)
 
148
     UNDO_LIST *head;
 
149
{
 
150
  UNDO_LIST *list, *new, *roving, *c;
 
151
 
 
152
  if (head == 0)
 
153
    return head;
 
154
 
 
155
  list = head;
 
156
  new = 0;
 
157
  while (list)
 
158
    {
 
159
      c = _rl_copy_undo_entry (list);
 
160
      if (new == 0)
 
161
        roving = new = c;
 
162
      else
 
163
        {
 
164
          roving->next = c;
 
165
          roving = roving->next;
 
166
        }
 
167
      list = list->next;
 
168
    }
 
169
 
 
170
  roving->next = 0;
 
171
  return new;
 
172
}
 
173
 
 
174
/* Undo the next thing in the list.  Return 0 if there
 
175
   is nothing to undo, or non-zero if there was. */
 
176
int
 
177
rl_do_undo ()
 
178
{
 
179
  UNDO_LIST *release;
 
180
  int waiting_for_begin, start, end;
 
181
  HIST_ENTRY *cur, *temp;
 
182
 
 
183
#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
 
184
 
 
185
  start = end = waiting_for_begin = 0;
 
186
  do
 
187
    {
 
188
      if (rl_undo_list == 0)
 
189
        return (0);
 
190
 
 
191
      _rl_doing_an_undo = 1;
 
192
      RL_SETSTATE(RL_STATE_UNDOING);
 
193
 
 
194
      /* To better support vi-mode, a start or end value of -1 means
 
195
         rl_point, and a value of -2 means rl_end. */
 
196
      if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
 
197
        {
 
198
          start = TRANS (rl_undo_list->start);
 
199
          end = TRANS (rl_undo_list->end);
 
200
        }
 
201
 
 
202
      switch (rl_undo_list->what)
 
203
        {
 
204
        /* Undoing deletes means inserting some text. */
 
205
        case UNDO_DELETE:
 
206
          rl_point = start;
 
207
          rl_insert_text (rl_undo_list->text);
 
208
          xfree (rl_undo_list->text);
 
209
          break;
 
210
 
 
211
        /* Undoing inserts means deleting some text. */
 
212
        case UNDO_INSERT:
 
213
          rl_delete_text (start, end);
 
214
          rl_point = start;
 
215
          break;
 
216
 
 
217
        /* Undoing an END means undoing everything 'til we get to a BEGIN. */
 
218
        case UNDO_END:
 
219
          waiting_for_begin++;
 
220
          break;
 
221
 
 
222
        /* Undoing a BEGIN means that we are done with this group. */
 
223
        case UNDO_BEGIN:
 
224
          if (waiting_for_begin)
 
225
            waiting_for_begin--;
 
226
          else
 
227
            rl_ding ();
 
228
          break;
 
229
        }
 
230
 
 
231
      _rl_doing_an_undo = 0;
 
232
      RL_UNSETSTATE(RL_STATE_UNDOING);
 
233
 
 
234
      release = rl_undo_list;
 
235
      rl_undo_list = rl_undo_list->next;
 
236
 
 
237
      /* If we are editing a history entry, make sure the change is replicated
 
238
         in the history entry's line */
 
239
      cur = current_history ();
 
240
      if (cur && cur->data && (UNDO_LIST *)cur->data == release)
 
241
        {
 
242
          temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
 
243
          xfree (temp->line);
 
244
          FREE (temp->timestamp);
 
245
          xfree (temp);
 
246
        }
 
247
 
 
248
      replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
 
249
 
 
250
      xfree (release);
 
251
    }
 
252
  while (waiting_for_begin);
 
253
 
 
254
  return (1);
 
255
}
 
256
#undef TRANS
 
257
 
 
258
int
 
259
_rl_fix_last_undo_of_type (type, start, end)
 
260
     int type, start, end;
 
261
{
 
262
  UNDO_LIST *rl;
 
263
 
 
264
  for (rl = rl_undo_list; rl; rl = rl->next)
 
265
    {
 
266
      if (rl->what == type)
 
267
        {
 
268
          rl->start = start;
 
269
          rl->end = end;
 
270
          return 0;
 
271
        }
 
272
    }
 
273
  return 1;
 
274
}
 
275
 
 
276
/* Begin a group.  Subsequent undos are undone as an atomic operation. */
 
277
int
 
278
rl_begin_undo_group ()
 
279
{
 
280
  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
 
281
  _rl_undo_group_level++;
 
282
  return 0;
 
283
}
 
284
 
 
285
/* End an undo group started with rl_begin_undo_group (). */
 
286
int
 
287
rl_end_undo_group ()
 
288
{
 
289
  rl_add_undo (UNDO_END, 0, 0, 0);
 
290
  _rl_undo_group_level--;
 
291
  return 0;
 
292
}
 
293
 
 
294
/* Save an undo entry for the text from START to END. */
 
295
int
 
296
rl_modifying (start, end)
 
297
     int start, end;
 
298
{
 
299
  if (start > end)
 
300
    {
 
301
      SWAP (start, end);
 
302
    }
 
303
 
 
304
  if (start != end)
 
305
    {
 
306
      char *temp = rl_copy_text (start, end);
 
307
      rl_begin_undo_group ();
 
308
      rl_add_undo (UNDO_DELETE, start, end, temp);
 
309
      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
 
310
      rl_end_undo_group ();
 
311
    }
 
312
  return 0;
 
313
}
 
314
 
 
315
/* Revert the current line to its previous state. */
 
316
int
 
317
rl_revert_line (count, key)
 
318
     int count, key;
 
319
{
 
320
  if (rl_undo_list == 0)
 
321
    rl_ding ();
 
322
  else
 
323
    {
 
324
      while (rl_undo_list)
 
325
        rl_do_undo ();
 
326
#if defined (VI_MODE)
 
327
      if (rl_editing_mode == vi_mode)
 
328
        rl_point = rl_mark = 0;         /* rl_end should be set correctly */
 
329
#endif
 
330
    }
 
331
    
 
332
  return 0;
 
333
}
 
334
 
 
335
/* Do some undoing of things that were done. */
 
336
int
 
337
rl_undo_command (count, key)
 
338
     int count, key;
 
339
{
 
340
  if (count < 0)
 
341
    return 0;   /* Nothing to do. */
 
342
 
 
343
  while (count)
 
344
    {
 
345
      if (rl_do_undo ())
 
346
        count--;
 
347
      else
 
348
        {
 
349
          rl_ding ();
 
350
          break;
 
351
        }
 
352
    }
 
353
  return 0;
 
354
}