mirror of
https://github.com/MariaDB/server.git
synced 2025-01-23 15:24:16 +01:00
87a569f3c0
cmd-line-utils/readline/undo.c: Replace an "uint" cast by the expanded "unsigned int", because there are platforms (QNX) on which "uint" is not defined in the "readline" library (and so building it failed, version 5.0.34).
259 lines
5.8 KiB
C
259 lines
5.8 KiB
C
/* 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
|
|
|
|
#include "config_readline.h"
|
|
|
|
#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 == (unsigned int) 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 (int count __attribute__((unused)), int key __attribute__((unused)))
|
|
{
|
|
if (!rl_undo_list)
|
|
rl_ding ();
|
|
else
|
|
{
|
|
while (rl_undo_list)
|
|
rl_do_undo ();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Do some undoing of things that were done. */
|
|
int
|
|
rl_undo_command (int count, int key __attribute__((unused)))
|
|
{
|
|
if (count < 0)
|
|
return 0; /* Nothing to do. */
|
|
|
|
while (count)
|
|
{
|
|
if (rl_do_undo ())
|
|
count--;
|
|
else
|
|
{
|
|
rl_ding ();
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|