#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif
#include <stdio.h>
#include "rldefs.h"
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#include "xmalloc.h"
int _rl_doing_an_undo = 0;
int _rl_undo_group_level = 0;
UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
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;
}
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;
}
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);
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)
{
case UNDO_DELETE:
rl_point = start;
rl_insert_text (rl_undo_list->text);
free (rl_undo_list->text);
break;
case UNDO_INSERT:
rl_delete_text (start, end);
rl_point = start;
break;
case UNDO_END:
waiting_for_begin++;
break;
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;
}
int
rl_begin_undo_group ()
{
rl_add_undo (UNDO_BEGIN, 0, 0, 0);
_rl_undo_group_level++;
return 0;
}
int
rl_end_undo_group ()
{
rl_add_undo (UNDO_END, 0, 0, 0);
_rl_undo_group_level--;
return 0;
}
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;
}
int
rl_revert_line (count, key)
int count, key;
{
if (!rl_undo_list)
rl_ding ();
else
{
while (rl_undo_list)
rl_do_undo ();
}
return 0;
}
int
rl_undo_command (count, key)
int count, key;
{
if (count < 0)
return 0;
while (count)
{
if (rl_do_undo ())
count--;
else
{
rl_ding ();
break;
}
}
return 0;
}