123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- /* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
- /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
- */
- #define READLINE_LIBRARY
- #if defined (HAVE_CONFIG_H)
- # include <config.h>
- #endif
- #include <sys/types.h>
- #if defined (HAVE_UNISTD_H)
- # include <unistd.h> /* for _POSIX_VERSION */
- #endif /* HAVE_UNISTD_H */
- #if defined (HAVE_STDLIB_H)
- # include <stdlib.h>
- #else
- # include "ansi_stdlib.h"
- #endif /* HAVE_STDLIB_H */
- #include <stdio.h>
- /* System-specific feature definitions and include files. */
- #include "rldefs.h"
- /* Some standard library routines. */
- #include "readline.h"
- #include "history.h"
- #include "rlprivate.h"
- #include "xmalloc.h"
- extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
- /* Non-zero tells rl_delete_text and rl_insert_text to not add to
- the undo list. */
- int _rl_doing_an_undo = 0;
- /* How many unclosed undo groups we currently have. */
- int _rl_undo_group_level = 0;
- /* The current undo list for THE_LINE. */
- UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
- /* **************************************************************** */
- /* */
- /* Undo, and Undoing */
- /* */
- /* **************************************************************** */
- static UNDO_LIST *
- alloc_undo_entry (what, start, end, text)
- enum undo_code what;
- int start, end;
- char *text;
- {
- UNDO_LIST *temp;
- temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
- temp->what = what;
- temp->start = start;
- temp->end = end;
- temp->text = text;
- temp->next = (UNDO_LIST *)NULL;
- return temp;
- }
- /* Remember how to undo something. Concatenate some undos if that
- seems right. */
- void
- rl_add_undo (what, start, end, text)
- enum undo_code what;
- int start, end;
- char *text;
- {
- UNDO_LIST *temp;
- temp = alloc_undo_entry (what, start, end, text);
- temp->next = rl_undo_list;
- rl_undo_list = temp;
- }
- /* Free the existing undo list. */
- void
- rl_free_undo_list ()
- {
- UNDO_LIST *release, *orig_list;
- orig_list = rl_undo_list;
- while (rl_undo_list)
- {
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
- if (release->what == UNDO_DELETE)
- xfree (release->text);
- xfree (release);
- }
- rl_undo_list = (UNDO_LIST *)NULL;
- replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
- }
- UNDO_LIST *
- _rl_copy_undo_entry (entry)
- UNDO_LIST *entry;
- {
- UNDO_LIST *new;
- new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
- new->text = entry->text ? savestring (entry->text) : 0;
- return new;
- }
- UNDO_LIST *
- _rl_copy_undo_list (head)
- UNDO_LIST *head;
- {
- UNDO_LIST *list, *new, *roving, *c;
- if (head == 0)
- return head;
- list = head;
- new = 0;
- while (list)
- {
- c = _rl_copy_undo_entry (list);
- if (new == 0)
- roving = new = c;
- else
- {
- roving->next = c;
- roving = roving->next;
- }
- list = list->next;
- }
- roving->next = 0;
- return new;
- }
- /* Undo the next thing in the list. Return 0 if there
- is nothing to undo, or non-zero if there was. */
- int
- rl_do_undo ()
- {
- UNDO_LIST *release;
- int waiting_for_begin, start, end;
- #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
- start = end = waiting_for_begin = 0;
- do
- {
- if (rl_undo_list == 0)
- return (0);
- _rl_doing_an_undo = 1;
- RL_SETSTATE(RL_STATE_UNDOING);
- /* To better support vi-mode, a start or end value of -1 means
- rl_point, and a value of -2 means rl_end. */
- if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
- {
- start = TRANS (rl_undo_list->start);
- end = TRANS (rl_undo_list->end);
- }
- switch (rl_undo_list->what)
- {
- /* Undoing deletes means inserting some text. */
- case UNDO_DELETE:
- rl_point = start;
- rl_insert_text (rl_undo_list->text);
- xfree (rl_undo_list->text);
- break;
- /* Undoing inserts means deleting some text. */
- case UNDO_INSERT:
- rl_delete_text (start, end);
- rl_point = start;
- break;
- /* Undoing an END means undoing everything 'til we get to a BEGIN. */
- case UNDO_END:
- waiting_for_begin++;
- break;
- /* Undoing a BEGIN means that we are done with this group. */
- case UNDO_BEGIN:
- if (waiting_for_begin)
- waiting_for_begin--;
- else
- rl_ding ();
- break;
- }
- _rl_doing_an_undo = 0;
- RL_UNSETSTATE(RL_STATE_UNDOING);
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
- replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
- xfree (release);
- }
- while (waiting_for_begin);
- return (1);
- }
- #undef TRANS
- int
- _rl_fix_last_undo_of_type (type, start, end)
- int type, start, end;
- {
- UNDO_LIST *rl;
- for (rl = rl_undo_list; rl; rl = rl->next)
- {
- if (rl->what == type)
- {
- rl->start = start;
- rl->end = end;
- return 0;
- }
- }
- return 1;
- }
- /* Begin a group. Subsequent undos are undone as an atomic operation. */
- int
- rl_begin_undo_group ()
- {
- rl_add_undo (UNDO_BEGIN, 0, 0, 0);
- _rl_undo_group_level++;
- return 0;
- }
- /* End an undo group started with rl_begin_undo_group (). */
- int
- rl_end_undo_group ()
- {
- rl_add_undo (UNDO_END, 0, 0, 0);
- _rl_undo_group_level--;
- return 0;
- }
- /* Save an undo entry for the text from START to END. */
- int
- rl_modifying (start, end)
- int start, end;
- {
- if (start > end)
- {
- SWAP (start, end);
- }
- if (start != end)
- {
- char *temp = rl_copy_text (start, end);
- rl_begin_undo_group ();
- rl_add_undo (UNDO_DELETE, start, end, temp);
- rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
- rl_end_undo_group ();
- }
- return 0;
- }
- /* Revert the current line to its previous state. */
- int
- rl_revert_line (count, key)
- int count, key;
- {
- if (rl_undo_list == 0)
- rl_ding ();
- else
- {
- while (rl_undo_list)
- rl_do_undo ();
- #if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_point = rl_mark = 0; /* rl_end should be set correctly */
- #endif
- }
-
- return 0;
- }
- /* Do some undoing of things that were done. */
- int
- rl_undo_command (count, key)
- int count, key;
- {
- if (count < 0)
- return 0; /* Nothing to do. */
- while (count)
- {
- if (rl_do_undo ())
- count--;
- else
- {
- rl_ding ();
- break;
- }
- }
- return 0;
- }
|