File Coverage

lib/Term/ReadLine/Perl5/readline.pm
Criterion Covered Total %
statement 360 1656 21.7
branch 179 996 17.9
condition 51 342 14.9
subroutine 45 228 19.7
pod 95 205 46.3
total 730 3427 21.3


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             =head1 NAME
3              
4             Term::ReadLine::Perl5::readline
5              
6             =head1 DESCRIPTION
7              
8             A non-OO package similar to GNU's readline. The preferred OO Package
9             is L. But that uses this internally.
10              
11             It could be made better by removing more of the global state and
12             moving it into the L side.
13              
14             There is some support for EUC-encoded Japanese text. This should be
15             rewritten for Perl Unicode though.
16              
17             Someone please volunteer to rewrite this!
18              
19             See also L.
20              
21             =cut
22              
23 11     11   65995 use warnings;
  11         38  
  11         565  
24             package Term::ReadLine::Perl5::readline;
25 11     11   78 use File::Glob ':glob';
  11         30  
  11         3258  
26              
27             # no critic
28             # Version can be below the version given in Term::ReadLine::Perl5
29             our $VERSION = '1.45';
30              
31             #
32             # Separation into my and vars needs more work.
33             # use strict 'vars';
34             #
35 11         4394 use vars qw(@KeyMap %KeyMap $rl_screen_width $rl_start_default_at_beginning
36             $rl_completion_function $rl_basic_word_break_characters
37             $rl_completer_word_break_characters $rl_special_prefixes
38             $rl_max_numeric_arg $rl_OperateCount
39             $rl_completion_suppress_append
40             $history_stifled
41             $KillBuffer $dumb_term $stdin_not_tty $InsertMode
42             $mode $winsz $force_redraw
43             $have_getpwent $minlength $rl_readline_name
44             @winchhooks $rl_NoInitFromFile
45             $editingMode $Vi_mode &rl_editMode
46             $DEBUG;
47 11     11   96 );
  11         29  
48              
49             @ISA = qw(Exporter);
50             @EXPORT = qw($minlength rl_NoInitFromFile rl_bind rl_set
51             rl_read_init_file
52             rl_basic_commands rl_filename_list
53             completion_function);
54              
55              
56 11     11   3700 use File::HomeDir;
  11         46447  
  11         735  
57 11     11   92 use File::Spec;
  11         31  
  11         267  
58 11     11   3240 use Term::ReadKey;
  11         17476  
  11         1096  
59              
60 11     11   109 eval "use rlib '.' "; # rlib is now optional
  11         33  
  11         104  
61 11     11   3981 use Term::ReadLine::Perl5::Common;
  11         42  
  11         743  
62 11     11   7632 use Term::ReadLine::Perl5::Dumb;
  11         39  
  11         411  
63 11     11   75 use Term::ReadLine::Perl5::History;
  11         51  
  11         1515  
64             use Term::ReadLine::Perl5::Keymap
65 11     11   3790 qw(KeymapEmacs KeymapVi KeymapVicmd KeymapVipos KeymapVisearch);
  11         37  
  11         871  
66 11     11   6554 use Term::ReadLine::Perl5::TermCap; # For ornaments
  11         35  
  11         1148  
67              
68             my $autoload_broken = 1; # currently: defined does not work with a-l
69             my $useioctl = 1;
70             my $usestty = 1;
71             my $max_include_depth = 10; # follow $include's in init files this deep
72              
73             my $HOME = File::HomeDir->my_home;
74              
75             BEGIN { # Some old systems have ioctl "unsupported"
76 11     11   11416 *ioctl = sub ($$$) { eval { CORE::ioctl $_[0], $_[1], $_[2] } };
  0     0   0  
  0         0  
77             }
78              
79             $rl_getc = \&rl_getc;
80             $minlength = 1;
81             $history_stifled = 0;
82              
83             &preinit;
84             &init;
85              
86             my $inDOS;
87              
88             # True when we're in one of the vi modes.
89             $Vi_mode = 0;
90              
91             # Array refs: saves keystrokes for '.' command. Undefined when we're
92             # not doing a '.'-able command.
93             my $Dot_buf; # Working buffer
94             my $Last_vi_command; # Gets $Dot_buf when a command is parsed
95              
96             # These hold state for vi 'u' and 'U'.
97             my($Dot_state, $Vi_undo_state, $Vi_undo_all_state);
98              
99             # Refs to hashes used for cursor movement
100             my($Vi_delete_patterns, $Vi_move_patterns,
101             $Vi_change_patterns, $Vi_yank_patterns);
102              
103             # Array ref: holds parameters from the last [fFtT] command, for ';'
104             # and ','.
105             my $Last_findchar;
106              
107             # Globals for history search commands (/, ?, n, N)
108             my $Vi_search_re; # Regular expression (compiled by qr{})
109             my $Vi_search_reverse; # True for '?' search, false for '/'
110              
111             =head1 SUBROUTINES
112              
113             =cut
114              
115             # Fix: case-sensitivity of inputrc on/off keywords in
116             # `set' commands. readline lib doesn't care about case.
117             # changed case of keys 'On' and 'Off' to 'on' and 'off'
118             # &rl_set changed so that it converts the value to
119             # lower case before hash lookup.
120             sub preinit
121             {
122 14 100   14 0 97 my $editMode = scalar(@_) > 0 ? $_[0] : 'vicmd';
123 14         41 $DEBUG = 0;
124              
125             ## Set up the input and output handles
126              
127 14 100       92 $term_IN = \*STDIN unless defined $term_IN;
128 14 100       63 $term_OUT = \*STDOUT unless defined $term_OUT;
129             ## not yet supported... always on.
130 14         39 $var_HorizontalScrollMode = 1;
131 14         50 $var_HorizontalScrollMode{'On'} = 1;
132 14         45 $var_HorizontalScrollMode{'Off'} = 0;
133              
134 14         51 $var_EditingMode{'emacs'} = \@emacs_keymap;
135 14         48 $var_EditingMode{'vi'} = \@vi_keymap;
136 14         50 $var_EditingMode{'vicmd'} = \@vicmd_keymap;
137 14         45 $var_EditingMode{'vipos'} = \@vipos_keymap;
138 14         48 $var_EditingMode{'visearch'} = \@visearch_keymap;
139              
140             ## this is an addition. Very nice.
141 14         40 $var_TcshCompleteMode = 0;
142 14         44 $var_TcshCompleteMode{'On'} = 1;
143 14         41 $var_TcshCompleteMode{'Off'} = 0;
144              
145 14         66 $var_CompleteAddsuffix = 1;
146 14         45 $var_CompleteAddsuffix{'On'} = 1;
147 14         43 $var_CompleteAddsuffix{'Off'} = 0;
148              
149 14         49 $var_DeleteSelection = $var_DeleteSelection{'On'} = 1;
150 14         42 $var_DeleteSelection{'Off'} = 0;
151 14         224 *rl_delete_selection = \$var_DeleteSelection; # Alias
152              
153             ## not yet supported... always on
154 14         58 for ('InputMeta', 'OutputMeta') {
155 28         63 ${"var_$_"} = 1;
  28         149  
156 28         63 ${"var_$_"}{'Off'} = 0;
  28         103  
157 28         66 ${"var_$_"}{'On'} = 1;
  28         97  
158             }
159              
160             ## not yet supported... always off
161 14         68 for (
162             qw(
163             BlinkMatchingParen
164             ConvertMeta
165             EnableKeypad
166             PrintCompletionsHorizontally
167             CompletionIgnoreCase
168             DisableCompletion
169             MarkDirectories
170             MarkModifiedLines
171             MetaFlag
172             PreferVisibleBell
173             ShowAllIfAmbiguous
174             VisibleStats
175             )) {
176 168         278 ${"var_$_"} = 0;
  168         679  
177 168         293 ${"var_$_"}{'Off'} = 0;
  168         454  
178 168         281 ${"var_$_"}{'On'} = 1;
  168         444  
179             }
180              
181             # WINCH hooks
182 14         52 @winchhooks = ();
183              
184 14 100 33     185 $inDOS = $^O eq 'os2' || defined $ENV{OS2_SHELL} unless defined $inDOS;
185              
186             # try to get, don't die if not found.
187 14         314 eval {require "ioctl.pl"};
  14         1089  
188 14         67 eval {require "sgtty.ph"};
  14         640  
189              
190 14 50 33     104 if ($inDOS and !defined $TIOCGWINSZ) {
191 0         0 $TIOCGWINSZ=0;
192 0         0 $TIOCGETP=1;
193 0         0 $TIOCSETP=2;
194 0         0 $sgttyb_t="I5 C8";
195 0         0 $winsz_t="";
196 0         0 $RAW=0xf002;
197 0         0 $ECHO=0x0008;
198             }
199 14 50       76 $TIOCGETP = &TIOCGETP if defined(&TIOCGETP);
200 14 50       56 $TIOCSETP = &TIOCSETP if defined(&TIOCSETP);
201 14 50       109 $TIOCGWINSZ = &TIOCGWINSZ if defined(&TIOCGWINSZ);
202 14 50       59 $FIONREAD = &FIONREAD if defined(&FIONREAD);
203 14 50       57 $TCGETS = &TCGETS if defined(&TCGETS);
204 14 50       62 $TCSETS = &TCSETS if defined(&TCSETS);
205 14 50       76 $TCXONC = &TCXONC if defined(&TCXONC);
206 14 100       67 $TIOCGETP = 0x40067408 if !defined($TIOCGETP);
207 14 100       86 $TIOCSETP = 0x80067409 if !defined($TIOCSETP);
208 14 100       69 $TIOCGWINSZ = 0x40087468 if !defined($TIOCGWINSZ);
209 14 100       58 $FIONREAD = 0x4004667f if !defined($FIONREAD);
210 14 100       59 $TCGETS = 0x40245408 if !defined($TCGETS);
211 14 100       53 $TCSETS = 0x80245409 if !defined($TCSETS);
212 14 100       62 $TCXONC = 0x20005406 if !defined($TCXONC);
213              
214             ## TTY modes
215 14 50       63 $ECHO = &ECHO if defined(&ECHO);
216 14 50       55 $RAW = &RAW if defined(&RAW);
217 14 100       61 $RAW = 040 if !defined($RAW);
218 14 100       56 $ECHO = 010 if !defined($ECHO);
219 14         37 $mode = $RAW; ## could choose CBREAK for testing....
220              
221 14 100       76 $IGNBRK = 1 if !defined($IGNBRK);
222 14 100       53 $BRKINT = 2 if !defined($BRKINT);
223 14 100       101 $ISTRIP = 040 if !defined($ISTRIP);
224 14 100       58 $INLCR = 0100 if !defined($INLCR);
225 14 100       125 $IGNCR = 0200 if !defined($IGNCR);
226 14 100       68 $ICRNL = 0400 if !defined($ICRNL);
227 14 100       56 $OPOST = 1 if !defined($OPOST);
228 14 100       82 $ISIG = 1 if !defined($ISIG);
229 14 100       55 $ICANON = 2 if !defined($ICANON);
230 14 100       54 $TCOON = 1 if !defined($TCOON);
231 14         32 $TERMIOS_READLINE_ION = $BRKINT;
232 14         63 $TERMIOS_READLINE_IOFF = $IGNBRK | $ISTRIP | $INLCR | $IGNCR | $ICRNL;
233 14         31 $TERMIOS_READLINE_OON = 0;
234 14         40 $TERMIOS_READLINE_OOFF = $OPOST;
235 14         39 $TERMIOS_READLINE_LON = 0;
236 14         41 $TERMIOS_READLINE_LOFF = $ISIG | $ICANON | $ECHO;
237 14         40 $TERMIOS_NORMAL_ION = $BRKINT;
238 14         34 $TERMIOS_NORMAL_IOFF = $IGNBRK;
239 14         30 $TERMIOS_NORMAL_OON = $OPOST;
240 14         32 $TERMIOS_NORMAL_OOFF = 0;
241 14         40 $TERMIOS_NORMAL_LON = $ISIG | $ICANON | $ECHO;
242 14         34 $TERMIOS_NORMAL_LOFF = 0;
243              
244 14 100       68 $sgttyb_t = 'C4 S' if !defined($sgttyb_t);
245 14 100       55 $winsz_t = "S S S S" if !defined($winsz_t);
246             # rows,cols, xpixel, ypixel
247 14         124 $winsz = pack($winsz_t,0,0,0,0);
248 14         45 $NCCS = 17;
249 14         89 $termios_t = "LLLLc" . ("c" x $NCCS); # true for SunOS 4.1.3, at least...
250 14         41 $termios = ''; ## just to shut up "perl -w".
251 14         50 $termios = pack($termios, 0); # who cares, just make it long enough
252 14         37 $TERMIOS_IFLAG = 0;
253 14         38 $TERMIOS_OFLAG = 1;
254             ## $TERMIOS_CFLAG = 2;
255 14         39 $TERMIOS_LFLAG = 3;
256 14         35 $TERMIOS_VMIN = 5 + 4;
257 14         35 $TERMIOS_VTIME = 5 + 5;
258 14         28 $rl_delete_selection = 1;
259 14 50       62 $rl_correct_sw = ($inDOS ? 1 : 0);
260 14 100       58 $rl_scroll_nextline = 1 unless defined $rl_scroll_nextline;
261 14 50       71 $rl_last_pos_can_backspace = ($inDOS ? 0 : 1) # Can backspace when the
    100          
262             unless defined $rl_last_pos_can_backspace; # whole line is filled?
263              
264 14         35 $rl_start_default_at_beginning = 0;
265 14         49 $rl_vi_replace_default_on_insert = 0;
266 14         31 $rl_screen_width = 79; ## default
267              
268 14 100       60 $rl_completion_function = "rl_filename_list"
269             unless defined($rl_completion_function);
270 14         36 $rl_basic_word_break_characters = "\\\t\n' \"`\@\$><=;|&{(";
271 14         35 $rl_completer_word_break_characters = $rl_basic_word_break_characters;
272 14         38 $rl_special_prefixes = '';
273 14 100       145 ($rl_readline_name = $0) =~ s#.*[/\\]## if !defined($rl_readline_name);
274              
275 14 100       58 $rl_max_numeric_arg = 200 if !defined($rl_max_numeric_arg);
276 14 100       60 $rl_OperateCount = 0 if !defined($rl_OperateCount);
277 14 100       56 $rl_completion_suppress_append = 0
278             if !defined($rl_completion_suppress_append);
279              
280 11     11   155 no warnings 'once';
  11         30  
  11         143440  
281 14         56 $rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
282 14 100       81 @$rl_term_set or $rl_term_set = ["","","",""];
283              
284 14         45 $InsertMode=1;
285 14         36 $KillBuffer='';
286 14         32 $line='';
287 14         38 $D = 0;
288 14         35 $InputLocMsg = ' [initialization]';
289              
290 14         122 KeymapEmacs(\&InitKeymap, \@emacs_keymap, $inDOS);
291 14         56 *KeyMap = \@emacs_keymap;
292 14         52 my @add_bindings = ();
293 14         56 foreach ('-', '0' .. '9') {
294 154         504 push(@add_bindings, "M-$_", 'DigitArgument');
295             }
296 14         83 foreach ("A" .. "Z") {
297             next if
298             # defined($KeyMap[27]) && defined (%{"$KeyMap{name}_27"}) &&
299 364 100       573 defined $ {"$KeyMap{name}_27"}[ord $_];
  364         1064  
300 275         782 push(@add_bindings, "M-$_", 'DoLowercaseVersion');
301             }
302 14 50       73 if ($inDOS) {
303             # Default translation of Alt-char
304 0         0 $ {"$KeyMap{name}_0"}{'Esc'} = *{"$KeyMap{name}_27"};
  0         0  
  0         0  
305 0         0 $ {"$KeyMap{name}_0"}{'default'} = 'F_DoEscVersion';
  0         0  
306             }
307 14         83 &rl_bind(@add_bindings);
308              
309 14         73 local(*KeyMap);
310              
311             # Vi input mode.
312 14         125 KeymapVi(\&InitKeymap, \@vi_keymap);
313              
314             # Vi command mode.
315 14         90 KeymapVicmd(\&InitKeymap, \@vicmd_keymap);
316              
317             # Vi positioning commands (suffixed to vi commands like 'd').
318 14         111 KeymapVipos(\&InitKeymap, \@vipos_keymap, $inDOS);
319              
320             # Vi search string input mode for '/' and '?'.
321 14         114 KeymapVisearch(\&InitKeymap, \@visearch_keymap);
322              
323             # These constant hashes hold the arguments to &forward_scan() or
324             # &backward_scan() for vi positioning commands, which all
325             # behave a little differently for delete, move, change, and yank.
326             #
327             # Note: I originally coded these as qr{}, but changed them to q{} for
328             # compatibility with older perls at the expense of some performance.
329             #
330             # Note: Some of the more obscure key combinations behave slightly
331             # differently in different vi implementation. This module matches
332             # the behavior of /usr/ucb/vi, which is different from the
333             # behavior of vim, nvi, and the ksh command line. One example is
334             # the command '2de', when applied to the string ('^' represents the
335             # cursor, not a character of the string):
336             #
337             # ^5.6 7...88888888
338             #
339             # With /usr/ucb/vi and with this module, the result is
340             #
341             # ^...88888888
342             #
343             # but with the other three vi implementations, the result is
344             #
345             # ^ 7...88888888
346              
347 14         272 $Vi_delete_patterns = {
348             ord('w') => q{(?:\w+|[^\w\s]+|)\s*},
349             ord('W') => q{\S*\s*},
350             ord('b') => q{\w+\s*|[^\w\s]+\s*|^\s+},
351             ord('B') => q{\S+\s*|^\s+},
352             ord('e') => q{.\s*\w+|.\s*[^\w\s]+|.\s*$},
353             ord('E') => q{.\s*\S+|.\s*$},
354             };
355              
356 14         117 $Vi_move_patterns = {
357             ord('w') => q{(?:\w+|[^\w\s]+|)\s*},
358             ord('W') => q{\S*\s*},
359             ord('b') => q{\w+\s*|[^\w\s]+\s*|^\s+},
360             ord('B') => q{\S+\s*|^\s+},
361             ord('e') => q{.\s*\w*(?=\w)|.\s*[^\w\s]*(?=[^\w\s])|.?\s*(?=\s$)},
362             ord('E') => q{.\s*\S*(?=\S)|.?\s*(?=\s$)},
363             };
364              
365 14         92 $Vi_change_patterns = {
366             ord('w') => q{\w+|[^\w\s]+|\s},
367             ord('W') => q{\S+|\s},
368             ord('b') => q{\w+\s*|[^\w\s]+\s*|^\s+},
369             ord('B') => q{\S+\s*|^\s+},
370             ord('e') => q{.\s*\w+|.\s*[^\w\s]+|.\s*$},
371             ord('E') => q{.\s*\S+|.\s*$},
372             };
373              
374 14         92 $Vi_yank_patterns = {
375             ord('w') => q{(?:\w+|[^\w\s]+|)\s*},
376             ord('W') => q{\S*\s*},
377             ord('b') => q{\w+\s*|[^\w\s]+\s*|^\s+},
378             ord('B') => q{\S+\s*|^\s+},
379             ord('e') => q{.\s*\w*(?=\w)|.\s*[^\w\s]*(?=[^\w\s])|.?\s*(?=\s$)},
380             ord('E') => q{.\s*\S*(?=\S)|.?\s*(?=\s$)},
381             };
382              
383 14         64 *KeyMap = $var_EditingMode = $var_EditingMode{$editMode};
384 14         157 1; # Returning a glob causes a bug in db5.001m
385             }
386              
387             # FIXME: something in here causes terminal attributes like bold and
388             # underline to work.
389             sub rl_term_set()
390             {
391 3     3 0 21 $rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
392             }
393              
394             sub init()
395             {
396 14 50 33 14 0 389 if ($ENV{'TERM'} and ($ENV{'TERM'} eq 'emacs' || $ENV{'TERM'} eq 'dumb')) {
    50 33        
      33        
397 0         0 $dumb_term = 1;
398             } elsif (! -c $term_IN && $term_IN eq \*STDIN) { # Believe if it is given
399 0         0 $stdin_not_tty = 1;
400             } else {
401 14         73 &get_window_size;
402 14 50       116 &F_ReReadInitFile if !defined($rl_NoInitFromFile);
403 14         214 $InputLocMsg = '';
404 14         73 *KeyMap = $var_EditingMode;
405             }
406              
407 14         61 $initialized = 1;
408             }
409              
410              
411             =head2 InitKeyMap
412              
413             C
414              
415             =cut
416              
417             sub InitKeymap
418             {
419 609     609 0 1486 local(*KeyMap) = shift(@_);
420 609         1213 my $default = shift(@_);
421 609         1672 my $name = $KeyMap{'name'} = shift(@_);
422              
423             # 'default' is now optional - if '', &do_command() defaults it to
424             # 'F_Ding'. Meta-maps now don't set a default - this lets
425             # us detect multiple '\*' default declarations. JP
426 609 100       1449 if ($default ne '') {
427 70         258 my $func = $KeyMap{'default'} = "F_$default";
428             ### Temporarily disabled
429 70 0 33     227 die qq/Bad default function [$func] for keymap "$name"/
430             if !$autoload_broken and !defined(&$func);
431             }
432              
433 609 100       1620 &rl_bind if @_ > 0; ## The rest of @_ gets passed silently.
434             }
435              
436             sub filler_Pending ($) {
437 0     0 0 0 my $keys = shift;
438             sub {
439 0     0   0 my $c = shift;
440 0         0 push @Pending, map chr, @$keys;
441 0 0 0     0 return if not @$keys or $c == 1 or not defined(my $in = &getc_with_pending);
      0        
442             # provide the numeric argument
443 0         0 local(*KeyMap) = $var_EditingMode;
444 0         0 $doingNumArg = 1; # Allow NumArg inside NumArg
445 0         0 &do_command(*KeyMap, $c, ord $in);
446 0         0 return;
447             }
448 0         0 }
449              
450              
451             =head2 _unescape
452              
453             _unescape($string) -> List of keys
454              
455             This internal function that takes I<$string> possibly containing
456             escape sequences, and converts to a series of octal keys.
457              
458             It has special rules for dealing with readline-specific escape-sequence
459             commands.
460              
461             New-style key bindings are enclosed in double-quotes.
462             Characters are taken verbatim except the special cases:
463              
464             \C-x Control x (for any x)
465             \M-x Meta x (for any x)
466             \e Escape
467             \* Set the keymap default (JP: added this)
468             (must be the last character of the sequence)
469             \x x (unless it fits the above pattern)
470              
471             Special case "\C-\M-x", should be treated like "\M-\C-x".
472              
473             =cut
474              
475             my @ESCAPE_REGEXPS = (
476             # Ctrl-meta
477             [ qr/^\\C-\\M-(.)/, sub { ord("\e"), ctrl(ord(shift)) } ],
478             # Meta
479             [ qr/^\\(M-|e)/, sub { ord("\e") } ],
480             # Ctrl
481             [ qr/^\\C-(.)/, sub { ctrl(ord(shift)) } ],
482             # hex value
483             [ qr/^\\x([0-9a-fA-F]{2})/, sub { hex(shift) } ],
484             # octal value
485             [ qr/^\\([0-7]{3})/, sub { oct(shift) } ],
486             # default
487             [ qr/^\\\*$/, sub { 'default'; } ],
488             # EOT (Ctrl-D)
489             [ qr/^\\d/, sub { 4 } ],
490             # Backspace
491             [ qr/\\b/, sub { 0x7f } ],
492             # Escape Sequence
493             [ qr/\\(.)/,
494             sub {
495             my $chr = shift;
496             ord(($chr =~ /^[afnrtv]$/) ? eval(qq("\\$chr")) : $chr);
497             } ],
498             );
499              
500             sub _unescape ($) {
501 1068     1068   14229 my($key, @keys) = shift;
502              
503 1068         2572 CHAR: while (length($key) > 0) {
504 4087         7176 foreach my $command (@ESCAPE_REGEXPS) {
505 8226         15654 my $regex = $command->[0];
506 8226 100       79395 if ($key =~ s/^$regex//) {
507 65         211 push @keys, $command->[1]->($1);
508 65         241 next CHAR;
509             }
510             }
511 4022         7102 push @keys, ord($key);
512 4022         8897 substr($key,0,1) = '';
513             }
514             @keys
515 1068         3478 }
516              
517             sub RL_func ($) {
518 3811     3811 0 6326 my $name_or_macro = shift;
519 3811 50       16497 if ($name_or_macro =~ /^"((?:\\.|[^\\\"])*)"|^'((?:\\.|[^\\\'])*)'/s) {
520 0         0 filler_Pending [_unescape "$+"];
521             } else {
522 3811         18805 "F_$name_or_macro";
523             }
524             }
525              
526             =head2 bind_parsed_keyseq
527              
528             B(I<$function1>, I<@sequence1>, ...)
529              
530             Actually inserts the binding for I<@sequence> to I<$function> into the
531             current map. I<@sequence> is an array of character ordinals.
532              
533             If C is more than one element long, all but the last will
534             cause meta maps to be created.
535              
536             I<$Function> will have an implicit I prepended to it.
537              
538             0 is returned if there is no error.
539              
540             =cut
541              
542             sub bind_parsed_keyseq
543             {
544 3811     3811 1 6002 my $bad = 0;
545 3811         8164 while (@_) {
546 3811         6624 my $func = shift;
547 3811         5888 my ($key, @keys) = @{shift()};
  3811         8433  
548 3811         6791 $key += 0;
549 3811         6843 local(*KeyMap) = *KeyMap;
550 3811         5686 my $map;
551 3811         8025 while (@keys) {
552 3695 50 66     12803 if (defined($KeyMap[$key]) && ($KeyMap[$key] ne 'F_PrefixMeta')) {
553 0 0       0 warn "Warning$InputLocMsg: ".
554             "Re-binding char #$key from [$KeyMap[$key]] to meta for [@keys] => $func.\n" if $^W;
555             }
556 3695         6872 $KeyMap[$key] = 'F_PrefixMeta';
557 3695         8243 $map = "$KeyMap{'name'}_$key";
558 3695 100       12204 InitKeymap(*$map, '', $map) if !(%$map);
559 3695         8119 *KeyMap = *$map;
560 3695         8733 $key = shift @keys;
561             #&bind_parsed_keyseq($func, \@keys);
562             }
563              
564 3811         7639 my $name = $KeyMap{'name'};
565 3811 100       8038 if ($key eq 'default') { # JP: added
566             warn "Warning$InputLocMsg: ".
567             " changing default action to $func in $name key map\n"
568 24 50 33     141 if $^W && defined $KeyMap{'default'};
569              
570 24         69 $KeyMap{'default'} = RL_func $func;
571             }
572             else {
573 3787 50 66     10032 if (defined($KeyMap[$key]) && $KeyMap[$key] eq 'F_PrefixMeta'
      33        
574             && $func ne 'PrefixMeta')
575             {
576 0 0       0 warn "Warning$InputLocMsg: ".
577             " Re-binding char #$key to non-meta ($func) in $name key map\n"
578             if $^W;
579             }
580 3787         7427 $KeyMap[$key] = RL_func $func;
581             }
582             }
583 3811         19592 return $bad;
584             }
585              
586             =head2 GNU ReadLine-ish Routines
587              
588             Many of these aren't the the name GNU readline uses, nor do they
589             correspond to GNU ReadLine functions. Sigh.
590              
591             =head3 rl_bind_keyseq
592              
593             B(I<$keyspec>, I<$function>)
594              
595             Bind the key sequence represented by the string I to the
596             function function, beginning in the current keymap. This makes new
597             keymaps as necessary. The return value is non-zero if keyseq is
598             invalid. I<$keyspec> should be the name of key sequence in one of two
599             forms:
600              
601             Old (GNU readline documented) form:
602              
603             M-x to indicate Meta-x
604             C-x to indicate Ctrl-x
605             M-C-x to indicate Meta-Ctrl-x
606             x simple char x
607              
608             where I above can be a single character, or the special:
609              
610             special means
611             -------- -----
612             space space ( )
613             spc space ( )
614             tab tab (\t)
615             del delete (0x7f)
616             rubout delete (0x7f)
617             newline newline (\n)
618             lfd newline (\n)
619             ret return (\r)
620             return return (\r)
621             escape escape (\e)
622             esc escape (\e)
623              
624             New form:
625             "chars" (note the required double-quotes)
626              
627             where each char in the list represents a character in the sequence, except
628             for the special sequences:
629              
630             \\C-x Ctrl-x
631             \\M-x Meta-x
632             \\M-C-x Meta-Ctrl-x
633             \\e escape.
634             \\x x (if not one of the above)
635              
636              
637             C<$function> should be in the form C or C.
638              
639             It is an error for the function to not be known....
640              
641             As an example, the following lines in .inputrc will bind one's xterm
642             arrow keys:
643              
644             "\e[[A": previous-history
645             "\e[[B": next-history
646             "\e[[C": forward-char
647             "\e[[D": backward-char
648              
649             =cut
650              
651             sub rl_bind_keyseq($$)
652             {
653 3811     3811 1 8110 my ($key, $func) = @_;
654 3811         9274 $func = canonic_command_function($func);
655              
656             ## print "sequence [$key] func [$func]\n"; ##DEBUG
657              
658 3811         7525 my @keys = ();
659             ## See if it's a new-style binding.
660 3811 100       11403 if ($key =~ m/"((?:\\.|[^\\])*)"/s) {
661 1044         4225 @keys = _unescape "$1";
662             } else {
663             ## old-style binding... only one key (or Meta+key)
664 2767         5519 my ($isctrl, $orig) = (0, $key);
665 2767         8128 $isctrl = $key =~ s/\b(C|Control|CTRL)-//i;
666 2767 100       8285 push(@keys, ord("\e")) if $key =~ s/\b(M|Meta)-//i; ## is meta?
667             ## Isolate key part. This matches GNU's implementation.
668             ## If the key is '-', be careful not to delete it!
669 2767         4781 $key =~ s/.*-(.)/$1/;
670 2767 50       11097 if ($key =~ /^(space|spc)$/i) { $key = ' '; }
  0 100       0  
    100          
    50          
    50          
    50          
    50          
671 56         149 elsif ($key =~ /^(rubout|del)$/i) { $key = "\x7f"; }
672 28         80 elsif ($key =~ /^tab$/i) { $key = "\t"; }
673 0         0 elsif ($key =~ /^(return|ret)$/i) { $key = "\r"; }
674 0         0 elsif ($key =~ /^(newline|lfd)$/i) { $key = "\n"; }
675 0         0 elsif ($key =~ /^(escape|esc)$/i) { $key = "\e"; }
676             elsif (length($key) > 1) {
677 0 0       0 warn "Warning$InputLocMsg: strange binding [$orig]\n" if $^W;
678             }
679 2767         4711 $key = ord($key);
680 2767 100       6302 $key = ctrl($key) if $isctrl;
681 2767         6211 push(@keys, $key);
682             }
683              
684             # Now do the mapping of the sequence represented in @keys
685 3811 50       8769 printf "rl_bind(%s, %s)\n", $func, join(', ', @keys) if $DEBUG;
686 3811         8065 &bind_parsed_keyseq($func, \@keys);
687             }
688              
689             =head3 rl_bind
690              
691             Accepts an array as pairs ($keyspec, $function, [$keyspec, $function]...).
692             and maps the associated bindings to the current KeyMap.
693              
694             =cut
695              
696             sub rl_bind
697             {
698 92   66 92 1 503 while (defined($key = shift(@_)) && defined($func = shift(@_)))
699             {
700 3811         7902 rl_bind_keyseq($key, $func);
701             }
702             }
703              
704             =head3 rl_editMode
705              
706             Changes editmode to $1 which shoujld either be 'emacs', 'vi',
707             'viopos', 'vicmd', 'visearch'
708              
709             =cut
710              
711             sub rl_editMode($)
712             {
713 0     0   0 $keymap_name = shift;
714 0 0       0 if ($keymap_name eq 'emacs') {
    0          
    0          
    0          
    0          
715 0         0 F_EmacsEditingMode();
716 0         0 @KeyMap = emacs_keymap;
717 0         0 $KeyMap{'name'} = 'emacs';
718             } elsif ($keymap_name eq 'vi') {
719 0         0 @KeyMap = vi_keymap;
720 0         0 $KeyMap{'name'} = 'vi';
721             } elsif ($keymap_name eq 'vicmd') {
722 0         0 F_ViCommandMode();
723 0         0 @KeyMap = vicmd_keymap;
724 0         0 $KeyMap{'name'} = 'vicmd';
725             } elsif ($keymap_name eq 'vipos') {
726 0         0 @KeyMap = vipos_keymap;
727 0         0 $KeyMap{'name'} = 'vipos';
728             } elsif ($keymap_name eq 'visearch') {
729 0         0 @KeyMap = visearch_keymap;
730 0         0 $KeyMap{'name'} = 'visearch';
731             }
732              
733 0   0     0 while (defined($key = shift(@_)) && defined($func = shift(@_)))
734             {
735 0         0 rl_bind_keyseq($key, $func);
736             }
737             }
738              
739             =head3 rl_set
740              
741             C
742              
743             Sets the named variable as per the given value, if both are appropriate.
744             Allows the user of the package to set such things as HorizontalScrollMode
745             and EditingMode. Value_string may be of the form
746              
747             HorizontalScrollMode
748             horizontal-scroll-mode
749              
750             Also called during the parsing of F<~/.inputrc> for "set var value" lines.
751              
752             The previous value is returned, or undef on error.
753              
754             Consider the following example for how to add additional variables
755             accessible via rl_set (and hence via F<~/.inputrc>).
756              
757             Want:
758              
759             We want an external variable called "FooTime" (or "foo-time").
760             It may have values "January", "Monday", or "Noon".
761             Internally, we'll want those values to translate to 1, 2, and 12.
762              
763             How:
764              
765             Have an internal variable $var_FooTime that will represent the current
766             internal value, and initialize it to the default value.
767             Make an array %var_FooTime whose keys and values are are the external
768             (January, Monday, Noon) and internal (1, 2, 12) values:
769              
770             $var_FooTime = $var_FooTime{'January'} = 1; #default
771             $var_FooTime{'Monday'} = 2;
772             $var_FooTime{'Noon'} = 12;
773              
774             =cut
775              
776             sub rl_set
777             {
778 0     0 1 0 local($var, $val) = @_;
779              
780             # &preinit's keys are all Capitalized
781 0 0       0 $val = ucfirst lc $val if $val =~ /^(on|off)$/i;
782              
783 0 0       0 $var = 'CompleteAddsuffix' if $var eq 'visible-stats';
784              
785             ## if the variable is in the form "some-name", change to "SomeName"
786 0         0 local($_) = "\u$var";
787 0         0 local($return) = undef;
788 0         0 s/-(.)/\u$1/g;
789              
790             # Skip unknown variables:
791 0 0       0 return unless defined $ {'Term::ReadLine::Perl5::readline::'}{"var_$_"};
  0         0  
792 0         0 local(*V); # avoid warning
793 0         0 { local $^W; *V = $ {'Term::ReadLine::Perl5::readline::'}{"var_$_"}; }
  0         0  
  0         0  
  0         0  
794 0 0       0 if (!defined($V)) { # XXX Duplicate check?
    0          
795 0 0       0 warn("Warning$InputLocMsg:\n".
796             " Invalid variable `$var'\n") if $^W;
797             } elsif (!defined($V{$val})) {
798 0         0 local(@selections) = keys(%V);
799 0 0       0 warn("Warning$InputLocMsg:\n".
800             " Invalid value `$val' for variable `$var'.\n".
801             " Choose from [@selections].\n") if $^W;
802             } else {
803 0         0 $return = $V;
804 0         0 $V = $V{$val}; ## make the setting
805             }
806 0         0 $return;
807             }
808              
809             =head3 rl_filename_list
810              
811             rl_filename_list($pattern) => list of files
812              
813             Returns a list of completions that begin with the string I<$pattern>.
814             Can be used to pass to I.
815              
816             This function corresponds to the L function
817             I. But that doesn't handle tilde expansion while
818             this does. Also, directories returned will have the '/' suffix
819             appended as is the case returned by GNU Readline, but not
820             I. Adding the '/' suffix is useful in completion
821             because it forces the next completion to complete inside that
822             directory.
823              
824             GNU Readline also will complete partial I<~> names; for example
825             I<~roo> maybe expanded to C for the root user. When
826             getpwent/setpwent is available we provide that.
827              
828             The user of this package can set I<$rl_completion_function> to
829             'rl_filename_list' to restore the default of filename matching if
830             they'd changed it earlier, either directly or via &rl_basic_commands.
831              
832             =cut
833              
834             sub rl_filename_list
835             {
836 4     4 1 9959 my $pattern = $_[0];
837 4 100       57 if ($pattern =~ m{^~[^/]*$}) {
838 2 100 66     28 if ($have_getpwent and length($pattern) > 1) {
839 1 50       14 map { -d $_ ? $_ . '/' : $_ }
  1         29  
840             tilde_complete(substr($pattern, 1));
841             } else {
842 1 50       38 map { -d $_ ? $_ . '/' : $_ } bsd_glob($pattern);
  1         21  
843             }
844             } else {
845 2 100       240 map { -d $_ ? $_ . '/' : $_ } bsd_glob($pattern . '*');
  2         60  
846             }
847             }
848              
849             =head3 rl_filename_list_deprecated
850              
851             C
852              
853             This was the I function before version 1.30,
854             and the current I function.
855              
856             For reasons that are a mystery to me (rocky), there seemed to be a the
857             need to classify the result adding a suffix for executable (*),
858             pipe/socket (=), and symbolic link (@), and directory (/). Of these,
859             the only useful one is directory since that will cause a further
860             completion to continue.
861              
862             =cut
863              
864             sub rl_filename_list_deprecated
865             {
866 0     0 1 0 my $pattern = $_[0];
867 0         0 my @files = (<$pattern*>);
868 0 0       0 if ($var_CompleteAddsuffix) {
869 0         0 foreach (@files) {
870 0 0 0     0 if (-l $_) {
    0          
    0          
    0          
871 0         0 $_ .= '@';
872             } elsif (-d _) {
873 0         0 $_ .= '/';
874             } elsif (-x _) {
875 0         0 $_ .= '*';
876             } elsif (-S _ || -p _) {
877 0         0 $_ .= '=';
878             }
879             }
880             }
881 0         0 return @files;
882             }
883              
884             # Handle one line of an input file. Note we also assume
885             # local-bound arrays I<@action> and I<@level>.
886             sub parse_and_bind($$$)
887             {
888 11     11 0 33 $_ = shift;
889 11         24 my $file = shift;
890 11         25 my $include_depth = shift;
891 11         38 s/^\s+//;
892 11 100       61 return if m/^\s*(#|$)/;
893 8         43 $InputLocMsg = " [$file line $.]";
894 8 50       115 if (/^\$if\s+(.*)/) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
895 0         0 my($test) = $1;
896 0         0 push(@level, 'if');
897 0 0       0 if ($action[$#action] ne 'exec') {
898             ## We're supposed to be skipping or ignoring this level,
899             ## so for subsequent levels we really ignore completely.
900 0         0 push(@action, 'ignore');
901             } else {
902             ## We're executing this IF... do the test.
903             ## The test is either "term=xxxx", or just a string that
904             ## we compare to $rl_readline_name;
905 0 0       0 if ($test =~ /term=([a-z0-9]+)/) {
906 0   0     0 $test = ($ENV{'TERM'} && $1 eq $ENV{'TERM'});
907             } else {
908 0         0 $test = $test =~ /^(perl|$rl_readline_name)\s*$/i;
909             }
910 0 0       0 push(@action, $test ? 'exec' : 'skip');
911             }
912 0         0 return;
913             } elsif (/^\$endif\b/) {
914 0 0       0 die qq/\rWarning$InputLocMsg: unmatched endif\n/ if @level == 0;
915 0         0 pop(@level);
916 0         0 pop(@action);
917 0         0 return;
918             } elsif (/^\$else\b/) {
919 0 0 0     0 die qq/\rWarning$InputLocMsg: unmatched else\n/ if
920             @level == 0 || $level[$#level] ne 'if';
921 0         0 $level[$#level] = 'else'; ## an IF turns into an ELSE
922 0 0       0 if ($action[$#action] eq 'skip') {
923 0         0 $action[$#action] = 'exec'; ## if were SKIPing, now EXEC
924             } else {
925 0         0 $action[$#action] = 'ignore'; ## otherwise, just IGNORE.
926             }
927 0         0 return;
928             } elsif (/^\$include\s+(\S+)/) {
929 0 0       0 if ($include_depth > $max_include_depth) {
930 0         0 warn "Deep recursion in \$include directives in $file.\n";
931             } else {
932 0         0 read_an_init_file($1, $include_depth + 1);
933             }
934             } elsif ($action[$#action] ne 'exec') {
935             ## skipping this one....
936             # Readline permits trailing comments in inputrc
937             # For example, /etc/inputrc on Mandrake Linux boxes has trailing
938             # comments
939             } elsif (m/\s*set\s+(\S+)\s+(\S*)/) { # Allow trailing comment
940 0         0 &rl_set($1, $2, $file);
941             } elsif (m/^\s*(\S+):\s+("(?:\\.|[^\\\"])*"|'(\\.|[^\\\'])*')/) { # Allow trailing comment
942 0         0 &rl_bind($1, $2);
943             } elsif (m/^\s*(\S+|"[^\"]+"):\s+(\S+)/) { # Allow trailing comment
944 8         32 &rl_bind($1, $2);
945             } else {
946 0         0 chomp;
947 0 0       0 warn "\rWarning$InputLocMsg: Bad line [$_]\n" if $^W;
948             }
949             }
950              
951             =head3 rl_parse_and_bind
952              
953             B(I<$line>)
954              
955             Parse I<$line> as if it had been read from the inputrc file and
956             perform any key bindings and variable assignments found.
957              
958             =cut
959              
960             sub rl_parse_and_bind($)
961             {
962 0     0 1 0 my $line = shift;
963 0         0 parse_and_bind($line, '*bogus*', 0);
964             }
965              
966             =head3 rl_basic_commands
967              
968             Called with a list of possible commands, will allow command completion
969             on those commands, but only for the first word on a line. For
970             example:
971              
972             &rl_basic_commands('set', 'quit', 'type', 'run');
973              
974             This is for people that want quick and simple command completion.
975             A more thoughtful implementation would set I<$rl_completion_function>
976             to a routine that would look at the context of the word being completed
977             and return the appropriate possibilities.
978              
979             =cut
980              
981             sub rl_basic_commands
982             {
983 0     0 1 0 @rl_basic_commands = @_;
984 0         0 $rl_completion_function = 'use_basic_commands';
985             }
986              
987             sub rl_getc() {
988 0 0 0 0 0 0 $Term::ReadLine::Perl5::term->Tk_loop
989             if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
990 0         0 return Term::ReadKey::ReadKey(0, $term_IN);
991             }
992              
993             =head3 rl_read_init_file
994              
995             B(I<$filename>)
996             Read keybindings and variable assignments from filename I<$filename>.
997              
998             =cut
999              
1000             sub rl_read_init_file($) {
1001 15     15 1 342 read_an_init_file(shift, 0);
1002             }
1003              
1004              
1005             ###########################################################################
1006             ## Bindable functions... pretty much in the same order as in readline.c ###
1007             ###########################################################################
1008             =head1 BINDABLE FUNCTIONS
1009              
1010             There are pretty much in the same order as in readline.c
1011              
1012             =head2 Commands For Moving
1013              
1014             =head3 F_BeginningOfLine
1015              
1016             Move to the start of the current line.
1017              
1018             =cut
1019              
1020             sub F_BeginningOfLine
1021             {
1022 0     0 1 0 $D = 0;
1023             }
1024              
1025             =head3 F_EndOfLine
1026              
1027             Move to the end of the line.
1028              
1029             =cut
1030              
1031             sub F_EndOfLine
1032             {
1033 0     0 1 0 &F_ForwardChar(100) while !&at_end_of_line;
1034             }
1035              
1036              
1037             =head3 F_ForwardChar
1038              
1039             Move forward (right) $count characters.
1040              
1041             =cut
1042              
1043             sub F_ForwardChar
1044             {
1045 85     85 1 161 my $count = shift;
1046 85 100       175 return &F_BackwardChar(-$count) if $count < 0;
1047              
1048 84   100     164 while (!&at_end_of_line && $count-- > 0) {
1049 104         212 $D += &CharSize($D);
1050             }
1051             }
1052              
1053             =head3 F_BackwardChar
1054              
1055             Move backward (left) $count characters.
1056              
1057             =cut
1058              
1059             sub F_BackwardChar
1060             {
1061 36     36 1 105 my $count = shift;
1062 36 100       101 return &F_ForwardChar(-$count) if $count < 0;
1063              
1064 35   100     162 while (($D > 0) && ($count-- > 0)) {
1065 36         76 $D--; ## Move back one regardless,
1066 36 100       90 $D-- if &OnSecondByte($D); ## another if over a big char.
1067             }
1068             }
1069              
1070             =head3 F_ForwardWord
1071              
1072             Move forward to the end of the next word. Words are composed of
1073             letters and digits.
1074              
1075             Done as many times as $count says.
1076              
1077             =cut
1078              
1079             sub F_ForwardWord
1080             {
1081 11     11 1 25 my $count = shift;
1082 11 100       38 return &F_BackwardWord(-$count) if $count < 0;
1083              
1084 10   66     27 while (!&at_end_of_line && $count-- > 0)
1085             {
1086             ## skip forward to the next word (if not already on one)
1087 15   66     39 &F_ForwardChar(1) while !&at_end_of_line && &WordBreak($D);
1088             ## skip forward to end of word
1089 15   66     40 &F_ForwardChar(1) while !&at_end_of_line && !&WordBreak($D);
1090             }
1091             }
1092              
1093             =head3 F_BackwardWord
1094              
1095             Move back to the start of the current or previous word. Words are
1096             composed of letters and digits.
1097              
1098             Done as many times as $count says.
1099              
1100             =cut
1101              
1102             sub F_BackwardWord
1103             {
1104 4     4 1 14 my $count = shift;
1105 4 100       20 return &F_ForwardWord(-$count) if $count < 0;
1106              
1107 3   100     29 while ($D > 0 && $count-- > 0) {
1108             ## skip backward to the next word (if not already on one)
1109 6   66     29 &F_BackwardChar(1) while (($D > 0) && &WordBreak($D-1));
1110             ## skip backward to start of word
1111 6   100     30 &F_BackwardChar(1) while (($D > 0) && !&WordBreak($D-1));
1112             }
1113             }
1114              
1115             =head3 F_ClearScreen
1116              
1117             Clear the screen and redraw the current line, leaving the current line
1118             at the top of the screen.
1119              
1120             If given a numeric arg other than 1, simply refreshes the line.
1121              
1122             =cut
1123              
1124             sub F_ClearScreen
1125             {
1126 0     0 1 0 my $count = shift;
1127 0 0       0 return &F_RedrawCurrentLine if $count != 1;
1128              
1129 0 0       0 $rl_CLEAR = `clear` if !defined($rl_CLEAR);
1130 0         0 local $\ = '';
1131 0         0 print $term_OUT $rl_CLEAR;
1132 0         0 $force_redraw = 1;
1133             }
1134              
1135             =head3 F_RedrawCurrentLine
1136              
1137             Refresh the current line. By default, this is unbound.
1138              
1139             =cut
1140              
1141             sub F_RedrawCurrentLine
1142             {
1143 0     0 1 0 $force_redraw = 1;
1144             }
1145              
1146             ###########################################################################
1147             =head2 Commands tor Manipulating the History
1148              
1149             =head3 F_AcceptLine
1150              
1151             Accept the line regardless of where the cursor is. If this line is
1152             non-empty, it may be added to the history list for future recall with
1153             add_history(). If this line is a modified history line, the history
1154             line is restored to its original state.
1155              
1156             =cut
1157              
1158             sub F_AcceptLine
1159             {
1160 0     0 1 0 &add_line_to_history($line, $minlength);
1161 0         0 $AcceptLine = $line;
1162 0         0 local $\ = '';
1163 0         0 print $term_OUT "\r\n";
1164 0         0 $force_redraw = 0;
1165 0         0 (pos $line) = undef; # Another way to force redraw...
1166             }
1167              
1168             =head3 F_PreviousHistory
1169              
1170             Move `back' through the history list, fetching the previous command.
1171              
1172             =cut
1173              
1174             sub F_PreviousHistory {
1175 0     0 1 0 &get_line_from_history($rl_HistoryIndex - shift);
1176             }
1177              
1178             =head3 F_PreviousHistory
1179              
1180             Move `forward' through the history list, fetching the next command.
1181              
1182             =cut
1183              
1184             sub F_NextHistory {
1185 0     0 0 0 &get_line_from_history($rl_HistoryIndex + shift);
1186             }
1187              
1188             =head3 F_BeginningOfHistory
1189              
1190             Move to the first line in the history.
1191              
1192             =cut
1193              
1194             sub F_BeginningOfHistory
1195             {
1196 0     0 1 0 &get_line_from_history(0);
1197             }
1198              
1199             =head3 F_EndOfHistory
1200              
1201             Move to the end of the input history, i.e., the line currently being
1202             entered.
1203              
1204             =cut
1205              
1206 0     0 1 0 sub F_EndOfHistory { &get_line_from_history(@rl_History); }
1207              
1208             =head3 F_ReverseSearchHistory
1209              
1210             Search backward starting at the current line and moving `up' through
1211             the history as necessary. This is an incremental search.
1212              
1213             =cut
1214              
1215             sub F_ReverseSearchHistory
1216             {
1217 0 0   0 1 0 &DoSearch($_[0] >= 0 ? 1 : 0);
1218             }
1219              
1220             =head3 F_ForwardSearchHistory
1221              
1222             Search forward starting at the current line and moving `down' through
1223             the the history as necessary. This is an increment
1224              
1225             =cut
1226              
1227             sub F_ForwardSearchHistory
1228             {
1229 0 0   0 1 0 &DoSearch($_[0] >= 0 ? 0 : 1);
1230             }
1231              
1232             =head3 F_HistorySearchBackward
1233              
1234             Search backward through the history for the string of characters
1235             between the start of the current line and the point. The search string
1236             must match at the beginning of a history line. This is a
1237             non-incremental search. By default, this command is unbound.
1238              
1239             =cut
1240              
1241             sub F_HistorySearchBackward
1242             {
1243 0 0   0 1 0 &DoSearchStart(($_[0] >= 0 ? 1 : 0),substr($line,0,$D));
1244             }
1245              
1246             =head3 F_HistorySearchForward
1247              
1248             Search forward through the history for the string of characters
1249             between the start of the current line and the point. The search string
1250             may match anywhere in a history line. This is a non-incremental
1251             search. By default, this command is unbound.
1252              
1253             =cut
1254              
1255             sub F_HistorySearchForward
1256             {
1257 0 0   0 1 0 &DoSearchStart(($_[0] >= 0 ? 0 : 1),substr($line,0,$D));
1258             }
1259              
1260             sub F_PrintHistory {
1261 0     0 0 0 my($count) = @_;
1262              
1263 0 0       0 $count = 20 if $count == 1; # Default - assume 'H', not '1H'
1264 0         0 my $end = $rl_HistoryIndex + $count/2;
1265 0 0       0 $end = @rl_History if $end > @rl_History;
1266 0         0 my $start = $end - $count + 1;
1267 0 0       0 $start = 0 if $start < 0;
1268              
1269 0         0 my $lmh = length $rl_MaxHistorySize;
1270              
1271 0         0 my $lspace = ' ' x ($lmh+3);
1272 0         0 my $hdr = "$lspace-----";
1273 0 0       0 $hdr .= " (Use ESC UP to retrieve command ) -----" unless $Vi_mode;
1274 0 0       0 $hdr .= " (Use 'G' to retrieve command ) -----" if $Vi_mode;
1275              
1276 0         0 local ($\, $,) = ('','');
1277 0         0 print "\n$hdr\n";
1278 0 0       0 print $lspace, ". . .\n" if $start > 0;
1279 0         0 my $i;
1280 0         0 my $shift = ($Vi_mode != 0);
1281 0         0 for $i ($start .. $end) {
1282 0 0       0 print + ($i == $rl_HistoryIndex) ? '>' : ' ',
    0          
    0          
1283              
1284             sprintf("%${lmh}d: ", @rl_History - $i + $shift),
1285              
1286             ($i < @rl_History) ? $rl_History[$i] :
1287             ($i == $rl_HistoryIndex) ? $line :
1288             $line_for_revert,
1289              
1290             "\n";
1291             }
1292 0 0       0 print $lspace, ". . .\n" if $end < @rl_History;
1293 0         0 print "$hdr\n";
1294              
1295 0         0 rl_forced_update_display();
1296              
1297 0 0 0     0 &F_ViInput() if $line eq '' && $Vi_mode;
1298             }
1299              
1300             ###########################################################################
1301             =head2 Commands For Changing Text
1302              
1303             =head3 F_DeleteChar
1304              
1305             Removes the $count chars from under the cursor.
1306             If there is no line and the last command was different, tells
1307             readline to return EOF.
1308             If there is a line, and the cursor is at the end of it, and we're in
1309             tcsh completion mode, then list possible completions.
1310             If $count > 1, deleted chars saved to kill buffer.
1311              
1312             =cut
1313              
1314             sub F_DeleteChar
1315             {
1316 0 0   0 1 0 return if remove_selection();
1317              
1318 0         0 my $count = shift;
1319 0 0       0 return F_DeleteBackwardChar(-$count) if $count < 0;
1320 0 0       0 if (length($line) == 0) { # EOF sent (probably OK in DOS too)
1321 0 0       0 $AcceptLine = $ReturnEOF = 1 if $lastcommand ne 'F_DeleteChar';
1322 0         0 return;
1323             }
1324 0 0       0 if ($D == length ($line))
1325             {
1326 0 0       0 &complete_internal('?') if $var_TcshCompleteMode;
1327 0         0 return;
1328             }
1329 0         0 my $oldD = $D;
1330 0         0 &F_ForwardChar($count);
1331 0 0       0 return if $D == $oldD;
1332 0         0 &kill_text($oldD, $D, $count > 1);
1333             }
1334              
1335             =head3 F_BackwardDeleteChar
1336              
1337             Removes $count chars to left of cursor (if not at beginning of line).
1338             If $count > 1, deleted chars saved to kill buffer.
1339              
1340             =cut
1341              
1342             sub F_BackwardDeleteChar
1343             {
1344 0 0   0 1 0 return if remove_selection();
1345              
1346 0         0 my $count = shift;
1347 0 0       0 return F_DeleteChar(-$count) if $count < 0;
1348 0         0 my $oldD = $D;
1349 0         0 &F_BackwardChar($count);
1350 0 0       0 return if $D == $oldD;
1351 0         0 &kill_text($oldD, $D, $count > 1);
1352             }
1353              
1354             =head3 F_QuotedInsert
1355              
1356             Add the next character typed to the line verbatim. This is how to
1357             insert key sequences like C-q, for example.
1358              
1359             =cut
1360              
1361             sub F_QuotedInsert
1362             {
1363 0     0 1 0 my $count = shift;
1364 0         0 &F_SelfInsert($count, ord(&getc_with_pending));
1365             }
1366              
1367             =head3 F_TabInsert
1368              
1369             Insert a tab character.
1370              
1371             =cut
1372              
1373             sub F_TabInsert
1374             {
1375 0     0 1 0 my $count = shift;
1376 0         0 &F_SelfInsert($count, ord("\t"));
1377             }
1378              
1379             =head3 F_SelfInsert
1380              
1381             B(I<$count>, I<$ord>)
1382              
1383             I<$ord> is an ASCII ordinal; inserts I<$count> of them into global
1384             I<$line>.
1385              
1386             Insert yourself.
1387              
1388             =cut
1389              
1390             sub F_SelfInsert
1391             {
1392 0     0 1 0 remove_selection();
1393 0         0 my ($count, $ord) = @_;
1394 0         0 my $text2add = pack('C', $ord) x $count;
1395 0 0       0 if ($InsertMode) {
1396 0         0 substr($line,$D,0) .= $text2add;
1397             } else {
1398             ## note: this can screw up with 2-byte characters.
1399 0         0 substr($line,$D,length($text2add)) = $text2add;
1400             }
1401 0         0 $D += length($text2add);
1402             }
1403              
1404             =head3 F_TransposeChars
1405              
1406             Switch char at dot with char before it.
1407             If at the end of the line, switch the previous two...
1408             I: this could screw up multibyte characters.. should do correctly)
1409              
1410             =cut
1411              
1412             sub F_TransposeChars
1413             {
1414 0 0 0 0 1 0 if ($D == length($line) && $D >= 2) {
    0          
1415 0         0 substr($line,$D-2,2) = substr($line,$D-1,1).substr($line,$D-2,1);
1416             } elsif ($D >= 1) {
1417 0         0 substr($line,$D-1,2) = substr($line,$D,1) .substr($line,$D-1,1);
1418             } else {
1419 0         0 F_Ding();
1420             }
1421             }
1422              
1423             =head3 F_TransposeWords
1424              
1425             Drag the word before point past the word after point, moving point
1426             past that word as well. If the insertion point is at the end of the
1427             line, this transposes the last two words on the line.
1428              
1429             =cut
1430              
1431             sub F_TransposeWords {
1432 0     0 1 0 my $c = shift;
1433 0 0       0 return F_Ding() unless $c;
1434             # Find "this" word
1435 0         0 F_BackwardWord(1);
1436 0         0 my $p0 = $D;
1437 0         0 F_ForwardWord(1);
1438 0         0 my $p1 = $D;
1439 0 0       0 return F_Ding() if $p1 == $p0;
1440 0         0 my ($p2, $p3) = ($p0, $p1);
1441 0 0       0 if ($c > 0) {
1442 0         0 F_ForwardWord($c);
1443 0         0 $p3 = $D;
1444 0         0 F_BackwardWord(1);
1445 0         0 $p2 = $D;
1446             } else {
1447 0         0 F_BackwardWord(1 - $c);
1448 0         0 $p0 = $D;
1449 0         0 F_ForwardWord(1);
1450 0         0 $p1 = $D;
1451             }
1452 0 0 0     0 return F_Ding() if $p3 == $p2 or $p2 < $p1;
1453 0         0 my $r = substr $line, $p2, $p3 - $p2;
1454 0         0 substr($line, $p2, $p3 - $p2) = substr $line, $p0, $p1 - $p0;
1455 0         0 substr($line, $p0, $p1 - $p0) = $r;
1456 0 0       0 $D = $c > 0 ? $p3 : $p0 + $p3 - $p2; # End of "this" word after edit
1457 0         0 return 1;
1458             }
1459              
1460             =head3 F_UpcaseWord
1461              
1462             Uppercase the current (or following) word. With a negative argument,
1463             uppercase the previous word, but do not move the cursor.
1464              
1465             =cut
1466              
1467 2     2 1 1257 sub F_UpcaseWord { &changecase($_[0], 'up'); }
1468              
1469             =head3 F_DownCaseWord
1470              
1471             Lowercase the current (or following) word. With a negative argument,
1472             lowercase the previous word, but do not move the cursor.
1473              
1474             =cut
1475              
1476 2     2 1 1199 sub F_DownCaseWord { &changecase($_[0], 'down'); }
1477              
1478             =head3 F_CapitalizeWord
1479              
1480             Capitalize the current (or following) word. With a negative argument,
1481             capitalize the previous word, but do not move the cursor.
1482              
1483             =cut
1484              
1485 2     2 1 1230 sub F_CapitalizeWord { &changecase($_[0], 'cap'); }
1486              
1487             =head3 F_OverwriteMode
1488              
1489             Toggle overwrite mode. With an explicit positive numeric argument,
1490             switches to overwrite mode. With an explicit non-positive numeric
1491             argument, switches to insert mode. This command affects only emacs
1492             mode; vi mode does overwrite differently. Each call to readline()
1493             starts in insert mode. In overwrite mode, characters bound to
1494             self-insert replace the text at point rather than pushing the text to
1495             the right. Characters bound to backward-delete-char replace the
1496             character before point with a space.
1497              
1498             By default, this command is unbound.
1499              
1500             =cut
1501              
1502             sub F_OverwriteMode
1503             {
1504 0     0 1 0 $InsertMode = 0;
1505             }
1506              
1507             ###########################################################################
1508             =head2 Killing and Yanking
1509              
1510             =head3 F_KillLine
1511              
1512             delete characters from cursor to end of line.
1513              
1514             =cut
1515              
1516             sub F_KillLine
1517             {
1518 0     0 1 0 my $count = shift;
1519 0 0       0 return F_BackwardKillLine(-$count) if $count < 0;
1520 0         0 kill_text($D, length($line), 1);
1521             }
1522              
1523             =head3 F_BackwardKillLine
1524              
1525             Delete characters from cursor to beginning of line.
1526              
1527             =cut
1528              
1529             sub F_BackwardKillLine
1530             {
1531 0     0 1 0 my $count = shift;
1532 0 0       0 return F_KillLine(-$count) if $count < 0;
1533 0 0       0 return F_Ding if $D == 0;
1534 0         0 kill_text(0, $D, 1);
1535             }
1536              
1537             =head3 F_UnixLineDiscard
1538              
1539             Kill line from cursor to beginning of line.
1540              
1541             =cut
1542              
1543             sub F_UnixLineDiscard
1544             {
1545 0 0   0 1 0 return F_Ding() if $D == 0;
1546 0         0 kill_text(0, $D, 1);
1547             }
1548              
1549             =head3 F_KillWord
1550              
1551             Delete characters to the end of the current word. If not on a word, delete to
1552             ## the end of the next word.
1553              
1554             =cut
1555              
1556             sub F_KillWord
1557             {
1558 0     0 1 0 my $count = shift;
1559 0 0       0 return &F_BackwardKillWord(-$count) if $count < 0;
1560 0         0 my $oldD = $D;
1561 0         0 &F_ForwardWord($count); ## moves forward $count words.
1562 0         0 kill_text($oldD, $D, 1);
1563             }
1564              
1565             =head3 F_BackwardKillWord
1566              
1567             Delete characters backward to the start of the current word, or, if
1568             currently not on a word (or just at the start of a word), to the start
1569             of the previous word.
1570              
1571             =cut
1572              
1573             sub F_BackwardKillWord
1574             {
1575 0     0 1 0 my $count = shift;
1576 0 0       0 return F_KillWord(-$count) if $count < 0;
1577 0         0 my $oldD = $D;
1578 0         0 &F_BackwardWord($count); ## moves backward $count words.
1579 0         0 kill_text($D, $oldD, 1);
1580             }
1581              
1582             =head3 F_UnixWordRubout
1583              
1584             Kill to previous whitespace.
1585              
1586             =cut
1587              
1588             sub F_UnixWordRubout
1589             {
1590 0 0   0 1 0 return F_Ding() if $D == 0;
1591 0         0 (my $oldD, local $rl_basic_word_break_characters) = ($D, "\t ");
1592             # JP: Fixed a bug here - both were 'my'
1593 0         0 F_BackwardWord(1);
1594 0         0 kill_text($D, $oldD, 1);
1595             }
1596              
1597             =head3 F_KillRegion
1598              
1599             Kill the text in the current region. By default, this command is
1600             unbound.
1601              
1602             =cut
1603              
1604             sub F_KillRegion {
1605 0 0   0 1 0 return F_Ding() unless $line_rl_mark == $rl_HistoryIndex;
1606 0 0       0 $rl_mark = length $line if $rl_mark > length $line;
1607 0         0 kill_text($rl_mark, $D, 1);
1608 0         0 $line_rl_mark = -1; # Disable mark
1609             }
1610              
1611             =head3 F_CopyRegionAsKill
1612              
1613             Copy the text in the region to the kill buffer, so it can be yanked right away. By default, this command is unbound.
1614              
1615             =cut
1616              
1617             sub F_CopyRegionAsKill {
1618 0 0   0 1 0 return F_Ding() unless $line_rl_mark == $rl_HistoryIndex;
1619 0 0       0 $rl_mark = length $line if $rl_mark > length $line;
1620 0         0 my ($s, $e) = ($rl_mark, $D);
1621 0 0       0 ($s, $e) = ($e, $s) if $s > $e;
1622 0         0 $ThisCommandKilledText = 1 + $s;
1623 0 0       0 $KillBuffer = '' if !$LastCommandKilledText;
1624 0         0 $KillBuffer .= substr($line, $s, $e - $s);
1625             }
1626              
1627             =head3 F_Yank
1628              
1629             Yank the top of the kill ring into the buffer at point.
1630              
1631             =cut
1632              
1633             sub F_Yank
1634             {
1635 0     0 1 0 remove_selection();
1636 0         0 &TextInsert($_[0], $KillBuffer);
1637             }
1638              
1639             sub F_YankPop {
1640 0     0 0 0 1;
1641             ## not implemented yet
1642             }
1643              
1644             sub F_YankNthArg {
1645 0     0 0 0 1;
1646             ## not implemented yet
1647             }
1648              
1649             ###########################################################################
1650             =head2 Specifying Numeric Arguments
1651              
1652             =head3 F_DigitArgument
1653              
1654             Add this digit to the argument already accumulating, or start a new
1655             argument. C starts a negative argument.
1656              
1657             =cut
1658              
1659             sub F_DigitArgument
1660             {
1661 0     0 1 0 my $in = chr $_[1];
1662 0         0 my ($NumericArg, $sawDigit) = (1, 0);
1663 0         0 my ($increment, $ord);
1664 0 0       0 ($NumericArg, $sawDigit) = ($_[0], $_[0] !~ /e0$/i)
1665             if $doingNumArg; # XXX What if Esc-- 1 ?
1666              
1667             do
1668 0         0 {
1669 0         0 $ord = ord $in;
1670 0 0 0     0 if (defined($KeyMap[$ord]) && $KeyMap[$ord] eq 'F_UniversalArgument') {
    0 0        
    0 0        
1671 0         0 $NumericArg *= 4;
1672             } elsif ($ord == ord('-') && !$sawDigit) {
1673 0         0 $NumericArg = -$NumericArg;
1674             } elsif ($ord >= ord('0') && $ord <= ord('9')) {
1675 0 0       0 $increment = ($ord - ord('0')) * ($NumericArg < 0 ? -1 : 1);
1676 0 0       0 if ($sawDigit) {
1677 0         0 $NumericArg = $NumericArg * 10 + $increment;
1678             } else {
1679 0         0 $NumericArg = $increment;
1680 0         0 $sawDigit = 1;
1681             }
1682             } else {
1683 0         0 local(*KeyMap) = $var_EditingMode;
1684 0         0 rl_redisplay();
1685 0         0 $doingNumArg = 1; # Allow NumArg inside NumArg
1686 0 0       0 &do_command(*KeyMap, $NumericArg . ($sawDigit ? '': 'e0'), $ord);
1687 0         0 return;
1688             }
1689             ## make sure it's not toooo big.
1690 0 0       0 if ($NumericArg > $rl_max_numeric_arg) {
    0          
1691 0         0 $NumericArg = $rl_max_numeric_arg;
1692             } elsif ($NumericArg < -$rl_max_numeric_arg) {
1693 0         0 $NumericArg = -$rl_max_numeric_arg;
1694             }
1695 0         0 redisplay(sprintf("(arg %d) ", $NumericArg));
1696             } while defined($in = &getc_with_pending);
1697             }
1698              
1699             =head3 F_UniversalArgument
1700              
1701             This is another way to specify an argument. If this command is
1702             followed by one or more digits, optionally with a leading minus sign,
1703             those digits define the argument. If the command is followed by
1704             digits, executing universal-argument again ends the numeric argument,
1705             but is otherwise ignored. As a special case, if this command is
1706             immediately followed by a character that is neither a digit or minus
1707             sign, the argument count for the next command is multiplied by
1708             four. The argument count is initially one, so executing this function
1709             the first time makes the argument count four, a second time makes the
1710             argument count sixteen, and so on. By default, this is not bound to a
1711             key.
1712              
1713             =cut
1714              
1715             sub F_UniversalArgument
1716             {
1717 0     0 1 0 &F_DigitArgument;
1718             }
1719              
1720             ###########################################################################
1721             =head2 Letting Readline Type For You
1722              
1723             =head3 F_Complete
1724              
1725             Do a completion operation. If the last thing we did was a completion
1726             operation, we'll now list the options available (under normal emacs
1727             mode).
1728              
1729             In I, each contiguous subsequent completion
1730             operation lists another of the possible options.
1731              
1732             Returns true if a completion was done, false otherwise, so vi
1733             completion routines can test it.
1734              
1735             =cut
1736              
1737             sub F_Complete
1738             {
1739 0 0   0 1 0 if ($lastcommand eq 'F_Complete') {
1740 0 0 0     0 if ($var_TcshCompleteMode && @tcsh_complete_selections > 0) {
1741 0         0 substr($line, $tcsh_complete_start, $tcsh_complete_len)
1742             = $tcsh_complete_selections[0];
1743 0         0 $D -= $tcsh_complete_len;
1744 0         0 $tcsh_complete_len = length($tcsh_complete_selections[0]);
1745 0         0 $D += $tcsh_complete_len;
1746 0         0 push(@tcsh_complete_selections, shift(@tcsh_complete_selections));
1747             } else {
1748 0 0       0 &complete_internal('?') or return;
1749             }
1750             } else {
1751 0         0 @tcsh_complete_selections = ();
1752 0 0       0 &complete_internal("\t") or return;
1753             }
1754              
1755 0         0 1;
1756             }
1757              
1758             =head3 F_PossibleCompletions
1759              
1760             List possible completions
1761              
1762             =cut
1763              
1764             sub F_PossibleCompletions
1765             {
1766 0     0 1 0 &complete_internal('?');
1767             }
1768              
1769             =head3 F_PossibleCompletions
1770              
1771             Insert all completions of the text before point that would have been
1772             generated by possible-completions.
1773              
1774             =cut
1775              
1776             sub F_InsertCompletions
1777             {
1778 0     0 0 0 &complete_internal('*');
1779             }
1780              
1781             ###########################################################################
1782             =head2 Miscellaneous Commands
1783              
1784             =head3 F_ReReadInitFile
1785              
1786             Read in the contents of the inputrc file, and incorporate any bindings
1787             or variable assignments found there.
1788              
1789             =cut
1790              
1791             sub F_ReReadInitFile
1792             {
1793 14     14 1 62 my ($file) = $ENV{'TRP5_INPUTRC'};
1794 14 50       96 $file = $ENV{'INPUTRC'} unless defined $file;
1795 14 100       71 unless (defined $file) {
1796 5 50       40 return unless defined $HOME;
1797 5         153 $file = File::Spec->catfile($HOME, '.inputrc');
1798             }
1799 14         101 rl_read_init_file($file);
1800             }
1801              
1802             =head3 F_Abort
1803              
1804             Abort the current editing command and ring the terminal's bell
1805             (subject to the setting of bell-style).
1806              
1807             =cut
1808              
1809             sub F_Abort
1810             {
1811 0     0 1 0 F_Ding();
1812             }
1813              
1814              
1815             =head3 F_Undo
1816              
1817             Incremental undo, separately remembered for each line.
1818              
1819             =cut
1820              
1821             sub F_Undo
1822             {
1823 0     0 1 0 pop(@undo); # unless $undo[-1]->[5]; ## get rid of the state we just put on, so we can go back one.
1824 0 0       0 if (@undo) {
1825 0         0 &getstate(pop(@undo));
1826             } else {
1827 0         0 F_Ding();
1828             }
1829             }
1830              
1831             =head3 F_RevertLine
1832              
1833             Undo all changes made to this line. This is like executing the undo
1834             command enough times to get back to the beginning.
1835              
1836             =cut
1837              
1838             sub F_RevertLine
1839             {
1840 0 0   0 1 0 if ($rl_HistoryIndex >= $#rl_History+1) {
1841 0         0 $line = $line_for_revert;
1842             } else {
1843 0         0 $line = $rl_History[$rl_HistoryIndex];
1844             }
1845 0         0 $D = length($line);
1846             }
1847              
1848             =head3 F_TildeExpand
1849              
1850             Perform tilde expansion on the current word.
1851              
1852             =cut
1853              
1854             sub F_TildeExpand {
1855              
1856 0     0 1 0 my $what_to_do = shift;
1857 0         0 my ($point, $end) = ($D, $D);
1858              
1859             # In vi mode, complete if the cursor is at the *end* of a word, not
1860             # after it.
1861 0 0       0 ($point++, $end++) if $Vi_mode;
1862              
1863             # Get text to work complete on.
1864 0 0       0 if ($point) {
1865             ## Not at the beginning of the line; Isolate the word to be
1866             ## completed.
1867 0   0     0 1 while (--$point && (-1 == index($rl_completer_word_break_characters,
1868             substr($line, $point, 1))));
1869              
1870             # Either at beginning of line or at a word break.
1871             # If at a word break (that we don't want to save), skip it.
1872 0 0 0     0 $point++ if (
1873             (index($rl_completer_word_break_characters,
1874             substr($line, $point, 1)) != -1) &&
1875             (index($rl_special_prefixes, substr($line, $point, 1)) == -1)
1876             );
1877             }
1878              
1879 0         0 my $text = substr($line, $point, $end - $point);
1880              
1881             # If the first character of the current word is a tilde, perform
1882             # tilde expansion and insert the result. If not a tilde, do
1883             # nothing.
1884 0 0       0 return if substr($text, 0, 1) ne '~';
1885              
1886 0         0 my @matches = tilde_complete($text);
1887 0 0       0 if (@matches == 0) {
1888 0         0 return F_Ding();
1889             }
1890 0         0 my $replacement = shift(@matches);
1891 0 0 0     0 $replacement .= $rl_completer_terminator_character
1892             if @matches == 1 && !$rl_completion_suppress_append;
1893 0 0       0 F_Ding() if @matches != 1;
1894 0 0       0 if ($var_TcshCompleteMode) {
1895 0         0 @tcsh_complete_selections = (@matches, $text);
1896 0         0 $tcsh_complete_start = $point;
1897 0         0 $tcsh_complete_len = length($replacement);
1898             }
1899              
1900 0 0       0 if ($replacement ne '') {
1901             # Finally! Do the replacement.
1902 0         0 substr($line, $point, $end-$point) = $replacement;
1903 0         0 $D = $D - ($end - $point) + length($replacement);
1904             }
1905             }
1906              
1907             =head3 F_SetMark
1908              
1909             Set the mark to the point. If a numeric argument is supplied, the mark
1910             is set to that position.
1911              
1912             =cut
1913              
1914             sub F_SetMark {
1915 0     0 1 0 $rl_mark = $D;
1916 0         0 pos $line = $rl_mark;
1917 0         0 $line_rl_mark = $rl_HistoryIndex;
1918 0         0 $force_redraw = 1;
1919             }
1920              
1921             =head3 F_ExchangePointAndMark
1922              
1923             Set the mark to the point. If a numeric argument is supplied, the mark
1924             is set to that position.
1925              
1926             =cut
1927              
1928             sub F_ExchangePointAndMark {
1929 0 0   0 1 0 return F_Ding unless $line_rl_mark == $rl_HistoryIndex;
1930 0         0 ($rl_mark, $D) = ($D, $rl_mark);
1931 0         0 pos $line = $rl_mark;
1932 0 0       0 $D = length $line if $D > length $line;
1933 0         0 $force_redraw = 1;
1934             }
1935              
1936             =head3 F_OperateAndGetNext
1937              
1938             Accept the current line and fetch from the history the next line
1939             relative to current line for default.
1940              
1941             =cut
1942              
1943             sub F_OperateAndGetNext
1944             {
1945 0     0 1 0 my $count = shift;
1946              
1947 0         0 &F_AcceptLine;
1948              
1949 0         0 my $remainingEntries = $#rl_History - $rl_HistoryIndex;
1950 0 0 0     0 if ($count > 0 && $remainingEntries >= 0) { # there is something to repeat
1951 0 0       0 if ($remainingEntries > 0) { # if we are not on last line
1952 0         0 $rl_HistoryIndex++; # fetch next one
1953 0 0       0 $count = $remainingEntries if $count > $remainingEntries;
1954             }
1955 0         0 $rl_OperateCount = $count;
1956             }
1957             }
1958              
1959             =head3 F_DoLowercaseVersion
1960              
1961             If the character that got us here is upper case,
1962             do the lower-case equivalent command.
1963              
1964             =cut
1965              
1966             sub F_DoLowercaseVersion
1967             {
1968 0     0 1 0 my $c = $_[1];
1969 0 0       0 if (isupper($c)) {
1970 0         0 &do_command(*KeyMap, $_[0], lc($c));
1971             } else {
1972 0         0 &F_Ding;
1973             }
1974             }
1975              
1976             =head3 F_DoControlVersion
1977              
1978             do the equiv with control key...
1979             If the character that got us here is upper case,
1980             do the lower-case equivalent command.
1981              
1982             =cut
1983              
1984             sub F_DoControlVersion
1985             {
1986 0     0 1 0 local *KeyMap = $var_EditingMode;
1987 0         0 my $key = $_[1];
1988              
1989 0 0       0 if ($key == ord('?')) {
1990 0         0 $key = 0x7F;
1991             } else {
1992 0         0 $key &= ~(0x80 | 0x60);
1993             }
1994 0         0 &do_command(*KeyMap, $_[0], $key);
1995             }
1996              
1997             =head3 F_DoMetaVersion
1998              
1999             do the equiv with meta key...
2000              
2001             =cut
2002              
2003             sub F_DoMetaVersion
2004             {
2005 0     0 1 0 local *KeyMap = $var_EditingMode;
2006 0         0 unshift @Pending, chr $_[1];
2007              
2008 0         0 &do_command(*KeyMap, $_[0], ord "\e");
2009             }
2010              
2011             =head3 F_DoEscVersion
2012              
2013             If the character that got us here is Alt-Char,
2014             do the Esc Char equiv...
2015              
2016             =cut
2017              
2018             sub F_DoEscVersion
2019             {
2020 0     0 1 0 my ($ord, $t) = $_[1];
2021 0 0       0 &F_Ding unless $KeyMap{'Esc'};
2022 0         0 for $t (([ord 'w', '`1234567890-='],
2023             [ord ',', 'zxcvbnm,./\\'],
2024             [16, 'qwertyuiop[]'],
2025             [ord(' ') - 2, 'asdfghjkl;\''])) {
2026 0 0 0     0 next unless $ord >= $t->[0] and $ord < $t->[0] + length($t->[1]);
2027 0         0 $ord = ord substr $t->[1], $ord - $t->[0], 1;
2028 0         0 return &do_command($KeyMap{'Esc'}, $_[0], $ord);
2029             }
2030 0         0 &F_Ding;
2031             }
2032              
2033             sub F_EmacsEditingMode
2034             {
2035 0     0 0 0 $var_EditingMode = $var_EditingMode{'emacs'};
2036 0         0 $Vi_mode = 0;
2037             }
2038              
2039             =head3 F_Interrupt
2040              
2041             (Attempt to) interrupt the current program via I
2042              
2043             =cut
2044              
2045             sub F_Interrupt
2046             {
2047 0     0 1 0 local $\ = '';
2048 0         0 print $term_OUT "\r\n";
2049 0         0 &ResetTTY;
2050 0         0 kill ("INT", 0);
2051              
2052             ## We're back.... must not have died.
2053 0         0 $force_redraw = 1;
2054             }
2055              
2056             ##
2057             ## Execute the next character input as a command in a meta keymap.
2058             ##
2059             sub F_PrefixMeta
2060             {
2061 0     0 0 0 my($count, $keymap) = ($_[0], "$KeyMap{'name'}_$_[1]");
2062 0 0       0 print "F_PrefixMeta [$keymap]\n\r" if $DEBUG;
2063 0 0       0 die "" unless %$keymap;
2064 0         0 do_command(*$keymap, $count, ord(&getc_with_pending));
2065             }
2066              
2067             sub F_InsertMode
2068             {
2069 0     0 0 0 $InsertMode = 1;
2070             }
2071              
2072             sub F_ToggleInsertMode
2073             {
2074 0     0 0 0 $InsertMode = !$InsertMode;
2075             }
2076              
2077             =head3 F_Suspend
2078              
2079             (Attempt to) suspend the program via I
2080              
2081             =cut
2082              
2083             sub F_Suspend
2084             {
2085 0 0 0 0 1 0 if ($inDOS && length($line)==0) { # EOF sent
2086 0 0       0 $AcceptLine = $ReturnEOF = 1 if $lastcommand ne 'F_DeleteChar';
2087 0         0 return;
2088             }
2089 0         0 local $\ = '';
2090 0         0 print $term_OUT "\r\n";
2091 0         0 &ResetTTY;
2092 0         0 eval { kill ("TSTP", 0) };
  0         0  
2093             ## We're back....
2094 0         0 &SetTTY;
2095 0         0 $force_redraw = 1;
2096             }
2097              
2098             =head3 F_Ding
2099              
2100             Ring the bell.
2101              
2102             Should do something with I<$var_PreferVisibleBel> here, but what?
2103              
2104             =cut
2105              
2106             sub F_Ding {
2107 0     0 1 0 Term::ReadLine::Perl5::Common::F_Ding($term_OUT)
2108             }
2109              
2110             =head2 vi Routines
2111              
2112             =cut
2113              
2114             sub F_ViAcceptLine
2115             {
2116 0     0 0 0 &F_AcceptLine();
2117 0         0 &F_ViInput();
2118             }
2119              
2120             =head3 F_ViRepeatLastCommand
2121              
2122             Repeat the most recent one of these vi commands:
2123              
2124             a A c C d D i I p P r R s S x X ~
2125              
2126             =cut
2127              
2128             sub F_ViRepeatLastCommand {
2129 0     0 1 0 my($count) = @_;
2130 0 0       0 return F_Ding() if !$Last_vi_command;
2131              
2132 0         0 my @lastcmd = @$Last_vi_command;
2133              
2134             # Multiply @lastcmd's numeric arg by $count.
2135 0 0       0 unless ($count == 1) {
2136              
2137 0         0 my $n = '';
2138 0   0     0 while (@lastcmd and $lastcmd[0] =~ /^\d$/) {
2139 0         0 $n *= 10;
2140 0         0 $n += shift(@lastcmd);
2141             }
2142 0 0       0 $count *= $n unless $n eq '';
2143 0         0 unshift(@lastcmd, split(//, $count));
2144             }
2145              
2146 0         0 push(@Pending, @lastcmd);
2147             }
2148              
2149             sub F_ViMoveCursor
2150             {
2151 0     0 0 0 my($count, $ord) = @_;
2152              
2153 0         0 my $new_cursor = &get_position($count, $ord, undef, $Vi_move_patterns);
2154 0 0       0 return F_Ding() if !defined $new_cursor;
2155              
2156 0         0 $D = $new_cursor;
2157             }
2158              
2159             sub F_ViFindMatchingParens {
2160              
2161             # Move to the first parens at or after $D
2162 0     0 0 0 my $old_d = $D;
2163 0         0 &forward_scan(1, q/[^[\](){}]*/);
2164 0         0 my $parens = substr($line, $D, 1);
2165              
2166             my $mate_direction = {
2167             '(' => [ ')', 1 ],
2168             '[' => [ ']', 1 ],
2169             '{' => [ '}', 1 ],
2170             ')' => [ '(', -1 ],
2171             ']' => [ '[', -1 ],
2172             '}' => [ '{', -1 ],
2173              
2174 0         0 }->{$parens};
2175              
2176 0 0       0 return &F_Ding() unless $mate_direction;
2177              
2178 0         0 my($mate, $direction) = @$mate_direction;
2179              
2180 0         0 my $lvl = 1;
2181 0         0 while ($lvl) {
2182 0 0 0     0 last if !$D && ($direction < 0);
2183 0         0 &F_ForwardChar($direction);
2184 0 0       0 last if &at_end_of_line;
2185 0         0 my $c = substr($line, $D, 1);
2186 0 0       0 if ($c eq $parens) {
    0          
2187 0         0 $lvl++;
2188             }
2189             elsif ($c eq $mate) {
2190 0         0 $lvl--;
2191             }
2192             }
2193              
2194 0 0       0 if ($lvl) {
2195             # We didn't find a match
2196 0         0 $D = $old_d;
2197 0         0 return &F_Ding();
2198             }
2199             }
2200              
2201             sub F_ViForwardFindChar {
2202 0     0 0 0 &do_findchar(1, 1, @_);
2203             }
2204              
2205             sub F_ViBackwardFindChar {
2206 0     0 0 0 &do_findchar(-1, 0, @_);
2207             }
2208              
2209             sub F_ViForwardToChar {
2210 0     0 0 0 &do_findchar(1, 0, @_);
2211             }
2212              
2213             sub F_ViBackwardToChar {
2214 0     0 0 0 &do_findchar(-1, 1, @_);
2215             }
2216              
2217             sub F_ViMoveCursorTo
2218             {
2219 0     0 0 0 &do_findchar(1, -1, @_);
2220             }
2221              
2222             sub F_ViMoveCursorFind
2223             {
2224 0     0 0 0 &do_findchar(1, 0, @_);
2225             }
2226              
2227              
2228             sub F_ViRepeatFindChar {
2229 0     0 0 0 my($n) = @_;
2230 0 0       0 return &F_Ding if !defined $Last_findchar;
2231 0         0 &findchar(@$Last_findchar, $n);
2232             }
2233              
2234             sub F_ViInverseRepeatFindChar {
2235 0     0 0 0 my($n) = @_;
2236 0 0       0 return &F_Ding if !defined $Last_findchar;
2237 0         0 my($c, $direction, $offset) = @$Last_findchar;
2238 0         0 &findchar($c, -$direction, $offset, $n);
2239             }
2240              
2241             sub do_findchar {
2242 0     0 0 0 my($direction, $offset, $n) = @_;
2243 0         0 my $c = &getc_with_pending;
2244 0 0       0 $c = &getc_with_pending if $c eq "\cV";
2245 0 0       0 return &F_ViCommandMode if $c eq "\e";
2246 0         0 $Last_findchar = [$c, $direction, $offset];
2247 0         0 &findchar($c, $direction, $offset, $n);
2248             }
2249              
2250             sub findchar {
2251 0     0 0 0 my($c, $direction, $offset, $n) = @_;
2252 0         0 my $old_d = $D;
2253 0         0 while ($n) {
2254 0 0 0     0 last if !$D && ($direction < 0);
2255 0         0 &F_ForwardChar($direction);
2256 0 0       0 last if &at_end_of_line;
2257 0         0 my $char = substr($line, $D, 1);
2258 0 0       0 $n-- if substr($line, $D, 1) eq $c;
2259             }
2260 0 0       0 if ($n) {
2261             # Not found
2262 0         0 $D = $old_d;
2263 0         0 return &F_Ding;
2264             }
2265 0         0 &F_ForwardChar($offset);
2266             }
2267              
2268             sub F_ViMoveToColumn {
2269 0     0 0 0 my($n) = @_;
2270 0         0 $D = 0;
2271 0         0 my $col = 1;
2272 0   0     0 while (!&at_end_of_line and $col < $n) {
2273 0         0 my $c = substr($line, $D, 1);
2274 0 0       0 if ($c eq "\t") {
2275 0         0 $col += 7;
2276 0         0 $col -= ($col % 8) - 1;
2277             }
2278             else {
2279 0         0 $col++;
2280             }
2281 0         0 $D += &CharSize($D);
2282             }
2283             }
2284              
2285             =head3 F_SaveLine
2286              
2287             Prepend line with '#', add to history, and clear the input buffer
2288             (this feature was borrowed from ksh).
2289              
2290             =cut
2291              
2292             sub F_SaveLine
2293             {
2294 0     0 1 0 local $\ = '';
2295 0         0 $line = '#'.$line;
2296 0         0 rl_redisplay();
2297 0         0 print $term_OUT "\r\n";
2298 0         0 &add_line_to_history($line, $minlength);
2299 0         0 $line_for_revert = '';
2300 0         0 &get_line_from_history(scalar @rl_History);
2301 0 0       0 &F_ViInput() if $Vi_mode;
2302             }
2303              
2304             =head3 F_ViNonePosition
2305              
2306             Come here if we see a non-positioning keystroke when a positioning
2307             keystroke is expected.
2308              
2309             =cut
2310              
2311             sub F_ViNonPosition {
2312             # Not a positioning command - undefine the cursor to indicate the error
2313             # to get_position().
2314 0     0 0 0 undef $D;
2315             }
2316              
2317             =head3 ViPositionEsc
2318              
2319             Comes here if we see II, but I an arrow key or other
2320             mapped sequence, when a positioning keystroke is expected.
2321              
2322             =cut
2323              
2324             sub F_ViPositionEsc {
2325 0     0 0 0 my($count, $ord) = @_;
2326              
2327             # We got in vipos mode. Put back onto the
2328             # input stream and terminate the positioning command.
2329 0         0 unshift(@Pending, pack('c', $ord));
2330 0         0 &F_ViNonPosition;
2331             }
2332              
2333             sub F_ViUndo {
2334 0 0   0 0 0 return &F_Ding unless defined $Vi_undo_state;
2335 0         0 my $state = savestate();
2336 0         0 &getstate($Vi_undo_state);
2337 0         0 $Vi_undo_state = $state;
2338             }
2339              
2340             sub F_ViUndoAll {
2341 0     0 0 0 $Vi_undo_state = $Vi_undo_all_state;
2342 0         0 &F_ViUndo;
2343             }
2344              
2345             sub F_ViChange
2346             {
2347 0     0 0 0 my($count, $ord) = @_;
2348 0         0 &start_dot_buf(@_);
2349 0 0       0 &do_delete($count, $ord, $Vi_change_patterns) || return();
2350 0         0 &vi_input_mode;
2351             }
2352              
2353             sub F_ViDelete
2354             {
2355 0     0 0 0 my($count, $ord) = @_;
2356 0         0 &start_dot_buf(@_);
2357 0         0 &do_delete($count, $ord, $Vi_delete_patterns);
2358 0         0 &end_dot_buf;
2359             }
2360              
2361             sub F_ViDeleteChar {
2362 0     0 0 0 my($count) = @_;
2363 0         0 &save_dot_buf(@_);
2364 0         0 my $other_end = $D + $count;
2365 0 0       0 $other_end = length($line) if $other_end > length($line);
2366 0         0 &kill_text($D, $other_end, 1);
2367             }
2368              
2369             sub F_ViBackwardDeleteChar {
2370 0     0 0 0 my($count) = @_;
2371 0         0 &save_dot_buf(@_);
2372 0         0 my $other_end = $D - $count;
2373 0 0       0 $other_end = 0 if $other_end < 0;
2374 0         0 &kill_text($other_end, $D, 1);
2375 0         0 $D = $other_end;
2376             }
2377              
2378             =head3 F_ViFirstWord
2379              
2380             Go to first non-space character of line.
2381              
2382             =cut
2383              
2384             sub F_ViFirstWord
2385             {
2386 0     0 1 0 $D = 0;
2387 0         0 &forward_scan(1, q{\s+});
2388             }
2389              
2390             =head3 F_ViTtoggleCase
2391              
2392             # Like the emacs case transforms.
2393              
2394             I: this doesn't work for multi-byte characters.
2395              
2396             =cut
2397              
2398             sub F_ViToggleCase {
2399 0     0 0 0 my($count) = @_;
2400 0         0 &save_dot_buf(@_);
2401 0         0 while ($count-- > 0) {
2402 0         0 substr($line, $D, 1) =~ tr/A-Za-z/a-zA-Z/;
2403 0         0 &F_ForwardChar(1);
2404 0 0       0 if (&at_end_of_line) {
2405 0         0 &F_BackwardChar(1);
2406 0         0 last;
2407             }
2408             }
2409             }
2410              
2411             =head3 F_ViHistoryLine
2412              
2413             Go to the numbered history line, as listed by the 'H' command,
2414             i.e. the current $line is line 1, the youngest line in I<@rl_History>
2415             is 2, etc.
2416              
2417             =cut
2418              
2419             sub F_ViHistoryLine {
2420 0     0 1 0 my($n) = @_;
2421 0         0 &get_line_from_history(@rl_History - $n + 1);
2422             }
2423              
2424             =head3 F_ViSearch
2425              
2426             Search history for matching string. As with vi in nomagic mode, the
2427             ^, $, \<, and \> positional assertions, the \* quantifier, the \.
2428             character class, and the \[ character class delimiter all have special
2429             meaning here.
2430              
2431             =cut
2432              
2433             sub F_ViSearch {
2434 0     0 1 0 my($n, $ord) = @_;
2435              
2436 0         0 my $c = pack('c', $ord);
2437              
2438 0         0 my $str = &get_vi_search_str($c);
2439 0 0       0 if (!defined $str) {
2440             # Search aborted by deleting the '/' at the beginning of the line
2441 0 0       0 return &F_ViInput() if $line eq '';
2442 0         0 return();
2443             }
2444              
2445             # Null string repeats last search
2446 0 0       0 if ($str eq '') {
2447 0 0       0 return &F_Ding unless defined $Vi_search_re;
2448             }
2449             else {
2450             # Convert to a regular expression. Interpret $str Like vi in nomagic
2451             # mode: '^', '$', '\<', and '\>' positional assertions, '\*'
2452             # quantifier, '\.' and '\[]' character classes.
2453              
2454 0         0 my @chars = ($str =~ m{(\\?.)}g);
2455 0         0 my(@re, @tail);
2456 0 0 0     0 unshift(@re, shift(@chars)) if @chars and $chars[0] eq '^';
2457 0 0 0     0 push (@tail, pop(@chars)) if @chars and $chars[-1] eq '$';
2458 0         0 my $in_chclass;
2459 0         0 my %chmap = (
2460             '\<' => '\b(?=\w)',
2461             '\>' => '(?<=\w)\b',
2462             '\*' => '*',
2463             '\[' => '[',
2464             '\.' => '.',
2465             );
2466 0         0 my $ch;
2467 0         0 foreach $ch (@chars) {
2468 0 0       0 if ($in_chclass) {
2469             # Any backslashes in vi char classes are literal
2470 0 0       0 push(@re, "\\") if length($ch) > 1;
2471 0         0 push(@re, $ch);
2472 0 0       0 $in_chclass = 0 if $ch =~ /\]$/;
2473             }
2474             else {
2475 0 0 0     0 push(@re, (length $ch == 2) ? ($chmap{$ch} || $ch) :
    0          
2476             ($ch =~ /^\w$/) ? $ch :
2477             ("\\", $ch));
2478 0 0       0 $in_chclass = 1 if $ch eq '\[';
2479             }
2480             }
2481 0         0 my $re = join('', @re, @tail);
2482 0         0 $Vi_search_re = q{$re};
2483             }
2484              
2485 0 0       0 local $reverse = $Vi_search_reverse = ($c eq '/') ? 1 : 0;
2486 0         0 &do_vi_search();
2487             }
2488              
2489             sub F_ViRepeatSearch {
2490 0     0 0 0 my($n, $ord) = @_;
2491 0         0 my $c = pack('c', $ord);
2492 0 0       0 return &F_Ding unless defined $Vi_search_re;
2493 0         0 local $reverse = $Vi_search_reverse;
2494 0 0       0 $reverse ^= 1 if $c eq 'N';
2495 0         0 &do_vi_search();
2496             }
2497              
2498       0 0   sub F_ViEndSearch {}
2499              
2500             sub F_ViSearchBackwardDeleteChar {
2501 0 0   0 0 0 if ($line eq '') {
2502             # Backspaced past beginning of line - terminate search mode
2503 0         0 undef $line;
2504             }
2505             else {
2506 0         0 &F_BackwardDeleteChar(@_);
2507             }
2508             }
2509              
2510             =head3 F_ViChangeEntireLine
2511              
2512             Kill entire line and enter input mode
2513              
2514             =cut
2515              
2516             sub F_ViChangeEntireLine
2517             {
2518 0     0 1 0 &start_dot_buf(@_);
2519 0         0 kill_text(0, length($line), 1);
2520 0         0 &vi_input_mode;
2521             }
2522              
2523             =head3 F_ViChangeChar
2524              
2525             Kill characters and enter input mode
2526              
2527             =cut
2528              
2529             sub F_ViChangeChar
2530             {
2531 0     0 1 0 &start_dot_buf(@_);
2532 0         0 &F_DeleteChar(@_);
2533 0         0 &vi_input_mode;
2534             }
2535              
2536             sub F_ViReplaceChar
2537             {
2538 0     0 0 0 &start_dot_buf(@_);
2539 0         0 my $c = &getc_with_pending;
2540 0 0       0 $c = &getc_with_pending if $c eq "\cV"; # ctrl-V
2541 0 0       0 return &F_ViCommandMode if $c eq "\e";
2542 0         0 &end_dot_buf;
2543              
2544 0         0 local $InsertMode = 0;
2545 0         0 local $D = $D; # Preserve cursor position
2546 0         0 &F_SelfInsert(1, ord($c));
2547             }
2548              
2549             =head3 F_ViChangeLine
2550              
2551             Delete characteres from cursor to end of line and enter VI input mode.
2552              
2553             =cut
2554              
2555             sub F_ViChangeLine
2556             {
2557 0     0 1 0 &start_dot_buf(@_);
2558 0         0 &F_KillLine(@_);
2559 0         0 &vi_input_mode;
2560             }
2561              
2562             sub F_ViDeleteLine
2563             {
2564 0     0 0 0 &save_dot_buf(@_);
2565 0         0 &F_KillLine(@_);
2566             }
2567              
2568             sub F_ViPut
2569             {
2570 0     0 0 0 my($count) = @_;
2571 0         0 &save_dot_buf(@_);
2572 0         0 my $text2add = $KillBuffer x $count;
2573 0         0 my $ll = length($line);
2574 0         0 $D++;
2575 0 0       0 $D = $ll if $D > $ll;
2576 0         0 substr($line, $D, 0) = $KillBuffer x $count;
2577 0         0 $D += length($text2add) - 1;
2578             }
2579              
2580             sub F_ViPutBefore
2581             {
2582 0     0 0 0 &save_dot_buf(@_);
2583 0         0 &TextInsert($_[0], $KillBuffer);
2584             }
2585              
2586             sub F_ViYank
2587             {
2588 0     0 0 0 my($count, $ord) = @_;
2589 0         0 my $pos = &get_position($count, undef, $ord, $Vi_yank_patterns);
2590 0 0       0 &F_Ding if !defined $pos;
2591 0 0       0 if ($pos < 0) {
2592             # yy
2593 0         0 &F_ViYankLine;
2594             }
2595             else {
2596 0 0       0 my($from, $to) = ($pos > $D) ? ($D, $pos) : ($pos, $D);
2597 0         0 $KillBuffer = substr($line, $from, $to-$from);
2598             }
2599             }
2600              
2601             sub F_ViYankLine
2602             {
2603 0     0 0 0 $KillBuffer = $line;
2604             }
2605              
2606             sub F_ViInput
2607             {
2608 0 0   0 0 0 @_ = (1, ord('i')) if !@_;
2609 0         0 &start_dot_buf(@_);
2610 0         0 &vi_input_mode;
2611             }
2612              
2613             sub F_ViBeginInput
2614             {
2615 0     0 0 0 &start_dot_buf(@_);
2616 0         0 &F_BeginningOfLine;
2617 0         0 &vi_input_mode;
2618             }
2619              
2620             sub F_ViReplaceMode
2621             {
2622 0     0 0 0 &start_dot_buf(@_);
2623 0         0 $InsertMode = 0;
2624 0         0 $var_EditingMode = $var_EditingMode{'vi'};
2625 0         0 $Vi_mode = 1;
2626             }
2627             # The previous keystroke was an escape, but the sequence was not recognized
2628             # as a mapped sequence (like an arrow key). Enter vi comand mode and
2629             # process this keystroke.
2630             sub F_ViAfterEsc {
2631 0     0 0 0 my($n, $ord) = @_;
2632 0         0 &F_ViCommandMode;
2633 0         0 &do_command($var_EditingMode, 1, $ord);
2634             }
2635              
2636             sub F_ViAppend
2637             {
2638 0     0 0 0 &start_dot_buf(@_);
2639 0         0 &vi_input_mode;
2640 0         0 &F_ForwardChar;
2641             }
2642              
2643             sub F_ViAppendLine
2644             {
2645 0     0 0 0 &start_dot_buf(@_);
2646 0         0 &vi_input_mode;
2647 0         0 &F_EndOfLine;
2648             }
2649              
2650             sub F_ViCommandMode
2651             {
2652 0     0 0 0 $var_EditingMode = $var_EditingMode{'vicmd'};
2653 0         0 $Vi_mode = 1;
2654             }
2655              
2656             sub F_ViAcceptInsert {
2657 0     0 0 0 local $in_accept_line = 1;
2658 0         0 &F_ViEndInsert;
2659 0         0 &F_ViAcceptLine;
2660             }
2661              
2662             sub F_ViEndInsert
2663             {
2664 0 0   0 0 0 if ($Dot_buf) {
2665 0 0 0     0 if ($line eq '' and $Dot_buf->[0] eq 'i') {
2666             # We inserted nothing into an empty $line - assume it was a
2667             # &F_ViInput() call with no arguments, and don't save command.
2668 0         0 undef $Dot_buf;
2669             }
2670             else {
2671             # Regardless of which keystroke actually terminated this insert
2672             # command, replace it with an in the dot buffer.
2673 0         0 @{$Dot_buf}[-1] = "\e";
  0         0  
2674 0         0 &end_dot_buf;
2675             }
2676             }
2677 0         0 &F_ViCommandMode;
2678             # Move cursor back to the last inserted character, but not when
2679             # we're about to accept a line of input
2680 0 0       0 &F_BackwardChar(1) unless $in_accept_line;
2681             }
2682              
2683             sub F_ViDigit {
2684 0     0 0 0 my($count, $ord) = @_;
2685              
2686 0         0 my $n = 0;
2687 0         0 my $ord0 = ord('0');
2688 0         0 while (1) {
2689              
2690 0         0 $n *= 10;
2691 0         0 $n += $ord - $ord0;
2692              
2693 0         0 my $c = &getc_with_pending;
2694 0 0       0 return unless defined $c;
2695 0         0 $ord = ord($c);
2696 0 0       0 last unless $c =~ /^\d$/;
2697             }
2698              
2699 0         0 $n *= $count; # So 2d3w deletes six words
2700 0 0       0 $n = $rl_max_numeric_arg if $n > $rl_max_numeric_arg;
2701              
2702 0         0 &do_command($var_EditingMode, $n, $ord);
2703             }
2704              
2705             sub F_ViComplete {
2706 0     0 0 0 my($n, $ord) = @_;
2707              
2708 0         0 $Dot_state = savestate(); # Completion is undo-able
2709 0         0 undef $Dot_buf; # but not redo-able
2710              
2711 0         0 my $ch;
2712 0         0 while (1) {
2713              
2714 0 0       0 &F_Complete() or return;
2715              
2716             # Vi likes the cursor one character right of where emacs like it.
2717 0         0 &F_ForwardChar(1);
2718 0         0 rl_forced_update_display();
2719              
2720             # Look ahead to the next input keystroke.
2721 0         0 $ch = &getc_with_pending();
2722 0 0       0 last unless ord($ch) == $ord; # Not a '\' - quit.
2723              
2724             # Another '\' was typed - put the cursor back where &F_Complete left
2725             # it, and try again.
2726 0         0 &F_BackwardChar(1);
2727 0         0 $lastcommand = 'F_Complete'; # Play along with &F_Complete's kludge
2728             }
2729 0         0 unshift(@Pending, $ch); # Unget the lookahead keystroke
2730              
2731             # Successful completion - enter input mode with cursor beyond end of word.
2732 0         0 &vi_input_mode;
2733             }
2734              
2735             sub F_ViInsertPossibleCompletions {
2736 0     0 0 0 $Dot_state = savestate(); # Completion is undo-able
2737 0         0 undef $Dot_buf; # but not redo-able
2738              
2739 0 0       0 &complete_internal('*') or return;
2740              
2741             # Successful completion - enter input mode with cursor beyond end of word.
2742 0         0 &F_ForwardChar(1);
2743 0         0 &vi_input_mode;
2744             }
2745              
2746             sub F_ViPossibleCompletions {
2747              
2748             # List possible completions
2749 0     0 0 0 &complete_internal('?');
2750              
2751             # Enter input mode with cursor where we left off.
2752 0         0 &F_ForwardChar(1);
2753 0         0 &vi_input_mode;
2754             }
2755              
2756             sub F_CopyRegionAsKillClipboard {
2757 0 0   0 0 0 return clipboard_set($line) unless $line_rl_mark == $rl_HistoryIndex;
2758 0         0 &F_CopyRegionAsKill;
2759 0         0 clipboard_set($KillBuffer);
2760             }
2761              
2762             sub F_KillRegionClipboard {
2763 0     0 0 0 &F_KillRegion;
2764 0         0 clipboard_set($KillBuffer);
2765             }
2766              
2767             sub F_YankClipboard
2768             {
2769 0     0 0 0 remove_selection();
2770 0         0 my $in;
2771 0 0       0 if ($^O eq 'os2') {
    0          
2772 0         0 eval {
2773 0         0 require OS2::Process;
2774 0         0 $in = OS2::Process::ClipbrdText();
2775 0         0 $in =~ s/\r\n/\n/g; # With old versions, or what?
2776             }
2777             } elsif ($^O eq 'MSWin32') {
2778 0         0 eval {
2779 0         0 require Win32::Clipboard;
2780 0         0 $in = Win32::Clipboard::GetText();
2781 0         0 $in =~ s/\r\n/\n/g; # is this needed?
2782             }
2783             } else {
2784 0         0 my $mess;
2785             my $paste_fh;
2786 0 0       0 if ($ENV{RL_PASTE_CMD}) {
    0          
2787 0         0 $mess = "Reading from pipe `$ENV{RL_PASTE_CMD}'";
2788 0 0       0 open($paste_fh, "$ENV{RL_PASTE_CMD} |") or warn("$mess: $!"), return;
2789             } elsif (defined $HOME) {
2790 0         0 my $cutpastefile = File::Spec($HOME, '.rl_cutandpaste');
2791 0         0 $mess = "Reading from file `$cutpastefile'";
2792 0 0       0 open($paste_fh, '<:encoding(utf-8)', $cutpastefile)
2793             or warn("$mess: $!"), return;
2794             }
2795 0 0       0 if ($mess) {
2796 0         0 local $/;
2797 0         0 $in = <$paste_fh>;
2798 0 0       0 close $paste_fh or warn("$mess, closing: $!");
2799             }
2800             }
2801 0 0       0 if (defined $in) {
2802 0         0 $in =~ s/\n+$//;
2803 0         0 return &TextInsert($_[0], $in);
2804             }
2805 0         0 &TextInsert($_[0], $KillBuffer);
2806             }
2807              
2808             sub F_BeginUndoGroup {
2809 0     0 0 0 push @undoGroupS, $#undo;
2810             }
2811              
2812             sub F_EndUndoGroup {
2813 0 0   0 0 0 return F_Ding unless @undoGroupS;
2814 0         0 my $last = pop @undoGroupS;
2815 0 0       0 return unless $#undo > $last + 1;
2816 0         0 my $now = pop @undo;
2817 0         0 $#undo = $last;
2818 0         0 push @undo, $now;
2819             }
2820              
2821             sub F_DoNothing { # E.g., reset digit-argument
2822 0     0 0 0 1;
2823             }
2824              
2825             sub F_ForceMemorizeDigitArgument {
2826 0     0 0 0 $memorizedArg = shift;
2827             }
2828              
2829             sub F_MemorizeDigitArgument {
2830 0 0   0 0 0 return if defined $memorizedArg;
2831 0         0 $memorizedArg = shift;
2832             }
2833              
2834             sub F_UnmemorizeDigitArgument {
2835 0     0 0 0 $memorizedArg = undef;
2836             }
2837              
2838             sub F_MemorizePos {
2839 0     0 0 0 $memorizedPos = $D;
2840             }
2841              
2842             ###########################################################################
2843              
2844             # It is assumed that F_MemorizePos was called, then something was inserted,
2845             # then F_MergeInserts is called with a prefix argument to multiply
2846             # insertion by
2847              
2848             sub F_MergeInserts {
2849 0     0 0 0 my $n = shift;
2850 0 0 0     0 return F_Ding unless defined $memorizedPos and $n > 0;
2851 0         0 my ($b, $e) = ($memorizedPos, $D);
2852 0 0       0 ($b, $e) = ($e, $b) if $e < $b;
2853 0 0       0 if ($n) {
2854 0         0 substr($line, $e, 0) = substr($line, $b, $e - $b) x ($n - 1);
2855             } else {
2856 0         0 substr($line, $b, $e - $b) = '';
2857             }
2858 0         0 $D = $b + ($e - $b) * $n;
2859             }
2860              
2861             sub F_ResetDigitArgument {
2862 0 0   0 0 0 return F_Ding unless defined $memorizedArg;
2863 0         0 my $in = &getc_with_pending;
2864 0 0       0 return unless defined $in;
2865 0         0 my $ord = ord $in;
2866 0         0 local(*KeyMap) = $var_EditingMode;
2867 0         0 &do_command(*KeyMap, $memorizedArg, $ord);
2868             }
2869              
2870             sub F_BeginPasteGroup {
2871 0     0 0 0 my $c = shift;
2872 0 0       0 $memorizedArg = $c unless defined $memorizedArg;
2873 0         0 F_BeginUndoGroup(1);
2874 0         0 $memorizedPos = $D;
2875             }
2876              
2877             sub F_EndPasteGroup {
2878 0     0 0 0 my $c = $memorizedArg;
2879 0         0 undef $memorizedArg;
2880 0 0       0 $c = 1 unless defined $c;
2881 0         0 F_MergeInserts($c);
2882 0         0 F_EndUndoGroup(1);
2883             }
2884              
2885             sub F_BeginEditGroup {
2886 0     0 0 0 $memorizedArg = shift;
2887 0         0 F_BeginUndoGroup(1);
2888             }
2889              
2890             sub F_EndEditGroup {
2891 0     0 0 0 undef $memorizedArg;
2892 0         0 F_EndUndoGroup(1);
2893             }
2894              
2895             ###########################################################################
2896             =head2 Internal Routines
2897              
2898             =head3 get_window_size
2899              
2900             get_window_size([$redisplay])
2901              
2902             I
2903             or the GNU ReadLine library. As such, it may disappear and be replaced
2904             by the corresponding L routines.>
2905              
2906             Causes a query to get the terminal width. If the terminal width can't
2907             be obtained, nothing is done. Otherwise...
2908              
2909             =over
2910              
2911             =item * Set I<$rl_screen_width> and to the current screen width.
2912             I<$rl_margin> is then set to be 1/3 of I<$rl_screen_width>.
2913              
2914             =item * any window-changeing hooks stored in array I<@winchhooks> are
2915             run.
2916              
2917             =item * I is set to run this routine. Any routines set are
2918             lost. A better behavior would be to add existing hooks to
2919             I<@winchhooks>, but hey, this routine is deprecated.
2920              
2921             =item * If I<$redisplay> is passed and is true, then a redisplay of
2922             the input line is done by calling I.
2923              
2924             =back
2925              
2926             =cut
2927              
2928             sub get_window_size
2929             {
2930 14     14 1 43 my $redraw = shift;
2931              
2932             # Preserve $! etc; the rest for hooks
2933 14         292 local($., $@, $!, $^E, $?);
2934              
2935 14         53 my ($num_cols,$num_rows) = (undef, undef);
2936 14         41 eval {
2937 14         100 ($num_cols,$num_rows) = Term::ReadKey::GetTerminalSize($term_OUT);
2938             };
2939 14 100 66     42966 return unless defined($num_cols) and defined($num_rows);
2940 9 50 33     79 $rl_screen_width = $num_cols - $rl_correct_sw
2941             if defined($num_cols) && $num_cols;
2942 9         43 $rl_margin = int($rl_screen_width/3);
2943 9 50       37 if (defined $redraw) {
2944 0         0 rl_forced_update_display();
2945             }
2946              
2947 9         62 for my $hook (@winchhooks) {
2948 0 0 0     0 eval {&$hook()}; warn $@ if $@ and $^W;
  0         0  
  0         0  
2949             }
2950             }
2951              
2952              
2953             sub get_ornaments_selected {
2954 0 0   0 0 0 return if @$rl_term_set >= 6;
2955 0         0 local $^W=0;
2956 0         0 my $Orig = Term::ReadLine::TermCap::ornaments(__PACKAGE__);
2957 0         0 eval {
2958             # Term::ReadLine does not expose its $terminal, so make another
2959 0         0 require Term::Cap;
2960 0         0 my $terminal = Tgetent Term::Cap ({OSPEED=>9600});
2961             # and be sure the terminal supports highlighting
2962 0         0 $terminal->Trequire('mr');
2963             };
2964 0 0 0     0 if (!$@ and $Orig ne ',,,'){
2965 0         0 my @set = @$rl_term_set;
2966              
2967 0         0 Term::ReadLine::TermCap::ornaments(__PACKAGE__,
2968             join(',',
2969             (split(/,/, $Orig))[0,1])
2970             . ',mr,me') ;
2971 0         0 @set[4,5] = @$rl_term_set[2,3];
2972 0         0 Term::ReadLine::TermCap::ornaments(__PACKAGE__, $Orig);
2973 0         0 @$rl_term_set = @set;
2974             } else {
2975 0         0 @$rl_term_set[4,5] = @$rl_term_set[2,3];
2976             }
2977             }
2978              
2979             =head3 readline
2980              
2981             &readline::readline($prompt, $default)>
2982              
2983             The main routine to call interactively read lines. Parameter
2984             I<$prompt> is the text you want to prompt with If it is empty string,
2985             no preceding prompt text is given. It is I a default value of
2986             "INPUT> " is used.
2987              
2988             Parameter I<$default> is the default value; it can be can be
2989             omitted. The next input line is returned or I on EOF.
2990              
2991             =cut
2992              
2993             sub readline($;$)
2994             {
2995 11     11   183 no warnings 'once';
  11         35  
  11         85985  
2996 0 0 0 0 1 0 $Term::ReadLine::Perl5::term->register_Tk
      0        
2997             if not $Term::ReadLine::registered and $Term::ReadLine::toloop
2998             and defined &Tk::DoOneEvent;
2999 0 0       0 if ($stdin_not_tty) {
3000 0         0 local $/ = "\n";
3001 0 0       0 return undef if !defined($line = <$term_IN>);
3002 0         0 chomp($line);
3003 0         0 return $line;
3004             }
3005              
3006 0         0 $old = select $term_OUT;
3007 0         0 $oldbar = $|;
3008 0         0 local($|) = 1;
3009 0         0 local($input);
3010              
3011             ## prompt should be given to us....
3012 0 0       0 $prompt = defined($_[0]) ? $_[0] : 'INPUT> ';
3013              
3014             # Try to move cursor to the beginning of the next line if this line
3015             # contains anything.
3016              
3017             # On DOSish 80-wide console
3018             # perl -we "print 1 x shift, qq(\b2\r3); sleep 2" 79
3019             # prints 3 on the same line,
3020             # perl -we "print 1 x shift, qq(\b2\r3); sleep 2" 80
3021             # on the next; $rl_screen_width is 79.
3022              
3023             # on XTerm one needs to increase the number by 1.
3024              
3025 0 0       0 print $term_OUT ' ' x ($rl_screen_width - !$rl_last_pos_can_backspace) . "\b \r"
3026             if $rl_scroll_nextline;
3027              
3028 0 0       0 if ($dumb_term) {
3029 0         0 return Term::ReadLine::Perl5::Dumb::readline($prompt, $term_IN,
3030             $term_OUT);
3031             }
3032              
3033             # test if we resume an 'Operate' command
3034 0 0 0     0 if ($rl_OperateCount > 0 && (!defined $_[1] || $_[1] eq '')) {
      0        
3035             ## it's from a valid previous 'Operate' command and
3036             ## user didn't give a default line
3037             ## we leave $rl_HistoryIndex untouched
3038 0         0 $line = $rl_History[$rl_HistoryIndex];
3039             } else {
3040             ## set history pointer at the end of history
3041 0         0 $rl_HistoryIndex = $#rl_History + 1;
3042 0         0 $rl_OperateCount = 0;
3043 0 0       0 $line = defined $_[1] ? $_[1] : '';
3044             }
3045 0 0       0 $rl_OperateCount-- if $rl_OperateCount > 0;
3046              
3047 0         0 $line_for_revert = $line;
3048              
3049             # I don't think we need to do this, actually...
3050             # while (&ioctl(STDIN,$FIONREAD,$fion))
3051             # {
3052             # local($n_chars_available) = unpack ($fionread_t, $fion);
3053             # ## print "n_chars = $n_chars_available\n";
3054             # last if $n_chars_available == 0;
3055             # $line .= getc_with_pending; # should we prepend if $rl_start_default_at_beginning?
3056             # }
3057              
3058 0 0       0 $D = $rl_start_default_at_beginning ? 0 : length($line); ## set dot.
3059 0         0 $LastCommandKilledText = 0; ## heck, was no last command.
3060 0         0 $lastcommand = ''; ## Well, there you go.
3061 0         0 $line_rl_mark = -1;
3062              
3063             ##
3064             ## some stuff for rl_redisplay.
3065             ##
3066 0         0 $lastredisplay = ''; ## Was no last redisplay for this time.
3067 0         0 $lastlen = length($lastredisplay);
3068 0         0 $lastpromptlen = 0;
3069 0         0 $lastdelta = 0; ## Cursor was nowhere
3070 0         0 $si = 0; ## Want line to start left-justified
3071 0         0 $force_redraw = 1; ## Want to display with brute force.
3072 0 0       0 if (!eval {SetTTY()}) { ## Put into raw mode.
  0         0  
3073 0 0       0 warn $@ if $@;
3074 0         0 $dumb_term = 1;
3075 0         0 return Term::ReadLine::Perl5::Dumb::readline($prompt, $term_IN,
3076             $term_OUT);
3077             }
3078              
3079 0         0 *KeyMap = $var_EditingMode;
3080 0         0 undef($AcceptLine); ## When set, will return its value.
3081 0         0 undef($ReturnEOF); ## ...unless this on, then return undef.
3082 0         0 @Pending = (); ## Contains characters to use as input.
3083 0         0 @undo = (); ## Undo history starts empty for each line.
3084 0         0 @undoGroupS = (); ## Undo groups start empty for each line.
3085 0         0 undef $memorizedArg; ## No digitArgument memorized
3086 0         0 undef $memorizedPos; ## No position memorized
3087              
3088 0         0 undef $Vi_undo_state;
3089 0         0 undef $Vi_undo_all_state;
3090              
3091             # We need to do some additional initialization for vi mode.
3092             # RS: bug reports/platform issues are welcome: russ@dvns.com
3093 0 0       0 if ($KeyMap{'name'} eq 'vi_keymap'){
3094 0         0 &F_ViInput();
3095 0 0       0 if ($rl_vi_replace_default_on_insert){
3096 0         0 local $^W=0;
3097 0         0 my $Orig = Term::ReadLine::TermCap::ornaments(__PACKAGE__);
3098 0         0 eval {
3099             # Term::ReadLine does not expose its $terminal, so make another
3100 0         0 require Term::Cap;
3101 0         0 my $terminal = Tgetent Term::Cap ({OSPEED=>9600});
3102             # and be sure the terminal supports highlighting
3103 0         0 $terminal->Trequire('mr');
3104             };
3105 0 0 0     0 if (!$@ and $Orig ne ',,,'){
3106 0         0 Term::ReadLine::TermCap::ornaments(__PACKAGE__,
3107             join(',',
3108             (split(/,/, $Orig))[0,1])
3109             . ',mr,me');
3110             }
3111 0         0 my $F_SelfInsert_Real = \&F_SelfInsert;
3112             *F_SelfInsert = sub {
3113 0     0   0 Term::ReadLine::TermCap::ornaments(__PACKAGE__);
3114 0         0 &F_ViChangeEntireLine;
3115 0         0 local $^W=0;
3116 0         0 *F_SelfInsert = $F_SelfInsert_Real;
3117 0         0 &F_SelfInsert;
3118 0         0 };
3119 0         0 my $F_ViEndInsert_Real = \&F_ViEndInsert;
3120             *F_ViEndInsert = sub {
3121 0     0   0 Term::ReadLine::TermCap::ornaments(__PACKAGE__, $Orig);
3122 0         0 local $^W=0;
3123 0         0 *F_SelfInsert = $F_SelfInsert_Real;
3124 0         0 *F_ViEndInsert = $F_ViEndInsert_Real;
3125 0         0 &F_ViEndInsert;
3126 0         0 $force_redraw = 1;
3127 0         0 rl_redisplay();
3128 0         0 };
3129             }
3130             }
3131              
3132 0 0       0 if ($rl_default_selected) {
3133 0         0 redisplay_high();
3134             } else {
3135             ## Show the line (prompt+default at this point).
3136 0         0 rl_redisplay();
3137             }
3138              
3139             # pretend input if we 'Operate' on more than one line
3140 0 0       0 &F_OperateAndGetNext($rl_OperateCount) if $rl_OperateCount > 0;
3141              
3142 0         0 $rl_first_char = 1;
3143 0         0 while (!defined($AcceptLine)) {
3144             ## get a character of input
3145 0         0 $input = &getc_with_pending(); # bug in debugger, returns 42. - No more!
3146              
3147 0 0       0 unless (defined $input) {
3148             # XXX What to do??? Until this is clear, just pretend we got EOF
3149 0         0 $AcceptLine = $ReturnEOF = 1;
3150 0         0 last;
3151             }
3152 0         0 preserve_state();
3153              
3154 0         0 $ThisCommandKilledText = 0;
3155             ##print "\n\rline is @$D:[$line]\n\r"; ##DEBUG
3156 0         0 my $cmd = get_command($var_EditingMode, ord($input));
3157 0 0 0     0 if ( $rl_first_char && $cmd =~ /^F_(SelfInsert$|Yank)/
      0        
      0        
3158             && length $line && $rl_default_selected ) {
3159             # (Backward)?DeleteChar special-cased in the code.
3160 0         0 $line = '';
3161 0         0 $D = 0;
3162 0 0       0 $cmd = 'F_BackwardDeleteChar' if $cmd eq 'F_DeleteChar';
3163             }
3164 0         0 undef $doingNumArg;
3165              
3166             # Execute input
3167 0         0 eval { &$cmd(1, ord($input)); };
  0         0  
3168              
3169 0         0 $rl_first_char = 0;
3170 0         0 $lastcommand = $cmd;
3171 0         0 *KeyMap = $var_EditingMode; # JP: added
3172              
3173             # In Vi command mode, don't position the cursor beyond the last
3174             # character of the line buffer.
3175             &F_BackwardChar(1) if $Vi_mode and $line ne ''
3176 0 0 0     0 and &at_end_of_line and $KeyMap{'name'} eq 'vicmd_keymap';
      0        
      0        
3177              
3178 0         0 rl_redisplay();
3179 0         0 $LastCommandKilledText = $ThisCommandKilledText;
3180             }
3181              
3182 0         0 undef @undo; ## Release the memory.
3183 0         0 undef @undoGroupS; ## Release the memory.
3184 0         0 &ResetTTY; ## Restore the tty state.
3185 0         0 $| = $oldbar;
3186 0         0 select $old;
3187 0 0       0 return undef if defined($ReturnEOF);
3188             #print STDOUT "|al=`$AcceptLine'";
3189 0         0 $AcceptLine; ## return the line accepted.
3190             }
3191              
3192             sub SetTTY {
3193 0 0 0 0 0 0 return if $dumb_term || $stdin_not_tty;
3194             #return system 'stty raw -echo' if defined &DB::DB;
3195 0         0 Term::ReadKey::ReadMode(4, $term_IN);
3196 0 0       0 if ($^O eq 'MSWin32') {
3197             # If we reached this, Perl isn't cygwin; Enter sends \r; thus
3198             # we need binmode XXXX Do we need to undo??? $term_IN is most
3199             # probably private now...
3200 0         0 binmode $term_IN;
3201             }
3202 0         0 return 1;
3203             }
3204              
3205             sub ResetTTY {
3206 1 50 33 1 0 9 return if $dumb_term || $stdin_not_tty;
3207 1         5 return Term::ReadKey::ReadMode(0, $term_IN);
3208             }
3209              
3210             =head3 substr_with_props
3211              
3212             C
3213              
3214             Gives the I of C<$prompt.$string> with embedded face-change
3215             commands.
3216              
3217             =cut
3218              
3219             sub substr_with_props {
3220 0     0 1 0 my ($p, $s, $from, $len, $ket, $bsel, $esel) = @_;
3221 0         0 my $lp = length $p;
3222              
3223 0 0       0 defined $from or $from = 0;
3224 0 0       0 defined $len or $len = length($p) + length($s) - $from;
3225 0 0       0 unless (defined $ket) {
3226 0         0 warn 'bug in Term::ReadLine::Perl5, please report to its author';
3227 0         0 $ket = '';
3228             }
3229             # We may draw over to put cursor in a correct position:
3230 0 0       0 $ket = '' if $len < length($p) + length($s) - $from; # Not redrawn
3231              
3232 0 0       0 if ($from >= $lp) {
3233 0         0 $p = '';
3234 0         0 my $start = $from - $lp;
3235 0 0       0 if ($start < length($s)) {
3236 0         0 $s = substr $s, $start;
3237 0         0 $lp = 0;
3238             } else {
3239 0         0 return '';
3240             }
3241             } else {
3242 0         0 $p = substr $p, $from;
3243 0         0 $lp -= $from;
3244 0         0 $from = 0;
3245             }
3246 0         0 $s = substr $s, 0, $len - $lp;
3247 0         0 $p =~ s/^(\s*)//; my $bs = $1;
  0         0  
3248 0         0 $p =~ s/(\s*)$//; my $as = $1;
  0         0  
3249 0 0       0 $p = $rl_term_set->[0] . $p . $rl_term_set->[1] if length $p;
3250 0         0 $p = "$bs$p$as";
3251 0 0       0 $ket = chop $s if $ket;
3252 0 0 0     0 if (defined $bsel and $bsel != $esel) {
3253 0 0       0 $bsel = $len if $bsel > $len;
3254 0 0       0 $esel = $len if $esel > $len;
3255             }
3256 0 0 0     0 if (defined $bsel and $bsel != $esel) {
3257 0         0 get_ornaments_selected;
3258 0         0 $bsel -= $lp; $esel -= $lp;
  0         0  
3259 0         0 my ($pre, $sel, $post) =
3260             (substr($s, 0, $bsel),
3261             substr($s, $bsel, $esel-$bsel),
3262             substr($s, $esel));
3263 0 0       0 $pre = $rl_term_set->[2] . $pre . $rl_term_set->[3] if length $pre;
3264 0 0       0 $sel = $rl_term_set->[4] . $sel . $rl_term_set->[5] if length $sel;
3265 0 0       0 $post = $rl_term_set->[2] . $post . $rl_term_set->[3] if length $post;
3266 0         0 $s = "$pre$sel$post"
3267             } else {
3268 0 0       0 $s = $rl_term_set->[2] . $s . $rl_term_set->[3] if length $s;
3269             }
3270              
3271 0 0       0 if (!$lp) { # Should not happen...
    0          
3272 0         0 return $s;
3273             } elsif (!length $s) { # Should not happen
3274 0         0 return $p;
3275             } else { # Do not underline spaces in the prompt
3276 0 0       0 return "$p$s"
3277             . (length $ket ? ($rl_term_set->[0] . $ket . $rl_term_set->[1]) : '');
3278             }
3279             }
3280              
3281             sub redisplay_high {
3282 0     0 0 0 get_ornaments_selected();
3283 0         0 @$rl_term_set[2,3,4,5] = @$rl_term_set[4,5,2,3];
3284             ## Show the line, default inverted.
3285 0         0 rl_redisplay();
3286 0         0 @$rl_term_set[2,3,4,5] = @$rl_term_set[4,5,2,3];
3287 0         0 $force_redraw = 1;
3288             }
3289              
3290             =head3 rl_redisplay
3291              
3292             B
3293              
3294             Updates the screen to reflect the current value of global C<$line>.
3295              
3296             For the purposes of this routine, we prepend the prompt to a local
3297             copy of C<$line> so that we display the prompt as well. We then
3298             modify it to reflect that some characters have different sizes. That
3299             is, control-C is represented as C<^C>, tabs are expanded, etc.
3300              
3301             This routine is somewhat complicated by two-byte characters.... must
3302             make sure never to try do display just half of one.
3303              
3304             This is some nasty code.
3305              
3306             =cut
3307              
3308             sub rl_redisplay()
3309             {
3310 0     0 1 0 my ($thislen, $have_bra);
3311 0         0 my($dline) = $prompt . $line;
3312 0         0 local($D) = $D + length($prompt);
3313 0         0 my ($bsel, $esel);
3314 0 0       0 if (defined pos $line) {
3315 0         0 $bsel = (pos $line) + length $prompt;
3316             }
3317 0         0 my ($have_ket) = '';
3318              
3319             ##
3320             ## If the line contains anything that might require special processing
3321             ## for displaying (such as tabs, control characters, etc.), we will
3322             ## take care of that now....
3323             ##
3324 0 0       0 if ($dline =~ m/[^\x20-\x7e]/)
3325             {
3326 0         0 local($new, $Dinc, $c) = ('', 0);
3327              
3328             ## Look at each character of $dline in turn.....
3329 0         0 for (my $i = 0; $i < length($dline); $i++) {
3330 0         0 $c = substr($dline, $i, 1);
3331              
3332             ## A tab to expand...
3333 0 0       0 if ($c eq "\t") {
    0          
    0          
3334 0         0 $c = ' ' x (8 - (($i-length($prompt)) % 8));
3335              
3336             ## A control character....
3337             } elsif ($c =~ tr/\000-\037//) {
3338 0         0 $c = sprintf("^%c", ord($c)+ord('@'));
3339              
3340             ## the delete character....
3341             } elsif (ord($c) == 127) {
3342 0         0 $c = '^?';
3343             }
3344 0         0 $new .= $c;
3345              
3346             ## Bump over $D if this char is expanded and left of $D.
3347 0 0 0     0 $Dinc += length($c) - 1 if (length($c) > 1 && $i < $D);
3348             ## Bump over $bsel if this char is expanded and left of $bsel.
3349 0 0 0     0 $bsel += length($c) - 1 if (defined $bsel && length($c) > 1 && $i < $bsel);
      0        
3350             }
3351 0         0 $dline = $new;
3352 0         0 $D += $Dinc;
3353             }
3354              
3355             ##
3356             ## Now $dline is what we'd like to display (with a prepended prompt)
3357             ## $D is the position of the cursor on it.
3358             ##
3359             ## If it's too long to fit on the line, we must decide what we can fit.
3360             ##
3361             ## If we end up moving the screen index ($si) [index of the leftmost
3362             ## character on the screen], to some place other than the front of the
3363             ## the line, we'll have to make sure that it's not on the first byte of
3364             ## a 2-byte character, 'cause we'll be placing a '<' marker there, and
3365             ## that would screw up the 2-byte character.
3366             ##
3367             ## $si is preserved between several displays (if possible).
3368             ##
3369             ## Similarly, if the line needs chopped off, we make sure that the
3370             ## placement of the tailing '>' won't screw up any 2-byte character in
3371             ## the vicinity.
3372              
3373             # Now $si keeps the value from previous display
3374 0 0 0     0 if ($D == length($prompt) # If prompts fits exactly, show only if need not show trailing '>'
    0 0        
    0          
    0          
3375             and length($prompt) < $rl_screen_width - (0 != length $dline)) {
3376 0         0 $si = 0; ## prefer displaying the whole prompt
3377             } elsif ($si >= $D) { # point to the left of what was displayed
3378 0         0 $si = &max(0, $D - $rl_margin);
3379 0 0 0     0 $si-- if $si > 0 && $si != length($prompt) && !&OnSecondByte($si);
      0        
3380             } elsif ($si + $rl_screen_width <= $D) { # Point to the right of ...
3381 0         0 $si = &min(length($dline), ($D - $rl_screen_width) + $rl_margin);
3382 0 0 0     0 $si-- if $si > 0 && $si != length($prompt) && !&OnSecondByte($si);
      0        
3383             } elsif (length($dline) - $si < $rl_screen_width - $rl_margin and $si) {
3384             # Too little of the line shown
3385 0         0 $si = &max(0, length($dline) - $rl_screen_width + 3);
3386 0 0 0     0 $si-- if $si > 0 && $si != length($prompt) && !&OnSecondByte($si);
      0        
3387             } else {
3388             ## Fine as-is.... don't need to change $si.
3389             }
3390 0 0       0 $have_bra = 1 if $si != 0; # Need the "chopped-off" marker
3391              
3392 0         0 $thislen = &min(length($dline) - $si, $rl_screen_width);
3393 0 0       0 if ($si + $thislen < length($dline)) {
3394             ## need to place a '>'... make sure to place on first byte.
3395 0 0       0 $thislen-- if &OnSecondByte($si+$thislen-1);
3396 0         0 substr($dline, $si+$thislen-1,1) = '>';
3397 0         0 $have_ket = 1;
3398             }
3399              
3400             ##
3401             ## Now know what to display.
3402             ## Must get substr($dline, $si, $thislen) on the screen,
3403             ## with the cursor at $D-$si characters from the left edge.
3404             ##
3405 0         0 $dline = substr($dline, $si, $thislen);
3406 0         0 $delta = $D - $si; ## delta is cursor distance from beginning of $dline.
3407 0 0       0 if (defined $bsel) { # Highlight the selected part
3408 0         0 $bsel -= $si;
3409 0         0 $esel = $delta;
3410 0 0       0 ($bsel, $esel) = ($esel, $bsel) if $bsel > $esel;
3411 0 0       0 $bsel = 0 if $bsel < 0;
3412 0 0       0 if ($have_ket) {
3413 0 0       0 $esel = $thislen - 1 if $esel > $thislen - 1;
3414             } else {
3415 0 0       0 $esel = $thislen if $esel > $thislen;
3416             }
3417             }
3418 0 0       0 if ($si >= length($prompt)) { # Keep $dline for $lastredisplay...
3419 0 0       0 $prompt = ($have_bra ? "<" : "");
3420 0 0       0 $dline = substr $dline, 1 if length($dline); # After prompt
3421 0 0 0     0 $bsel = 1 if defined $bsel and $bsel == 0;
3422             } else {
3423 0         0 $dline = substr($dline, (length $prompt) - $si);
3424 0         0 $prompt = substr($prompt,$si);
3425 0 0       0 substr($prompt, 0, 1) = '<' if $si > 0;
3426             }
3427             # Now $dline is the part after the prompt...
3428              
3429             ##
3430             ## Now must output $dline, with cursor $delta spaces from left of TTY
3431             ##
3432              
3433 0         0 local ($\, $,) = ('','');
3434              
3435             ##
3436             ## If $force_redraw is not set, we can attempt to optimize the redisplay
3437             ## However, if we don't happen to find an easy way to optimize, we just
3438             ## fall through to the brute-force method of re-drawing the whole line.
3439             ##
3440 0 0 0     0 if (not $force_redraw and not defined $bsel)
3441             {
3442             ## can try to optimize here a bit.
3443              
3444             ## For when we only need to move the cursor
3445 0 0 0     0 if ($lastredisplay eq $dline and $lastpromptlen == length $prompt) {
3446             ## If we need to move forward, just overwrite as far as we need.
3447 0 0       0 if ($lastdelta < $delta) {
    0          
3448 0         0 print $term_OUT
3449             substr_with_props($prompt, $dline,
3450             $lastdelta, $delta-$lastdelta, $have_ket);
3451             ## Need to move back.
3452             } elsif($lastdelta > $delta) {
3453             ## Two ways to move back... use the fastest. One is to just
3454             ## backspace the proper amount. The other is to jump to the
3455             ## the beginning of the line and overwrite from there....
3456 0         0 my $out = substr_with_props($prompt, $dline, 0, $delta, $have_ket);
3457 0 0       0 if ($lastdelta - $delta <= length $out) {
3458 0         0 print $term_OUT "\b" x ($lastdelta - $delta);
3459             } else {
3460 0         0 print $term_OUT "\r", $out;
3461             }
3462             }
3463 0         0 ($lastlen, $lastredisplay, $lastdelta, $lastpromptlen)
3464             = ($thislen, $dline, $delta, length $prompt);
3465             # print $term_OUT "\a"; # Debugging
3466 0         0 return;
3467             }
3468              
3469             ## for when we've just added stuff to the end
3470 0 0 0     0 if ($thislen > $lastlen &&
      0        
      0        
      0        
3471             $lastdelta == $lastlen &&
3472             $delta == $thislen &&
3473             $lastpromptlen == length($prompt) &&
3474             substr($dline, 0, $lastlen - $lastpromptlen) eq $lastredisplay)
3475             {
3476 0         0 print $term_OUT substr_with_props($prompt, $dline,
3477             $lastdelta, undef, $have_ket);
3478             # print $term_OUT "\a"; # Debugging
3479 0         0 ($lastlen, $lastredisplay, $lastdelta, $lastpromptlen)
3480             = ($thislen, $dline, $delta, length $prompt);
3481 0         0 return;
3482             }
3483              
3484             ## There is much more opportunity for optimizing.....
3485             ## something to work on later.....
3486             }
3487              
3488             ##
3489             ## Brute force method of redisplaying... redraw the whole thing.
3490             ##
3491              
3492 0         0 print $term_OUT "\r", substr_with_props($prompt, $dline, 0, undef, $have_ket, $bsel, $esel);
3493 0         0 my $back = length ($dline) + length ($prompt) - $delta;
3494 0 0 0     0 $back += $lastlen - $thislen,
3495             print $term_OUT ' ' x ($lastlen - $thislen) if $lastlen and $lastlen > $thislen;
3496              
3497 0 0       0 if ($back) {
3498 0         0 my $out = substr_with_props($prompt, $dline, 0, $delta, $have_ket, $bsel, $esel);
3499 0 0 0     0 if ($back <= length $out and not defined $bsel) {
3500 0         0 print $term_OUT "\b" x $back;
3501             } else {
3502 0         0 print $term_OUT "\r", $out;
3503             }
3504             }
3505              
3506 0         0 ($lastlen, $lastredisplay, $lastdelta, $lastpromptlen)
3507             = ($thislen, $dline, $delta, length $prompt);
3508              
3509 0         0 $force_redraw = 0;
3510             }
3511              
3512             =head3 redisplay
3513              
3514             B[(I<$prompt>)]
3515              
3516             If an argument I<$prompt> is given, it is used instead of the prompt.
3517             Updates the screen to reflect the current value of global C<$line> via
3518             L.
3519              
3520             =cut
3521              
3522             sub redisplay(;$)
3523             {
3524             ## local $line has prompt also; take that into account with $D.
3525 0 0   0 1 0 local($prompt) = defined($_[0]) ? $_[0] : $prompt;
3526 0 0       0 $prompt = '' unless defined($prompt);
3527 0         0 rl_redisplay();
3528              
3529             }
3530              
3531 0 0   0 0 0 sub min($$) { $_[0] < $_[1] ? $_[0] : $_[1]; }
3532              
3533             sub getc_with_pending {
3534              
3535 0 0   0 0 0 my $key = @Pending ? shift(@Pending) : &$rl_getc;
3536              
3537             # Save keystrokes for vi '.' command
3538 0 0       0 push(@$Dot_buf, $key) if $Dot_buf;
3539              
3540 0         0 $key;
3541             }
3542              
3543             =head3 get_command
3544              
3545             C
3546              
3547             If the C<*keymap>) has an entry for C<$ord_command_char>, it is returned.
3548             Otherwise, the default command in C<$Keymap{'default'}> is returned if that
3549             exists. If C<$Keymap{'default'}> is false, C<'F_Ding'> is returned.
3550              
3551             =cut
3552              
3553             sub get_command
3554             {
3555 0     0 1 0 local *KeyMap = shift;
3556 0         0 my ($key) = @_;
3557             my $cmd = defined($KeyMap[$key]) ? $KeyMap[$key]
3558 0 0 0     0 : ($KeyMap{'default'} || 'F_Ding');
3559 0 0 0     0 if (!defined($cmd) || $cmd eq ''){
3560 0         0 warn "internal error (key=$key)";
3561 0         0 $cmd = 'F_Ding';
3562             }
3563             $cmd
3564 0         0 }
3565              
3566             =head3 do_command
3567              
3568             C
3569              
3570             If the C<*keymap> has an entry for C<$key>, it is executed.
3571             Otherwise, the default command for the keymap is executed.
3572              
3573             =cut
3574              
3575             sub do_command
3576             {
3577 0     0 1 0 my ($keymap, $count, $key) = @_;
3578 0         0 my $cmd = get_command($keymap, $key);
3579              
3580 0         0 local *KeyMap = $keymap; # &$cmd may expect it...
3581 0         0 &$cmd($count, $key);
3582 0         0 $lastcommand = $cmd;
3583             }
3584              
3585             =head3 savestate
3586              
3587             C
3588              
3589             Save whatever state we wish to save as an anonymous array. The only
3590             other function that needs to know about its encoding is
3591             getstate/preserve_state.
3592              
3593             =cut
3594              
3595             sub savestate
3596             {
3597 0     0 1 0 [$D, $si, $LastCommandKilledText, $KillBuffer, $line, @_];
3598             }
3599              
3600             =head3 preserve_state
3601              
3602             C
3603              
3604             =cut
3605              
3606             sub preserve_state {
3607 0 0   0 1 0 return if $Vi_mode;
3608 0 0       0 push(@undo, savestate()), return unless @undo;
3609 0         0 my $last = $undo[-1];
3610 0         0 my @only_movement;
3611 0 0       0 if ( #$last->[1] == $si and $last->[2] eq $LastCommandKilledText
3612             # and $last->[3] eq $KillBuffer and
3613             $last->[4] eq $line ) {
3614             # Only position changed; remove old only-position-changed records
3615 0 0       0 pop @undo if $undo[-1]->[5];
3616 0         0 @only_movement = 1;
3617             }
3618 0         0 push(@undo, savestate(@only_movement));
3619             }
3620              
3621             sub remove_selection {
3622 0 0 0 0 0 0 if ( $rl_first_char && length $line && $rl_default_selected ) {
      0        
3623 0         0 $line = '';
3624 0         0 $D = 0;
3625 0         0 return 1;
3626             }
3627 0 0 0     0 if ($rl_delete_selection and defined pos $line and $D != pos $line) {
      0        
3628 0         0 kill_text(pos $line, $D);
3629 0         0 return 1;
3630             }
3631 0         0 return;
3632             }
3633              
3634 0 0   0 0 0 sub max($$) { $_[0] > $_[1] ? $_[0] : $_[1]; }
3635 0 0   0 0 0 sub isupper($) { ord($_[0]) >= ord('A') && ord($_[0]) <= ord('Z'); }
3636 0 0   0 0 0 sub islower($) { ord($_[0]) >= ord('a') && ord($_[0]) <= ord('z'); }
3637              
3638             =head3 OnSecondByte
3639              
3640             B(I<$index>)
3641              
3642             Returns true if the byte at I<$index> into I<$line> is the second byte
3643             of a two-byte character.
3644              
3645             =cut
3646              
3647             sub OnSecondByte
3648             {
3649 36 100 66 36 1 247 return 0 if !$_rl_japanese_mb || $_[0] == 0 || $_[0] == length($line);
      66        
3650              
3651 33 50       94 die 'internal error' if $_[0] > length($line);
3652              
3653             ##
3654             ## must start looking from the beginning of the line .... can
3655             ## have one- and two-byte characters interspersed, so can't tell
3656             ## without starting from some know location.....
3657             ##
3658 33         99 for (my $i = 0; $i < $_[0]; $i++) {
3659 326 100       1129 next if ord(substr($line, $i, 1)) < 0x80;
3660             ## We have the first byte... must bump up $i to skip past the 2nd.
3661             ## If that one we're skipping past is the index, it should be changed
3662             ## to point to the first byte of the pair (therefore, decremented).
3663 8 100       51 return 1 if ++$i == $_[0];
3664             }
3665 29         242 0; ## seemed to be OK.
3666             }
3667              
3668              
3669             =head3 CharSize
3670              
3671             BC(I<$index>)
3672              
3673             Returns the size of the character at the given I<$index> in the
3674             current line. Most characters are just one byte in length. However,
3675             if the byte at the index and the one after both have the high bit set
3676             and I<$_rl_japanese_mb> is set, those two bytes are one character of
3677             size two.
3678              
3679             Assumes that I<$index> points to the first of a 2-byte char if not
3680             pointing to a 1-byte char.
3681              
3682             TODO: handle Unicode
3683              
3684             =cut
3685              
3686             sub CharSize
3687             {
3688 440     440 1 8748 my $index = shift;
3689 440 100 100     1356 return 2 if $_rl_japanese_mb &&
      66        
3690             ord(substr($line, $index, 1)) >= 0x80 &&
3691             ord(substr($line, $index+1, 1)) >= 0x80;
3692 423         1518 1;
3693             }
3694              
3695             sub GetTTY
3696             {
3697 0     0 0 0 $base_termios = $termios; # make it long enough
3698 0 0       0 &ioctl($term_IN,$TCGETS,$base_termios) || die "Can't ioctl TCGETS: $!";
3699             }
3700              
3701             sub XonTTY
3702             {
3703             # I don't know which of these I actually need to do this to, so we'll
3704             # just cover all bases.
3705              
3706 0     0 0 0 &ioctl($term_IN,$TCXONC,$TCOON); # || die "Can't ioctl TCXONC STDIN: $!";
3707 0         0 &ioctl($term_OUT,$TCXONC,$TCOON); # || die "Can't ioctl TCXONC STDOUT: $!";
3708             }
3709              
3710             sub ___SetTTY
3711             {
3712 0 0   0   0 if ($DEBUG) {
3713 0         0 print "before ResetTTY\n\r";
3714 0         0 system 'stty -a';
3715             }
3716              
3717 0         0 &XonTTY;
3718              
3719 0 0       0 &GetTTY
3720             if !defined($base_termios);
3721              
3722 0         0 @termios = unpack($termios_t,$base_termios);
3723 0         0 $termios[$TERMIOS_IFLAG] |= $TERMIOS_READLINE_ION;
3724 0         0 $termios[$TERMIOS_IFLAG] &= ~$TERMIOS_READLINE_IOFF;
3725 0         0 $termios[$TERMIOS_OFLAG] |= $TERMIOS_READLINE_OON;
3726 0         0 $termios[$TERMIOS_OFLAG] &= ~$TERMIOS_READLINE_OOFF;
3727 0         0 $termios[$TERMIOS_LFLAG] |= $TERMIOS_READLINE_LON;
3728 0         0 $termios[$TERMIOS_LFLAG] &= ~$TERMIOS_READLINE_LOFF;
3729 0         0 $termios[$TERMIOS_VMIN] = 1;
3730 0         0 $termios[$TERMIOS_VTIME] = 0;
3731 0         0 $termios = pack($termios_t,@termios);
3732 0 0       0 &ioctl($term_IN,$TCSETS,$termios) || die "Can't ioctl TCSETS: $!";
3733              
3734 0 0       0 if ($DEBUG) {
3735 0         0 print "after ResetTTY\n\r";
3736 0         0 system 'stty -a';
3737             }
3738             }
3739              
3740             sub normal_tty_mode
3741             {
3742 0 0 0 0 0 0 return if $stdin_not_tty || $dumb_term || !$initialized;
      0        
3743 0         0 &XonTTY;
3744 0 0       0 &GetTTY if !defined($base_termios);
3745 0         0 &ResetTTY;
3746             }
3747              
3748             sub ___ResetTTY
3749             {
3750 0 0   0   0 if ($DEBUG) {
3751 0         0 print "before ResetTTY\n\r";
3752 0         0 system 'stty -a';
3753             }
3754              
3755 0         0 @termios = unpack($termios_t,$base_termios);
3756 0         0 $termios[$TERMIOS_IFLAG] |= $TERMIOS_NORMAL_ION;
3757 0         0 $termios[$TERMIOS_IFLAG] &= ~$TERMIOS_NORMAL_IOFF;
3758 0         0 $termios[$TERMIOS_OFLAG] |= $TERMIOS_NORMAL_OON;
3759 0         0 $termios[$TERMIOS_OFLAG] &= ~$TERMIOS_NORMAL_OOFF;
3760 0         0 $termios[$TERMIOS_LFLAG] |= $TERMIOS_NORMAL_LON;
3761 0         0 $termios[$TERMIOS_LFLAG] &= ~$TERMIOS_NORMAL_LOFF;
3762 0         0 $termios = pack($termios_t,@termios);
3763 0 0       0 &ioctl($term_IN,$TCSETS,$termios) || die "Can't ioctl TCSETS: $!";
3764              
3765 0 0       0 if ($DEBUG) {
3766 0         0 print "after ResetTTY\n\r";
3767 0         0 system 'stty -a';
3768             }
3769             }
3770              
3771             =head3 WordBreak
3772              
3773             C
3774              
3775             Returns true if the character at I into $line is a basic word
3776             break character, false otherwise.
3777              
3778             =cut
3779              
3780             sub WordBreak
3781             {
3782 147     147 1 711 index($rl_basic_word_break_characters,
3783             substr($line,$_[0],1)) != -1;
3784             }
3785              
3786             sub getstate
3787             {
3788 0     0 0 0 ($D, $si, $LastCommandKilledText, $KillBuffer, $line) = @{$_[0]};
  0         0  
3789 0         0 $ThisCommandKilledText = $LastCommandKilledText;
3790             }
3791              
3792             =head3 kill_text
3793              
3794             kills from D=$_[0] to $_[1] (to the killbuffer if $_[2] is true)
3795              
3796             =cut
3797              
3798             sub kill_text
3799             {
3800 0     0 1 0 my($from, $to, $save) = (&min($_[0], $_[1]), &max($_[0], $_[1]), $_[2]);
3801 0         0 my $len = $to - $from;
3802 0 0       0 if ($save) {
3803 0 0       0 $KillBuffer = '' if !$LastCommandKilledText;
3804 0 0       0 if ($from < $LastCommandKilledText - 1) {
3805 0         0 $KillBuffer = substr($line, $from, $len) . $KillBuffer;
3806             } else {
3807 0         0 $KillBuffer .= substr($line, $from, $len);
3808             }
3809 0         0 $ThisCommandKilledText = 1 + $from;
3810             }
3811 0         0 substr($line, $from, $len) = '';
3812              
3813             ## adjust $D
3814 0 0       0 if ($D > $from) {
3815 0         0 $D -= $len;
3816 0 0       0 $D = $from if $D < $from;
3817             }
3818             }
3819              
3820              
3821             =head3 at_end_of_line
3822              
3823             Returns true if $D at the end of the line.
3824              
3825             =cut
3826              
3827             sub at_end_of_line
3828             {
3829 321     321 1 1387 ($D + &CharSize($D)) == (length($line) + 1);
3830             }
3831              
3832             =head3 changecase
3833              
3834             changecase($count, $up_down_caps)
3835              
3836             Translated from GNU's I.
3837              
3838             If I<$up_down_caps> is 'up' to upcase I<$count> words;
3839             'down' to downcase them, or something else to capitalize them.
3840              
3841             If I<$count> is negative, the dot is not moved.
3842              
3843             =cut
3844              
3845             sub changecase
3846             {
3847 6     6 1 13 my $op = $_[1];
3848              
3849 6         12 my ($start, $state, $c, $olddot) = ($D, 0);
3850 6 50       16 if ($_[0] < 0)
3851             {
3852 0         0 $olddot = $D;
3853 0         0 $_[0] = -$_[0];
3854             }
3855              
3856 6         16 &F_ForwardWord; ## goes forward $_[0] words.
3857              
3858 6         13 while ($start < $D) {
3859 45         65 $c = substr($line, $start, 1);
3860              
3861 45 100       73 if ($op eq 'up') {
    100          
3862 15         20 $c = uc $c;
3863             } elsif ($op eq 'down') {
3864 15         19 $c = lc $c;
3865             } else { ## must be 'cap'
3866 15 100       26 if ($state == 1) {
3867 6         9 $c = lc $c;
3868             } else {
3869 9         15 $c = uc $c;
3870 9         10 $state = 1;
3871             }
3872 15 100       26 $state = 0 if $c !~ tr/a-zA-Z//;
3873             }
3874              
3875 45         58 substr($line, $start, 1) = $c;
3876 45         70 $start++;
3877             }
3878 6 50       19 $D = $olddot if defined($olddot);
3879             }
3880              
3881             =head3 search
3882              
3883             search($position, $string)
3884              
3885             Checks if $string is at position I<$rl_History[$position]> and returns
3886             I<$position> if found or -1 if not found.
3887              
3888             This is intended to be the called first in a potentially repetitive
3889             search, which is why the unusual return value. See also
3890             L.
3891              
3892             =cut
3893              
3894             sub search($$) {
3895 0     0 1 0 my ($i, $str) = @_;
3896 0 0 0     0 return -1 if $i < 0 || $i > $#rl_History; ## for safety
3897 0         0 while (1) {
3898 0 0       0 return $i if rindex($rl_History[$i], $str) >= 0;
3899 0 0       0 if ($reverse) {
3900 0 0       0 return -1 if $i-- == 0;
3901             } else {
3902 0 0       0 return -1 if $i++ == $#rl_History;
3903             }
3904             }
3905             }
3906              
3907             sub DoSearch
3908             {
3909 0     0 0 0 local $reverse = shift; # Used in search()
3910 0         0 my $oldline = $line;
3911 0         0 my $oldD = $D;
3912 0         0 my $tmp;
3913              
3914 0         0 my $searchstr = ''; ## string we're searching for
3915 0         0 my $I = -1; ## which history line
3916              
3917 0         0 $si = 0;
3918              
3919 0         0 while (1)
3920             {
3921 0 0       0 if ($I != -1) {
3922 0         0 $line = $rl_History[$I];
3923 0         0 $D += index($rl_History[$I], $searchstr);
3924             }
3925 0 0       0 redisplay( '('.($reverse?'reverse-':'') ."i-search) `$searchstr': ");
3926              
3927 0         0 $c = &getc_with_pending;
3928 0 0 0     0 if (($KeyMap[ord($c)] || 0) eq 'F_ReverseSearchHistory') {
    0 0        
    0 0        
    0          
3929 0 0 0     0 if ($reverse && $I != -1) {
3930 0 0       0 if ($tmp = &search($I-1,$searchstr), $tmp >= 0) {
3931 0         0 $I = $tmp;
3932             } else {
3933 0         0 &F_Ding;
3934             }
3935             }
3936 0         0 $reverse = 1;
3937             } elsif (($KeyMap[ord($c)] || 0) eq 'F_ForwardSearchHistory') {
3938 0 0 0     0 if (!$reverse && $I != -1) {
3939 0 0       0 if ($tmp = &search($I+1,$searchstr), $tmp >= 0) {
3940 0         0 $I = $tmp;
3941             } else {
3942 0         0 &F_Ding;
3943             }
3944             }
3945 0         0 $reverse = 0;
3946             } elsif ($c eq "\007") { ## abort search... restore line and return
3947 0         0 $line = $oldline;
3948 0         0 $D = $oldD;
3949 0         0 return;
3950             } elsif (ord($c) < 32 || ord($c) > 126) {
3951 0 0       0 push(@Pending, $c) if $c ne "\e";
3952 0 0       0 if ($I < 0) {
3953             ## just restore
3954 0         0 $line = $oldline;
3955 0         0 $D = $oldD;
3956             } else {
3957             #chose this line
3958 0         0 $line = $rl_History[$I];
3959 0         0 $D = index($rl_History[$I], $searchstr);
3960             }
3961 0         0 rl_redisplay();
3962 0         0 last;
3963             } else {
3964             ## Add this character to the end of the search string and
3965             ## see if that'll match anything.
3966 0 0       0 $tmp = &search($I < 0 ? $rl_HistoryIndex-$reverse: $I, $searchstr.$c);
3967 0 0       0 if ($tmp == -1) {
3968 0         0 &F_Ding;
3969             } else {
3970 0         0 $searchstr .= $c;
3971 0         0 $I = $tmp;
3972             }
3973             }
3974             }
3975             }
3976              
3977             =head3 search
3978              
3979             searchStart($position, $reverse, $string)
3980              
3981             I<$reverse> should be either +1, or -1;
3982              
3983             Checks if $string is at position I<$rl_History[$position+$reverse]> and
3984             returns I<$position> if found or -1 if not found.
3985              
3986             This is intended to be the called first in a potentially repetitive
3987             search, which is why the unusual return value. See also L.
3988              
3989             =cut
3990              
3991             sub searchStart($$$) {
3992 0     0 0 0 my ($i, $reverse, $str) = @_;
3993 0 0       0 $i += $reverse ? - 1: +1;
3994 0 0 0     0 return -1 if $i < 0 || $i > $#rl_History; ## for safety
3995 0         0 while (1) {
3996 0 0       0 return $i if index($rl_History[$i], $str) == 0;
3997 0 0       0 if ($reverse) {
3998 0 0       0 return -1 if $i-- == 0;
3999             } else {
4000 0 0       0 return -1 if $i++ == $#rl_History;
4001             }
4002             }
4003             }
4004              
4005             sub DoSearchStart
4006             {
4007 0     0 0 0 my ($reverse,$what) = @_;
4008 0         0 my $i = searchStart($rl_HistoryIndex, $reverse, $what);
4009 0 0       0 return if $i == -1;
4010 0         0 $rl_HistoryIndex = $i;
4011 0         0 ($D, $line) = (0, $rl_History[$rl_HistoryIndex]);
4012 0         0 F_BeginningOfLine();
4013 0         0 F_ForwardChar(length($what));
4014              
4015             }
4016              
4017             ###########################################################################
4018             ###########################################################################
4019              
4020             =head3 TextInsert
4021              
4022             C
4023              
4024             =cut
4025              
4026             sub TextInsert {
4027 0     0 1 0 my $count = shift;
4028 0         0 my $text2add = shift(@_) x $count;
4029 0 0       0 if ($InsertMode) {
4030 0         0 substr($line,$D,0) .= $text2add;
4031             } else {
4032 0         0 substr($line,$D,length($text2add)) = $text2add;
4033             }
4034 0         0 $D += length($text2add);
4035             }
4036              
4037             =head3 complete_internal
4038              
4039             The meat of command completion. Patterned closely after GNU's.
4040              
4041             The supposedly partial word at the cursor is "completed" as per the
4042             single argument:
4043             "\t" complete as much of the word as is unambiguous
4044             "?" list possibilities.
4045             "*" replace word with all possibilities. (who would use this?)
4046              
4047             A few notable variables used:
4048             $rl_completer_word_break_characters
4049             -- characters in this string break a word.
4050             $rl_special_prefixes
4051             -- but if in this string as well, remain part of that word.
4052              
4053             Returns true if a completion was done, false otherwise, so vi completion
4054             routines can test it.
4055              
4056             =cut
4057              
4058             sub complete_internal
4059              
4060             {
4061 0     0 1 0 my $what_to_do = shift;
4062 0         0 my ($point, $end) = ($D, $D);
4063              
4064             # In vi mode, complete if the cursor is at the *end* of a word, not
4065             # after it.
4066 0 0       0 ($point++, $end++) if $Vi_mode;
4067              
4068 0 0       0 if ($point)
4069             {
4070             ## Not at the beginning of the line; Isolate the word to be completed.
4071 0   0     0 1 while (--$point && (-1 == index($rl_completer_word_break_characters,
4072             substr($line, $point, 1))));
4073              
4074             # Either at beginning of line or at a word break.
4075             # If at a word break (that we don't want to save), skip it.
4076 0 0 0     0 $point++ if (
4077             (index($rl_completer_word_break_characters,
4078             substr($line, $point, 1)) != -1) &&
4079             (index($rl_special_prefixes, substr($line, $point, 1)) == -1)
4080             );
4081             }
4082              
4083 0         0 my $text = substr($line, $point, $end - $point);
4084 0         0 $rl_completer_terminator_character = ' ';
4085 0         0 my @matches =
4086             &completion_matches($rl_completion_function,$text,$line,$point);
4087              
4088 0 0       0 if (@matches == 0) {
    0          
    0          
    0          
4089 0         0 return &F_Ding;
4090             } elsif ($what_to_do eq "\t") {
4091 0         0 my $replacement = shift(@matches);
4092 0 0 0     0 $replacement .= $rl_completer_terminator_character
4093             if @matches == 1 && !$rl_completion_suppress_append;
4094 0 0       0 &F_Ding if @matches != 1;
4095 0 0       0 if ($var_TcshCompleteMode) {
4096 0         0 @tcsh_complete_selections = (@matches, $text);
4097 0         0 $tcsh_complete_start = $point;
4098 0         0 $tcsh_complete_len = length($replacement);
4099             }
4100 0 0       0 if ($replacement ne '') {
4101 0         0 substr($line, $point, $end-$point) = $replacement;
4102 0         0 $D = $D - ($end - $point) + length($replacement);
4103             }
4104             } elsif ($what_to_do eq '?') {
4105 0         0 shift(@matches); ## remove prepended common prefix
4106 0         0 local $\ = '';
4107 0         0 print $term_OUT "\n\r";
4108             # print "@matches\n\r";
4109 0         0 &pretty_print_list (@matches);
4110 0         0 $force_redraw = 1;
4111             } elsif ($what_to_do eq '*') {
4112 0         0 shift(@matches); ## remove common prefix.
4113 0         0 local $" = $rl_completer_terminator_character;
4114 0         0 my $replacement = "@matches$rl_completer_terminator_character";
4115 0         0 substr($line, $point, $end-$point) = $replacement; ## insert all.
4116 0         0 $D = $D - ($end - $point) + length($replacement);
4117             } else {
4118 0         0 warn "\r\n[Internal error]";
4119 0         0 return &F_Ding;
4120             }
4121              
4122 0         0 1;
4123             }
4124              
4125             =head3 use_basic_commands
4126              
4127             use_basic_commands($text, $line, $start);
4128              
4129             Used as a completion function by I<&rl_basic_commands>. Return items
4130             from I<@rl_basic_commands> that start with the pattern in I<$text>.
4131              
4132             I<$start> should be 0, signifying matching from the beginning of the
4133             line, for this to work. Otherwise we return the empty list. I<$line>
4134             is ignored, but needs to be there in to match the completion-function
4135             API.
4136              
4137             =cut
4138              
4139             sub use_basic_commands($$$) {
4140 0     0 1 0 my ($text, $line, $start) = @_;
4141 0 0       0 return () if $start != 0;
4142 0         0 grep(/^$text/, @rl_basic_commands);
4143             }
4144              
4145             =head3 completion_matches
4146              
4147             completion_matches(func, text, line, start)
4148              
4149             I is a function to call as
4150              
4151             func($text, $line, $start)
4152              
4153             where I<$text> is the item to be completed,
4154             I<$line> is the whole command line, and
4155             I<$start> is the starting index of I<$text> in I<$line>.
4156             The function I<$func> should return a list of items that might match.
4157              
4158             completion_matches will return that list, with the longest common
4159             prefix prepended as the first item of the list. Therefore, the list
4160             will either be of zero length (meaning no matches) or of 2 or more.....
4161              
4162             =cut
4163              
4164             sub completion_matches
4165             {
4166 0     0 1 0 my ($func, $text, $line, $start) = @_;
4167              
4168             ## get the raw list
4169 0         0 my @matches;
4170              
4171             #print qq/\r\neval("\@matches = &$func(\$text, \$line, \$start)\n\r/;#DEBUG
4172             #eval("\@matches = &$func(\$text, \$line, \$start);1") || warn "$@ ";
4173              
4174 0         0 @matches = &$func($text, $line, $start);
4175              
4176             ## if anything returned , find the common prefix among them
4177 0 0       0 if (@matches) {
4178 0         0 my $prefix = $matches[0];
4179 0         0 my $len = length($prefix);
4180 0         0 for (my $i = 1; $i < @matches; $i++) {
4181 0 0       0 next if substr($matches[$i], 0, $len) eq $prefix;
4182 0         0 $prefix = substr($prefix, 0, --$len);
4183 0 0       0 last if $len == 0;
4184 0         0 $i--; ## retry this one to see if the shorter one matches.
4185             }
4186 0         0 unshift(@matches, $prefix); ## make common prefix the first thing.
4187             }
4188 0         0 @matches;
4189             }
4190              
4191             $have_getpwent = eval{
4192             my @fields = getpwent(); setpwent(); 1;
4193             };
4194              
4195             sub rl_tilde_expand($) {
4196 1     1 0 6 my $prefix = shift;
4197 1         4 my @matches = ();
4198 1         18 setpwent();
4199 1         64 while (my @fields = (getpwent)[0]) {
4200 23 100 66     1243 push @matches, $fields[0]
4201             if ( $prefix eq ''
4202             || $prefix eq substr($fields[0], 0, length($prefix)) );
4203             }
4204 1         12 setpwent();
4205 1         9 @matches;
4206             }
4207              
4208             sub tilde_complete($) {
4209 1     1 0 11 my $prefix = shift;
4210 1 50       9 return $prefix unless $have_getpwent;
4211 1         11 my @names = rl_tilde_expand($prefix);
4212 1 50       10 if (scalar @names == 1) {
4213 1         73 (getpwnam($names[0]))[7];
4214             } else {
4215 0         0 map {'~' . $_} @names;
  0         0  
4216             }
4217             }
4218              
4219             =head3 pretty_print_list
4220              
4221             Print an array in columns like ls -C. Originally based on stuff
4222             (lsC2.pl) by utashiro@sran230.sra.co.jp (Kazumasa Utashiro).
4223              
4224             See L for a more flexible and more general routine.
4225              
4226             =cut
4227              
4228             sub pretty_print_list
4229             {
4230 0     0 1 0 my @list = @_;
4231 0 0       0 return unless @list;
4232 0         0 my ($lines, $columns, $mark, $index);
4233              
4234             ## find width of widest entry
4235 0         0 my $maxwidth = 0;
4236 0   0     0 grep(length > $maxwidth && ($maxwidth = length), @list);
4237 0         0 $maxwidth++;
4238              
4239 0 0       0 $columns = $maxwidth >= $rl_screen_width
4240             ? 1 : int($rl_screen_width / $maxwidth);
4241              
4242             ## if there's enough margin to interspurse among the columns, do so.
4243 0         0 $maxwidth += int(($rl_screen_width % $maxwidth) / $columns);
4244              
4245 0         0 $lines = int((@list + $columns - 1) / $columns);
4246 0         0 $columns-- while ((($lines * $columns) - @list + 1) > $lines);
4247              
4248 0         0 $mark = $#list - $lines;
4249 0         0 local $\ = '';
4250 0         0 for ($l = 0; $l < $lines; $l++) {
4251 0         0 for ($index = $l; $index <= $mark; $index += $lines) {
4252 0         0 printf("%-$ {maxwidth}s", $list[$index]);
4253             }
4254 0 0       0 print $term_OUT $list[$index] if $index <= $#list;
4255 0         0 print $term_OUT "\n\r";
4256             }
4257             }
4258              
4259             sub start_dot_buf {
4260 0     0 0 0 my($count, $ord) = @_;
4261 0         0 $Dot_buf = [pack('c', $ord)];
4262 0 0       0 unshift(@$Dot_buf, split(//, $count)) if $count > 1;
4263 0         0 $Dot_state = savestate();
4264             }
4265              
4266             sub end_dot_buf {
4267             # We've recognized an editing command
4268              
4269             # Save the command keystrokes for use by '.'
4270 0     0 0 0 $Last_vi_command = $Dot_buf;
4271 0         0 undef $Dot_buf;
4272              
4273             # Save the pre-command state for use by 'u' and 'U';
4274 0         0 $Vi_undo_state = $Dot_state;
4275 0 0       0 $Vi_undo_all_state = $Dot_state if !$Vi_undo_all_state;
4276              
4277             # Make sure the current line is treated as new line for history purposes.
4278 0         0 $rl_HistoryIndex = $#rl_History + 1;
4279             }
4280              
4281             sub save_dot_buf {
4282 0     0 0 0 &start_dot_buf(@_);
4283 0         0 &end_dot_buf;
4284             }
4285              
4286             sub do_delete {
4287              
4288 0     0 0 0 my($count, $ord, $poshash) = @_;
4289              
4290 0         0 my $other_end = &get_position($count, undef, $ord, $poshash);
4291 0 0       0 return &F_Ding if !defined $other_end;
4292              
4293 0 0       0 if ($other_end < 0) {
4294             # dd - delete entire line
4295 0         0 &kill_text(0, length($line), 1);
4296             }
4297             else {
4298 0         0 &kill_text($D, $other_end, 1);
4299             }
4300              
4301 0         0 1; # True return value
4302             }
4303              
4304             =head3 get_position
4305              
4306             get_position($count, $ord, $fulline_ord, $poshash)
4307              
4308             Interpret vi positioning commands
4309              
4310             =cut
4311              
4312             sub get_position {
4313 0     0 1 0 my ($count, $ord, $fullline_ord, $poshash) = @_;
4314              
4315             # Manipulate a copy of the cursor, not the real thing
4316 0         0 local $D = $D;
4317              
4318             # $ord (first character of positioning command) is an optional argument.
4319 0 0       0 $ord = ord(&getc_with_pending) if !defined $ord;
4320              
4321             # Detect double character (for full-line operation, e.g. dd)
4322 0 0 0     0 return -1 if defined $fullline_ord and $ord == $fullline_ord;
4323              
4324 0         0 my $re = $poshash->{$ord};
4325              
4326 0 0       0 if ($re) {
4327 0         0 my $c = pack('c', $ord);
4328 0 0       0 if (lc($c) eq 'b') {
4329 0         0 &backward_scan($count, $re);
4330             }
4331             else {
4332 0         0 &forward_scan($count, $re);
4333             }
4334             }
4335             else {
4336             # Move the local copy of the cursor
4337 0         0 &do_command($var_EditingMode{'vipos'}, $count, $ord);
4338             }
4339              
4340             # Return the new cursor (undef if illegal command)
4341 0         0 $D;
4342             }
4343              
4344             sub forward_scan {
4345 0     0 0 0 my($count, $re) = @_;
4346 0         0 while ($count--) {
4347 0 0       0 last unless substr($line, $D) =~ m{^($re)};
4348 0         0 $D += length($1);
4349             }
4350             }
4351              
4352             sub backward_scan {
4353 0     0 0 0 my($count, $re) = @_;
4354 0         0 while ($count--) {
4355 0 0       0 last unless substr($line, 0, $D) =~ m{($re)$};
4356 0         0 $D -= length($1);
4357             }
4358             }
4359              
4360             sub get_line_from_history($) {
4361 0     0 0 0 my($n) = @_;
4362 0 0 0     0 return &F_Ding if $n < 0 or $n > @rl_History;
4363 0 0       0 return if $n == $rl_HistoryIndex;
4364              
4365             # If we're moving from the currently-edited line, save it for later.
4366 0 0       0 $line_for_revert = $line if $rl_HistoryIndex == @rl_History;
4367              
4368             # Get line from history buffer (or from saved edit line).
4369 0 0       0 $line = ($n == @rl_History) ? $line_for_revert : $rl_History[$n];
4370 0 0       0 $D = $Vi_mode ? 0 : length $line;
4371              
4372             # Subsequent 'U' will bring us back to this point.
4373 0 0       0 $Vi_undo_all_state = savestate() if $Vi_mode;
4374              
4375 0         0 $rl_HistoryIndex = $n;
4376             }
4377              
4378             # Redisplay the line, without attempting any optimization
4379             sub rl_forced_update_display() {
4380 0     0 0 0 local $force_redraw = 1;
4381 0         0 redisplay(@_);
4382             }
4383              
4384             ## returns a new $i or -1 if not found.
4385             sub vi_search {
4386 0     0 0 0 my ($i) = @_;
4387 0 0 0     0 return -1 if $i < 0 || $i > $#rl_History; ## for safety
4388 0         0 while (1) {
4389 0 0       0 return $i if $rl_History[$i] =~ /$Vi_search_re/;
4390 0 0       0 if ($reverse) {
4391 0 0       0 return -1 if $i-- == 0;
4392             } else {
4393 0 0       0 return -1 if $i++ == $#rl_History;
4394             }
4395             }
4396             }
4397              
4398             sub do_vi_search {
4399 0 0   0 0 0 my $incr = $reverse ? -1 : 1;
4400              
4401 0         0 my $i = &vi_search($rl_HistoryIndex + $incr);
4402 0 0       0 return &F_Ding if $i < 0; # Not found.
4403              
4404 0         0 $rl_HistoryIndex = $i;
4405 0         0 ($D, $line) = (0, $rl_History[$rl_HistoryIndex]);
4406             }
4407              
4408             # Using local $line, $D, and $prompt, get and return the string to
4409             # search for.
4410             sub get_vi_search_str($) {
4411 0     0 0 0 my($c) = @_;
4412              
4413 0         0 local $prompt = $prompt . $c;
4414 0         0 local ($line, $D) = ('', 0);
4415 0         0 rl_redisplay();
4416              
4417             # Gather a search string in our local $line.
4418 0         0 while ($lastcommand ne 'F_ViEndSearch') {
4419 0         0 &do_command($var_EditingMode{'visearch'}, 1, ord(&getc_with_pending));
4420 0         0 rl_redisplay();
4421              
4422             # We've backspaced past beginning of line
4423 0 0       0 return undef if !defined $line;
4424             }
4425 0         0 $line;
4426             }
4427              
4428             sub vi_input_mode()
4429             {
4430 0     0 0 0 $InsertMode = 1;
4431 0         0 $var_EditingMode = $var_EditingMode{'vi'};
4432 0         0 $Vi_mode = 1;
4433             }
4434              
4435             sub clipboard_set($) {
4436 0     0 0 0 my $in = shift;
4437 0 0       0 if ($^O eq 'os2') {
    0          
4438 0 0       0 eval {
4439 0         0 require OS2::Process;
4440 0         0 OS2::Process::ClipbrdText_set($in); # Do not disable \r\n-conversion
4441 0         0 1
4442             } and return;
4443             } elsif ($^O eq 'MSWin32') {
4444 0 0       0 eval {
4445 0         0 require Win32::Clipboard;
4446 0         0 Win32::Clipboard::Set($in);
4447 0         0 1
4448             } and return;
4449             }
4450 0         0 my $mess;
4451 0 0       0 if ($ENV{RL_CLCOPY_CMD}) {
    0          
4452 0         0 $mess = "Writing to pipe `$ENV{RL_CLCOPY_CMD}'";
4453 0 0       0 open COPY, "| $ENV{RL_CLCOPY_CMD}" or warn("$mess: $!"), return;
4454             } elsif (defined $HOME) {
4455 0         0 my $cutpastefile = File::Spec($HOME, '.rl_cutandpaste');
4456 0         0 $mess = "Writing to file `$cutpastefile'";
4457 0 0       0 open COPY, "> $cutpastefile" or warn("$mess: $!"), return;
4458             } else {
4459 0         0 return;
4460             }
4461 0         0 print COPY $in;
4462 0 0       0 close COPY or warn("$mess: closing $!");
4463             }
4464              
4465             =head3 read_an_init_file
4466              
4467             B(I, [I])
4468              
4469             Reads and executes I which does things like Sets input
4470             key bindings in key maps.
4471              
4472             If there was a problem return 0. Otherwise return 1;
4473              
4474             =cut
4475              
4476             sub read_an_init_file($;$)
4477             {
4478 15     15 1 51 my $file = shift;
4479 15 50       83 my $include_depth = shift or 0;
4480 15         46 my $rc;
4481              
4482 15 100       576 $file = File::Spec->catfile($HOME, $file) unless -f $file;
4483 15 100       607 return 0 unless open $rc, "< $file";
4484 1         11 local (@action) = ('exec'); ## exec, skip, ignore (until appropriate endnif)
4485 1         6 local (@level) = (); ## if, else
4486              
4487 1         10 local $/ = "\n";
4488 1         18 while (my $line = <$rc>) {
4489 11         35 parse_and_bind($line, $file, $include_depth);
4490             }
4491 1         11 close($rc);
4492 1         10 return 1;
4493             }
4494              
4495             =head1 SEE ALSO
4496              
4497             L
4498              
4499             =cut
4500              
4501             1;