/* readline.c -- a general facility for reading lines of input
   with emacs style editing and completion. */

/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.

   This file is part of the GNU Readline Library, a library for
   reading lines of text with interactive input and history editing.

   The GNU Readline Library 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 2, or
   (at your option) any later version.

   The GNU Readline Library 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.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#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"

/* 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			    */
/*								    */
/* **************************************************************** */

/* 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 = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
  temp->what = what;
  temp->start = start;
  temp->end = end;
  temp->text = text;
  temp->next = rl_undo_list;
  rl_undo_list = temp;
}

/* Free the existing undo list. */
void
rl_free_undo_list ()
{
  while (rl_undo_list)
    {
      UNDO_LIST *release = rl_undo_list;
      rl_undo_list = rl_undo_list->next;

      if (release->what == UNDO_DELETE)
	free (release->text);

      free (release);
    }
  rl_undo_list = (UNDO_LIST *)NULL;
}

/* 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)
	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);
	  free (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;
      free (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)
    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;
}
