TheGNUGeneralPublicLicenseisoftenshippedwithGNUsoftware,and isgenerallykeptinafilecalledCOPYINGorLICENSE.Ifyoudonot haveacopyofthelicense,writetotheFreeSoftwareFoundation,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ #define READLINE_LIBRARY
#ifdefined (HAVE_CONFIG_H) # include "config_readline.h" #endif
#ifdefined (HAVE_UNISTD_H) # include <unistd.h> #endif/* HAVE_UNISTD_H */
#ifdefined (HAVE_STDLIB_H) # include <stdlib.h> #else # include "ansi_stdlib.h" #endif/* HAVE_STDLIB_H */
#ifdefined (HAVE_LOCALE_H) # include <locale.h> #endif
#include <stdio.h>
/* System-specific feature definitions and include files. */ #include"rldefs.h" #include"rlmbutil.h"
/* Insert a string of text into the line at point. This is the only waythatyoushoulddoinsertion._rl_insert_char()callsthis
function. Returns the number of characters inserted. */ int
rl_insert_text (string) constchar *string;
{ registerint i, l;
l = (string && *string) ? strlen (string) : 0; if (l == 0) return0;
if (rl_end + l >= rl_line_buffer_len)
rl_extend_line_buffer (rl_end + l);
for (i = rl_end; i >= rl_point; i--)
rl_line_buffer[i + l] = rl_line_buffer[i];
strncpy (rl_line_buffer + rl_point, string, l);
/* Remember how to undo this if we aren't undoing something. */ if (_rl_doing_an_undo == 0)
{ /* If possible and desirable, concatenate the undos. */ if ((l == 1) &&
rl_undo_list &&
(rl_undo_list->what == UNDO_INSERT) &&
(rl_undo_list->end == rl_point) &&
(rl_undo_list->end - rl_undo_list->start < 20))
rl_undo_list->end++; else
rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
}
rl_point += l;
rl_end += l;
rl_line_buffer[rl_end] = '\0'; return l;
}
/* Delete the string between FROM and TO. FROM is inclusive, TO is not.
Returns the number of characters deleted. */ int
rl_delete_text (from, to) int from, to;
{ registerchar *text; registerint diff, i;
/* Fix it if the caller is confused. */ if (from > to)
SWAP (from, to);
/* fix boundaries */ if (to > rl_end)
{
to = rl_end; if (from > to)
from = to;
} if (from < 0)
from = 0;
text = rl_copy_text (from, to);
/* Some versions of strncpy() can't handle overlapping arguments. */
diff = to - from; for (i = from; i < rl_end - diff; i++)
rl_line_buffer[i] = rl_line_buffer[i + diff];
/* Remember how to undo this delete. */ if (_rl_doing_an_undo == 0)
rl_add_undo (UNDO_DELETE, from, to, text); else
free (text);
/* Fix up point so that it is within the line boundaries after killing text.IfFIX_MARK_TOOisnon-zero,themarkisforcedwithinline
boundaries also. */
#define _RL_FIX_POINT(x) \ do { \ if (x > rl_end) \
x = rl_end; \ elseif (x < 0) \
x = 0; \
} while (0)
void
_rl_fix_point (fix_mark_too) int fix_mark_too;
{
_RL_FIX_POINT (rl_point); if (fix_mark_too)
_RL_FIX_POINT (rl_mark);
} #undef _RL_FIX_POINT
/* Replace the contents of the line buffer between START and END with TEXT.Theoperationisundoable.Toreplacetheentirelineinan
undoable mode, use _rl_replace_text(text, 0, rl_end); */ int
_rl_replace_text (text, start, end) constchar *text; int start, end;
{ int n;
rl_begin_undo_group ();
rl_delete_text (start, end + 1);
rl_point = start;
n = rl_insert_text (text);
rl_end_undo_group ();
return n;
}
/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
non-zero, we free the current undo list. */ void
rl_replace_line (text, clear_undo) constchar *text; int clear_undo;
{ int len;
len = strlen (text); if (len >= rl_line_buffer_len)
rl_extend_line_buffer (len);
strcpy (rl_line_buffer, text);
rl_end = len;
/* Note that if you `optimize' the display for these functions, you cannot usesaidfunctionsinotherfunctionswhichdonotdooptimizingdisplay. I.e.,youwillhavetoupdatethedatabaseforrl_redisplay,andyou
might as well let rl_redisplay do that job. */
/* Move forward COUNT bytes. */ int
rl_forward_byte (count, key) int count, key;
{ if (count < 0) return (rl_backward_byte (-count, key));
if (count > 0)
{ int end = rl_point + count; #ifdefined (VI_MODE) int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end; #else int lend = rl_end; #endif
#ifdefined (HANDLE_MULTIBYTE) /* Move backward COUNT characters. */ int
rl_backward_char (count, key) int count, key;
{ int point;
if (MB_CUR_MAX == 1 || rl_byte_oriented) return (rl_backward_byte (count, key));
if (count < 0) return (rl_forward_char (-count, key));
if (count > 0)
{
point = rl_point;
while (count > 0 && point > 0)
{
point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
count--;
} if (count > 0)
{
rl_point = 0;
rl_ding ();
} else
rl_point = point;
}
return0;
} #else int
rl_backward_char (count, key) int count, key;
{ return (rl_backward_byte (count, key));
} #endif
/* Backwards compatibility. */ int
rl_backward (count, key) int count, key;
{ return (rl_backward_char (count, key));
}
/* Move to the beginning of the line. */ int
rl_beg_of_line (count, key) int count __attribute__((unused)), key __attribute__((unused));
{
rl_point = 0; return0;
}
/* Move to the end of the line. */ int
rl_end_of_line (count, key) int count __attribute__((unused)), key __attribute__((unused));
{
rl_point = rl_end; return0;
}
/* Move forward a word. We do what Emacs does. Handles multibyte chars. */ int
rl_forward_word (count, key) int count, key;
{ int c;
if (count < 0) return (rl_backward_word (-count, key));
while (count)
{ if (rl_point == rl_end) return0;
/* If we are not in a word, move forward until we are in one.
Then, move forward until we hit a non-alphabetic character. */
c = _rl_char_value (rl_line_buffer, rl_point);
if (_rl_walphabetic (c) == 0)
{
rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); while (rl_point < rl_end)
{
c = _rl_char_value (rl_line_buffer, rl_point); if (_rl_walphabetic (c)) break;
rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
}
}
/* Move backward a word. We do what Emacs does. Handles multibyte chars. */ int
rl_backward_word (count, key) int count, key;
{ int c, p;
if (count < 0) return (rl_forward_word (-count, key));
while (count)
{ if (rl_point == 0) return0;
/* Like rl_forward_word (), except that we look at the characters
just before point. */
p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
c = _rl_char_value (rl_line_buffer, p);
if (_rl_walphabetic (c) == 0)
{
rl_point = p; while (rl_point > 0)
{
p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
c = _rl_char_value (rl_line_buffer, p); if (_rl_walphabetic (c)) break;
rl_point = p;
}
}
while (rl_point)
{
p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
c = _rl_char_value (rl_line_buffer, p); if (_rl_walphabetic (c) == 0) break; else
rl_point = p;
}
--count;
}
return0;
}
/* Clear the current line. Numeric argument to C-l does this. */ int
rl_refresh_line (ignore1, ignore2) int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
{ int curr_line;
curr_line = _rl_current_display_line ();
_rl_move_vert (curr_line);
_rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
_rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
/* C-l typed to a line without quoting clears the screen, and then reprints thepromptandthecurrentinputline.Givenanumericarg,redrawonly
the current line. */ int
rl_clear_screen (count, key) int count, key;
{ if (rl_explicit_arg)
{
rl_refresh_line (count, key); return0;
}
_rl_clear_screen (); /* calls termcap function to clear screen */
rl_forced_update_display ();
rl_display_fixed = 1;
return0;
}
int
rl_arrow_keys (count, c) int count, c __attribute__((unused));
{ int ch;
/* Insert the character C at the current location, moving point forward. IfCintroducesamultibytesequence,wereadthewholesequenceand
then insert the multibyte char into the line buffer. */ int
_rl_insert_char (count, c) int count, c;
{ registerint i; char *string; #ifdef HANDLE_MULTIBYTE int string_size; char incoming[MB_LEN_MAX + 1]; int incoming_length = 0;
mbstate_t ps_back; staticint stored_count = 0; #endif
if (ret == (size_t)-2)
{ /* Bytes too short to compose character, try to wait for next byte. Restorethestateofthebytesequence,becauseinthiscasethe
effect of mbstate is undefined. */
ps = ps_back; return1;
} elseif (ret == (size_t)-1)
{ /* Invalid byte sequence for the current locale. Treat first byte
as a single character. */
incoming[0] = pending_bytes[0];
incoming[1] = '\0';
incoming_length = 1;
pending_bytes_length--;
memmove (pending_bytes, pending_bytes + 1, pending_bytes_length); /* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
} elseif (ret == (size_t)0)
{
incoming[0] = '\0';
incoming_length = 0;
pending_bytes_length--; /* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
} else
{ /* We successfully read a single multibyte character. */
memcpy (incoming, pending_bytes, pending_bytes_length);
incoming[pending_bytes_length] = '\0';
incoming_length = pending_bytes_length;
pending_bytes_length = 0;
}
} #endif/* HANDLE_MULTIBYTE */
/* If we can optimize, then do it. But don't let people crash
readline because of extra large arguments. */ if (count > 1 && count <= 1024)
{ #ifdefined (HANDLE_MULTIBYTE)
string_size = count * incoming_length;
string = (char *)xmalloc (1 + string_size);
i = 0; while (i < string_size)
{
strncpy (string + i, incoming, incoming_length);
i += incoming_length;
}
incoming_length = 0;
stored_count = 0; #else/* !HANDLE_MULTIBYTE */
string = (char *)xmalloc (1 + count);
for (i = 0; i < count; i++)
string[i] = c; #endif/* !HANDLE_MULTIBYTE */
if (MB_CUR_MAX == 1 || rl_byte_oriented)
{ /* We are inserting a single character. Ifthereispendinginput,thenmakeastringofallofthe pendingcharactersthatareboundtorl_insert,andinsert
them all. */ if (_rl_any_typein ())
_rl_insert_typein (c); else
{ /* Inserting a single character. */ char str[2];
/* Overwrite the character at point (or next COUNT characters) with C. IfCintroducesamultibytecharactersequence,readtheentiresequence
before starting the overwrite loop. */ int
_rl_overwrite_char (count, c) int count, c;
{ int i; #ifdefined (HANDLE_MULTIBYTE) char mbkey[MB_LEN_MAX];
/* Read an entire multibyte character sequence to insert COUNT times. */ if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
_rl_read_mbstring (c, mbkey, MB_LEN_MAX); #endif
rl_begin_undo_group ();
for (i = 0; i < count; i++)
{ #ifdefined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
rl_insert_text (mbkey); else #endif
_rl_insert_char (1, c);
if (rl_point < rl_end)
rl_delete (1, c);
}
rl_end_undo_group ();
return0;
}
int
rl_insert (count, c) int count, c;
{ return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
: _rl_overwrite_char (count, c));
}
/* Insert the next typed character verbatim. */ staticint
_rl_insert_next (count) int count;
{ int c;
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#ifdefined (HANDLE_SIGNALS) if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_restore_tty_signals (); #endif
return (_rl_insert_char (count, c));
}
#ifdefined (READLINE_CALLBACKS) staticint
_rl_insert_next_callback (data)
_rl_callback_generic_arg *data;
{ int count;
count = data->count;
/* Deregister function, let rl_callback_read_char deallocate data */
_rl_callback_func = 0;
_rl_want_redisplay = 1;
return _rl_insert_next (count);
} #endif
int
rl_quoted_insert (count, key) int count, key __attribute__((unused));
{ /* Let's see...should the callback interface futz with signal handling? */ #ifdefined (HANDLE_SIGNALS) if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_disable_tty_signals (); #endif
/* Insert a tab character. */ int
rl_tab_insert (count, key) int count, key __attribute__((unused));
{ return (_rl_insert_char (count, '\t'));
}
/* What to do when a NEWLINE is pressed. We accept the whole line. KEYisthekeythatinvokedthiscommand.Iguessitcouldhave
meaning in the future. */ int
rl_newline (count, key) int count __attribute__((unused)), key __attribute__((unused));
{
rl_done = 1;
/* If we've been asked to erase empty lines, suppress the final update,
since _rl_update_final calls rl_crlf(). */ if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) return0;
if (readline_echoing_p)
_rl_update_final (); return0;
}
/* What to do for some uppercase characters, like meta characters, andsomecharactersappearinginemacs_ctlx_keymap.Thisfunction isjustastub,youbindkeystoitandthecodein_rl_dispatch()
is special cased. */ int
rl_do_lowercase_version (ignore1, ignore2) int ignore1 __attribute__((unused)), ignore2 __attribute__((unused));
{ return0;
}
/* This is different from what vi does, so the code's not shared. Emacs ruboutinoverwritemodehasoneoddity:itreplacesacontrol
character that's displayed as two characters (^X) with two spaces. */ int
_rl_overwrite_rubout (count, key) int count, key;
{ int opoint; int i, l;
if (rl_point == 0)
{
rl_ding (); return1;
}
opoint = rl_point;
/* L == number of spaces to insert */ for (i = l = 0; i < count; i++)
{
rl_backward_char (1, key);
l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */
}
/* Emacs puts point at the beginning of the sequence of spaces. */ if (rl_point < rl_end)
{
opoint = rl_point;
_rl_insert_char (l, ' ');
rl_point = opoint;
}
rl_end_undo_group ();
return0;
}
/* Rubout the character behind point. */ int
rl_rubout (count, key) int count, key;
{ if (count < 0) return (rl_delete (-count, key));
if (!rl_point)
{
rl_ding (); return -1;
}
if (rl_insert_mode == RL_IM_OVERWRITE) return (_rl_overwrite_rubout (count, key));
return (_rl_rubout_char (count, key));
}
int
_rl_rubout_char (count, key) int count, key;
{ int orig_point; unsignedchar c;
/* Duplicated code because this is called from other parts of the library. */ if (count < 0) return (rl_delete (-count, key));
if (rl_point == 0)
{
rl_ding (); return -1;
}
orig_point = rl_point; if (count > 1 || rl_explicit_arg)
{
rl_backward_char (count, key);
rl_kill_text (orig_point, rl_point);
} elseif (MB_CUR_MAX == 1 || rl_byte_oriented)
{
c = rl_line_buffer[--rl_point];
rl_delete_text (rl_point, orig_point); /* The erase-at-end-of-line hack is of questionable merit now. */ if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
{ int l;
l = rl_character_len (c, rl_point);
_rl_erase_at_end_of_line (l);
}
} else
{
rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
rl_delete_text (rl_point, orig_point);
}
return0;
}
/* Delete the character under the cursor. Given a numeric argument,
kill that many characters instead. */ int
rl_delete (count, key) int count, key;
{ int xpoint;
if (count < 0) return (_rl_rubout_char (-count, key));
if (rl_point == rl_end)
{
rl_ding (); return -1;
}
/* Delete the character under the cursor, unless the insertion pointisattheendoftheline,inwhichcasethecharacter behindthecursorisdeleted.COUNTisobeyedandmaybeused
to delete forward or backward that many characters. */ int
rl_rubout_or_delete (count, key) int count, key;
{ if (rl_end != 0 && rl_point == rl_end) return (_rl_rubout_char (count, key)); else return (rl_delete (count, key));
}
/* Delete all spaces and tabs around point. */ int
rl_delete_horizontal_space (count, ignore) int count __attribute__((unused)), ignore __attribute__((unused));
{ int start = rl_point;
while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
rl_point--;
start = rl_point;
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
rl_point++;
/* Like the tcsh editing function delete-char-or-list. The eof character iscaughtbeforethisisinvoked,sothisreallydoesthesamethingas
delete-char-or-list-or-eof, as long as it's bound to the eof character. */ int
rl_delete_or_show_completions (count, key) int count, key;
{ if (rl_end != 0 && rl_point == rl_end) return (rl_possible_completions (count, key)); else return (rl_delete (count, key));
}
/* Turn the current line into a comment in shell history.
A K*rn shell style function. */ int
rl_insert_comment (count, key) int count __attribute__((unused)), key;
{ constchar *rl_comment_text; int rl_comment_len;
/* The three kinds of things that we know how to do. */ #define UpCase 1 #define DownCase 2 #define CapCase 3
/* Uppercase the word at point. */ int
rl_upcase_word (count, key) int count, key __attribute__((unused));
{ return (rl_change_case (count, UpCase));
}
/* Lowercase the word at point. */ int
rl_downcase_word (count, key) int count, key __attribute__((unused));
{ return (rl_change_case (count, DownCase));
}
/* Upcase the first letter, downcase the rest. */ int
rl_capitalize_word (count, key) int count, key __attribute__((unused));
{ return (rl_change_case (count, CapCase));
}
/* The meaty function. ChangethecaseofCOUNTwords,performingOPonthem. OPisoneofUpCase,DownCase,orCapCase. Ifanegativeargumentisgiven,leavepointwhereitstarted,
otherwise, leave it where it moves to. */ staticint
rl_change_case (count, op) int count, op;
{ int start, next, end; int inword, c, nc, nop; #ifdefined (HANDLE_MULTIBYTE) wchar_t wc, nwc; char mb[MB_LEN_MAX+1]; int mlen;
mbstate_t mps; #endif
start = rl_point;
rl_forward_word (count, 0);
end = rl_point;
if (op != UpCase && op != DownCase && op != CapCase)
{
rl_ding (); return -1;
}
/* We are going to modify some text, so let's prepare to undo it. */
rl_modifying (start, end);
inword = 0; while (start < end)
{
c = _rl_char_value (rl_line_buffer, start); /* This assumes that the upper and lower case versions are the same width. */
next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
/* Transpose the words at point. If point is at the end of the line,
transpose the two words before point. */ int
rl_transpose_words (count, key) int count, key;
{ char *word1, *word2; int w1_beg, w1_end, w2_beg, w2_end; int orig_point = rl_point;
/* Do some check to make sure that there really are two words. */ if ((w1_beg == w2_beg) || (w2_beg < w1_end))
{
rl_ding ();
rl_point = orig_point; return -1;
}
/* Get the text of the words. */
word1 = rl_copy_text (w1_beg, w1_end);
word2 = rl_copy_text (w2_beg, w2_end);
/* We are about to do many insertions and deletions. Remember them
as one operation. */
rl_begin_undo_group ();
/* Do the stuff at word2 first, so that we don't have to worry
about word1 moving. */
rl_point = w2_beg;
rl_delete_text (w2_beg, w2_end);
rl_insert_text (word1);
/* This is exactly correct since the text before this point has not
changed in length. */
rl_point = w2_end;
/* I think that does it. */
rl_end_undo_group ();
free (word1);
free (word2);
return0;
}
/* Transpose the characters at point. If point is at the end of the line,
then transpose the characters before point. */ int
rl_transpose_chars (count, key) int count, key __attribute__((unused));
{ #ifdefined (HANDLE_MULTIBYTE) char *dummy; int i; int prev_point; #else char dummy[2]; #endif int char_length;
/* Search COUNT times for a character read from the current input stream. FDIRisthedirectiontosearchifCOUNTisnon-negative;otherwise thesearchgoesinBDIR.SomuchisdependentonHANDLE_MULTIBYTE
that there are two separate versions of this function. */ #ifdefined (HANDLE_MULTIBYTE) staticint
_rl_char_search (count, fdir, bdir) int count, fdir, bdir;
{ char mbchar[MB_LEN_MAX]; int mb_len;
/* **************************************************************** */ /* */ /* The Mark and the Region. */ /* */ /* **************************************************************** */
/* Set the mark at POSITION. */ int
_rl_set_mark_at_pos (position) int position;
{ if (position > rl_end) return -1;
rl_mark = position; return0;
}
/* A bindable command to set the mark. */ int
rl_set_mark (count, key) int count, key __attribute__((unused));
{ return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
}
/* Exchange the position of mark and point. */ int
rl_exchange_point_and_mark (count, key) int count __attribute__((unused)), key __attribute__((unused));
{ if (rl_mark > rl_end)
rl_mark = -1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.