121308Sache/* readline.c -- a general facility for reading lines of input
221308Sache   with emacs style editing and completion. */
321308Sache
4165670Sache/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc.
521308Sache
621308Sache   This file is part of the GNU Readline Library, a library for
721308Sache   reading lines of text with interactive input and history editing.
821308Sache
921308Sache   The GNU Readline Library is free software; you can redistribute it
1021308Sache   and/or modify it under the terms of the GNU General Public License
1158310Sache   as published by the Free Software Foundation; either version 2, or
1221308Sache   (at your option) any later version.
1321308Sache
1421308Sache   The GNU Readline Library is distributed in the hope that it will be
1521308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1621308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1721308Sache   GNU General Public License for more details.
1821308Sache
1921308Sache   The GNU General Public License is often shipped with GNU software, and
2021308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2121308Sache   have a copy of the license, write to the Free Software Foundation,
2258310Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2321308Sache#define READLINE_LIBRARY
2421308Sache
2521308Sache#if defined (HAVE_CONFIG_H)
2621308Sache#  include <config.h>
2721308Sache#endif
2821308Sache
2921308Sache#include <sys/types.h>
3021308Sache
3121308Sache#if defined (HAVE_UNISTD_H)
3221308Sache#  include <unistd.h>           /* for _POSIX_VERSION */
3321308Sache#endif /* HAVE_UNISTD_H */
3421308Sache
3521308Sache#if defined (HAVE_STDLIB_H)
3621308Sache#  include <stdlib.h>
3721308Sache#else
3821308Sache#  include "ansi_stdlib.h"
3921308Sache#endif /* HAVE_STDLIB_H */
4021308Sache
4121308Sache#include <stdio.h>
4221308Sache
4321308Sache/* System-specific feature definitions and include files. */
4421308Sache#include "rldefs.h"
4521308Sache
4621308Sache/* Some standard library routines. */
4721308Sache#include "readline.h"
4821308Sache#include "history.h"
4921308Sache
5058310Sache#include "rlprivate.h"
51119610Sache#include "xmalloc.h"
5258310Sache
53165670Sacheextern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
54165670Sache
5521308Sache/* Non-zero tells rl_delete_text and rl_insert_text to not add to
5621308Sache   the undo list. */
5721308Sacheint _rl_doing_an_undo = 0;
5821308Sache
5921308Sache/* How many unclosed undo groups we currently have. */
6021308Sacheint _rl_undo_group_level = 0;
6121308Sache
6221308Sache/* The current undo list for THE_LINE. */
6321308SacheUNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
6421308Sache
6521308Sache/* **************************************************************** */
6621308Sache/*								    */
6721308Sache/*			Undo, and Undoing			    */
6821308Sache/*								    */
6921308Sache/* **************************************************************** */
7021308Sache
71165670Sachestatic UNDO_LIST *
72165670Sachealloc_undo_entry (what, start, end, text)
73165670Sache     enum undo_code what;
74165670Sache     int start, end;
75165670Sache     char *text;
76165670Sache{
77165670Sache  UNDO_LIST *temp;
78165670Sache
79165670Sache  temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
80165670Sache  temp->what = what;
81165670Sache  temp->start = start;
82165670Sache  temp->end = end;
83165670Sache  temp->text = text;
84165670Sache
85165670Sache  temp->next = (UNDO_LIST *)NULL;
86165670Sache  return temp;
87165670Sache}
88165670Sache
8921308Sache/* Remember how to undo something.  Concatenate some undos if that
9021308Sache   seems right. */
9121308Sachevoid
9221308Sacherl_add_undo (what, start, end, text)
9321308Sache     enum undo_code what;
9421308Sache     int start, end;
9521308Sache     char *text;
9621308Sache{
97165670Sache  UNDO_LIST *temp;
98165670Sache
99165670Sache  temp = alloc_undo_entry (what, start, end, text);
10021308Sache  temp->next = rl_undo_list;
10121308Sache  rl_undo_list = temp;
10221308Sache}
10321308Sache
10421308Sache/* Free the existing undo list. */
10521308Sachevoid
10675406Sacherl_free_undo_list ()
10721308Sache{
108165670Sache  UNDO_LIST *release, *orig_list;
109165670Sache
110165670Sache  orig_list = rl_undo_list;
11121308Sache  while (rl_undo_list)
11221308Sache    {
113165670Sache      release = rl_undo_list;
11421308Sache      rl_undo_list = rl_undo_list->next;
11521308Sache
11621308Sache      if (release->what == UNDO_DELETE)
11721308Sache	free (release->text);
11821308Sache
11921308Sache      free (release);
12021308Sache    }
12121308Sache  rl_undo_list = (UNDO_LIST *)NULL;
122165670Sache  replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
12321308Sache}
12421308Sache
125165670SacheUNDO_LIST *
126165670Sache_rl_copy_undo_entry (entry)
127165670Sache     UNDO_LIST *entry;
128165670Sache{
129165670Sache  UNDO_LIST *new;
130165670Sache
131165670Sache  new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
132165670Sache  new->text = entry->text ? savestring (entry->text) : 0;
133165670Sache  return new;
134165670Sache}
135165670Sache
136165670SacheUNDO_LIST *
137165670Sache_rl_copy_undo_list (head)
138165670Sache     UNDO_LIST *head;
139165670Sache{
140165670Sache  UNDO_LIST *list, *new, *roving, *c;
141165670Sache
142165670Sache  list = head;
143165670Sache  new = 0;
144165670Sache  while (list)
145165670Sache    {
146165670Sache      c = _rl_copy_undo_entry (list);
147165670Sache      if (new == 0)
148165670Sache	roving = new = c;
149165670Sache      else
150165670Sache	{
151165670Sache	  roving->next = c;
152165670Sache	  roving = roving->next;
153165670Sache	}
154165670Sache      list = list->next;
155165670Sache    }
156165670Sache
157165670Sache  roving->next = 0;
158165670Sache  return new;
159165670Sache}
160165670Sache
16121308Sache/* Undo the next thing in the list.  Return 0 if there
16221308Sache   is nothing to undo, or non-zero if there was. */
16321308Sacheint
16421308Sacherl_do_undo ()
16521308Sache{
16621308Sache  UNDO_LIST *release;
16775406Sache  int waiting_for_begin, start, end;
16821308Sache
16921308Sache#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
17021308Sache
17175406Sache  start = end = waiting_for_begin = 0;
17221308Sache  do
17321308Sache    {
17421308Sache      if (!rl_undo_list)
17521308Sache	return (0);
17621308Sache
17721308Sache      _rl_doing_an_undo = 1;
17875406Sache      RL_SETSTATE(RL_STATE_UNDOING);
17921308Sache
18021308Sache      /* To better support vi-mode, a start or end value of -1 means
18121308Sache	 rl_point, and a value of -2 means rl_end. */
18221308Sache      if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
18321308Sache	{
18421308Sache	  start = TRANS (rl_undo_list->start);
18521308Sache	  end = TRANS (rl_undo_list->end);
18621308Sache	}
18721308Sache
18821308Sache      switch (rl_undo_list->what)
18921308Sache	{
19021308Sache	/* Undoing deletes means inserting some text. */
19121308Sache	case UNDO_DELETE:
19221308Sache	  rl_point = start;
19321308Sache	  rl_insert_text (rl_undo_list->text);
19421308Sache	  free (rl_undo_list->text);
19521308Sache	  break;
19621308Sache
19721308Sache	/* Undoing inserts means deleting some text. */
19821308Sache	case UNDO_INSERT:
19921308Sache	  rl_delete_text (start, end);
20021308Sache	  rl_point = start;
20121308Sache	  break;
20221308Sache
20321308Sache	/* Undoing an END means undoing everything 'til we get to a BEGIN. */
20421308Sache	case UNDO_END:
20521308Sache	  waiting_for_begin++;
20621308Sache	  break;
20721308Sache
20821308Sache	/* Undoing a BEGIN means that we are done with this group. */
20921308Sache	case UNDO_BEGIN:
21021308Sache	  if (waiting_for_begin)
21121308Sache	    waiting_for_begin--;
21221308Sache	  else
21375406Sache	    rl_ding ();
21421308Sache	  break;
21521308Sache	}
21621308Sache
21721308Sache      _rl_doing_an_undo = 0;
21875406Sache      RL_UNSETSTATE(RL_STATE_UNDOING);
21921308Sache
22021308Sache      release = rl_undo_list;
22121308Sache      rl_undo_list = rl_undo_list->next;
222165670Sache      replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
223165670Sache
22421308Sache      free (release);
22521308Sache    }
22621308Sache  while (waiting_for_begin);
22721308Sache
22821308Sache  return (1);
22921308Sache}
23021308Sache#undef TRANS
23121308Sache
23221308Sacheint
23321308Sache_rl_fix_last_undo_of_type (type, start, end)
23421308Sache     int type, start, end;
23521308Sache{
23621308Sache  UNDO_LIST *rl;
23721308Sache
23821308Sache  for (rl = rl_undo_list; rl; rl = rl->next)
23921308Sache    {
24021308Sache      if (rl->what == type)
24121308Sache	{
24221308Sache	  rl->start = start;
24321308Sache	  rl->end = end;
24421308Sache	  return 0;
24521308Sache	}
24621308Sache    }
24721308Sache  return 1;
24821308Sache}
24921308Sache
25021308Sache/* Begin a group.  Subsequent undos are undone as an atomic operation. */
25121308Sacheint
25221308Sacherl_begin_undo_group ()
25321308Sache{
25421308Sache  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
25521308Sache  _rl_undo_group_level++;
25621308Sache  return 0;
25721308Sache}
25821308Sache
25921308Sache/* End an undo group started with rl_begin_undo_group (). */
26021308Sacheint
26121308Sacherl_end_undo_group ()
26221308Sache{
26321308Sache  rl_add_undo (UNDO_END, 0, 0, 0);
26421308Sache  _rl_undo_group_level--;
26521308Sache  return 0;
26621308Sache}
26721308Sache
26821308Sache/* Save an undo entry for the text from START to END. */
26921308Sacheint
27021308Sacherl_modifying (start, end)
27121308Sache     int start, end;
27221308Sache{
27321308Sache  if (start > end)
27421308Sache    {
27521308Sache      SWAP (start, end);
27621308Sache    }
27721308Sache
27821308Sache  if (start != end)
27921308Sache    {
28021308Sache      char *temp = rl_copy_text (start, end);
28121308Sache      rl_begin_undo_group ();
28221308Sache      rl_add_undo (UNDO_DELETE, start, end, temp);
28321308Sache      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
28421308Sache      rl_end_undo_group ();
28521308Sache    }
28621308Sache  return 0;
28721308Sache}
28821308Sache
28921308Sache/* Revert the current line to its previous state. */
29021308Sacheint
29121308Sacherl_revert_line (count, key)
29221308Sache     int count, key;
29321308Sache{
29421308Sache  if (!rl_undo_list)
29575406Sache    rl_ding ();
29621308Sache  else
29721308Sache    {
29821308Sache      while (rl_undo_list)
29921308Sache	rl_do_undo ();
300157184Sache#if defined (VI_MODE)
301157184Sache      if (rl_editing_mode == vi_mode)
302157184Sache	rl_point = rl_mark = 0;		/* rl_end should be set correctly */
303157184Sache#endif
30421308Sache    }
305157184Sache
30621308Sache  return 0;
30721308Sache}
30821308Sache
30921308Sache/* Do some undoing of things that were done. */
31021308Sacheint
31121308Sacherl_undo_command (count, key)
31221308Sache     int count, key;
31321308Sache{
31421308Sache  if (count < 0)
31521308Sache    return 0;	/* Nothing to do. */
31621308Sache
31721308Sache  while (count)
31821308Sache    {
31921308Sache      if (rl_do_undo ())
32021308Sache	count--;
32121308Sache      else
32221308Sache	{
32375406Sache	  rl_ding ();
32421308Sache	  break;
32521308Sache	}
32621308Sache    }
32721308Sache  return 0;
32821308Sache}
329