/* A simplified loop for vi. Don't dispatch key at end. Don't recognize minus sign? Should this do rl_save_prompt/rl_restore_prompt? */ static int rl_digit_loop1(void) { int key, c; RL_SETSTATE(RL_STATE_NUMERICARG); while (1) { if (rl_numeric_arg > 1000000) { rl_explicit_arg = rl_numeric_arg = 0; rl_ding (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); return 1; } rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); RL_SETSTATE(RL_STATE_MOREINPUT); key = c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { rl_numeric_arg *= 4; continue; } c = UNMETA (c); if (_rl_digit_p (c)) { if (rl_explicit_arg) rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); else rl_numeric_arg = _rl_digit_value (c); rl_explicit_arg = 1; } else { rl_clear_message (); rl_stuff_char (key); break; } } RL_UNSETSTATE(RL_STATE_NUMERICARG); return (0); }
void _rl_vi_initialize_line () { register int i; for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) vi_mark_chars[i] = -1; RL_UNSETSTATE(RL_STATE_VICMDONCE); }
/* How to abort things. */ int _rl_abort_internal (void) { rl_ding (); rl_clear_message (); _rl_reset_argument (); rl_clear_pending_input (); RL_UNSETSTATE (RL_STATE_MACRODEF); while (rl_executing_macro) _rl_pop_executing_macro (); RL_UNSETSTATE (RL_STATE_MULTIKEY); /* XXX */ rl_last_func = (rl_command_func_t *)NULL; _rl_longjmp (_rl_top_level, 1); return (0); }
int rl_vi_char_search(int count, int key) { #if defined(HANDLE_MULTIBYTE) static char *target; static int mb_len; #else static char target; #endif static int orig_dir, dir; if ((key == ';') || (key == ',')) dir = ((key == ';') ? orig_dir : -orig_dir); else { if (vi_redoing) #if defined(HANDLE_MULTIBYTE) target = _rl_vi_last_search_mbchar; #else target = (char)_rl_vi_last_search_char; #endif else { #if defined(HANDLE_MULTIBYTE) mb_len = _rl_read_mbchar(_rl_vi_last_search_mbchar, MB_LEN_MAX); target = _rl_vi_last_search_mbchar; #else RL_SETSTATE(RL_STATE_MOREINPUT); _rl_vi_last_search_char = target = (char)rl_read_key(); RL_UNSETSTATE(RL_STATE_MOREINPUT); #endif } switch (key) { case 't': orig_dir = dir = FTO; break; case 'T': orig_dir = dir = BTO; break; case 'f': orig_dir = dir = FFIND; break; case 'F': orig_dir = dir = BFIND; break; default: break; } }
int _rl_arg_getchar () { int c; rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); return c; }
int _rl_arg_overflow () { if (rl_numeric_arg > 1000000) { _rl_argcxt = 0; rl_explicit_arg = rl_numeric_arg = 0; rl_ding (); rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); return 1; } return 0; }
/* Stop defining a keyboard macro. A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */ int rl_end_kbd_macro (int count, int ignore) { if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) { _rl_abort_internal (); return 1; } current_macro_index -= rl_key_sequence_length; current_macro[current_macro_index] = '\0'; RL_UNSETSTATE(RL_STATE_MACRODEF); return (rl_call_last_kbd_macro (--count, 0)); }
void _rl_kill_kbd_macro (void) { if (current_macro) { xfree (current_macro); current_macro = (char *) NULL; } current_macro_size = current_macro_index = 0; FREE (rl_executing_macro); rl_executing_macro = (char *) NULL; executing_macro_index = 0; RL_UNSETSTATE(RL_STATE_MACRODEF); }
/* Discard the current macro, replacing it with the one on the top of the stack of saved macros. */ void _rl_pop_executing_macro (void) { struct saved_macro *macro; FREE (rl_executing_macro); rl_executing_macro = (char *)NULL; executing_macro_index = 0; if (macro_list) { macro = macro_list; rl_executing_macro = macro_list->string; executing_macro_index = macro_list->sindex; macro_list = macro_list->next; xfree (macro); } macro_level--; if (rl_executing_macro == 0) RL_UNSETSTATE(RL_STATE_MACROINPUT); }
int _rl_arg_callback (_rl_arg_cxt cxt) { int c, r; c = _rl_arg_getchar (); if (c < 0) return (1); /* EOF */ if (_rl_argcxt & NUM_READONE) { _rl_argcxt &= ~NUM_READONE; rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); rl_execute_next (c); return 0; } r = _rl_arg_dispatch (cxt, c); if (r > 0) rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); return (r != 1); }
//------------------------------------------------------------------------------ static void simulate_sigwinch(COORD expected_cursor_pos) { // In the land of POSIX a terminal would raise a SIGWINCH signal when it is // resized. See rl_sigwinch_handler() in readline/signal.c. extern int _rl_vis_botlin; extern int _rl_last_v_pos; CONSOLE_SCREEN_BUFFER_INFO csbi; rl_voidfunc_t* redisplay_func_cache; int base_y; int bottom_line; HANDLE handle; bottom_line = _rl_vis_botlin - 1; handle = GetStdHandle(STD_OUTPUT_HANDLE); // Cache redisplay function. Need original as it handles redraw correctly. redisplay_func_cache = rl_redisplay_function; rl_redisplay_function = rl_redisplay; // Cursor may be out of sync with where Readline expects the cursor to be. // Put it back where it was, clamping if necessary. GetConsoleScreenBufferInfo(handle, &csbi); if (expected_cursor_pos.X >= csbi.dwSize.X) { expected_cursor_pos.X = csbi.dwSize.X - 1; } if (expected_cursor_pos.Y >= csbi.dwSize.Y) { expected_cursor_pos.Y = csbi.dwSize.Y - 1; } SetConsoleCursorPosition(handle, expected_cursor_pos); // Let Readline handle the buffer resize. RL_SETSTATE(RL_STATE_SIGHANDLER); rl_resize_terminal(); RL_UNSETSTATE(RL_STATE_SIGHANDLER); rl_redisplay_function = redisplay_func_cache; // Now some redraw edge cases need to be handled. GetConsoleScreenBufferInfo(handle, &csbi); base_y = csbi.dwCursorPosition.Y - _rl_last_v_pos; if (bottom_line > _rl_vis_botlin) { // Readline SIGWINCH handling assumes that at most one line needs to // be cleared which is not the case when resizing from small to large // widths. CHAR_INFO fill; SMALL_RECT rect; COORD coord; rect.Left = 0; rect.Right = csbi.dwSize.X; rect.Top = base_y + _rl_vis_botlin + 1; rect.Bottom = base_y + bottom_line; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; coord.X = rect.Right + 1; coord.Y = rect.Top; ScrollConsoleScreenBuffer(handle, &rect, NULL, coord, &fill); } else { // Readline never writes to the last column as it wraps the cursor. The // last column will have noise when making the width smaller. Clear it. CHAR_INFO fill; SMALL_RECT rect; COORD coord; rect.Left = rect.Right = csbi.dwSize.X - 1; rect.Top = base_y; rect.Bottom = base_y + _rl_vis_botlin; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; coord.X = rect.Right + 1; coord.Y = rect.Top; ScrollConsoleScreenBuffer(handle, &rect, NULL, coord, &fill); } }
/* Process C as part of the current numeric argument. Return -1 if the argument should be aborted, 0 if we should not read any more chars, and 1 if we should continue to read chars. */ int _rl_arg_dispatch (_rl_arg_cxt cxt, int c) { int key, r; key = c; /* If we see a key bound to `universal-argument' after seeing digits, it ends the argument but is otherwise ignored. */ if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) { if ((cxt & NUM_SAWDIGITS) == 0) { rl_numeric_arg *= 4; return 1; } else if (RL_ISSTATE (RL_STATE_CALLBACK)) { _rl_argcxt |= NUM_READONE; return 0; /* XXX */ } else { RL_SETSTATE(RL_STATE_MOREINPUT); key = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); if (key < 0) return -1; return (_rl_dispatch (key, _rl_keymap)); } } c = UNMETA (c); if (_rl_digit_p (c)) { r = _rl_digit_value (c); rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; rl_explicit_arg = 1; _rl_argcxt |= NUM_SAWDIGITS; } else if (c == '-' && rl_explicit_arg == 0) { rl_numeric_arg = 1; _rl_argcxt |= NUM_SAWMINUS; rl_arg_sign = -1; } else { /* Make M-- command equivalent to M--1 command. */ if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) rl_explicit_arg = 1; rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); r = _rl_dispatch (key, _rl_keymap); if (RL_ISSTATE (RL_STATE_CALLBACK)) { /* At worst, this will cause an extra redisplay. Otherwise, we have to wait until the next character comes in. */ if (rl_done == 0) (*rl_redisplay_function) (); r = 0; } return r; } return 1; }
int rl_vi_domove(int key, int *nextkey) { int c, save; int old_end; rl_mark = rl_point; RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); *nextkey = c; if (!member (c, vi_motion)) { if (_rl_digit_p (c)) { save = rl_numeric_arg; rl_numeric_arg = _rl_digit_value (c); rl_digit_loop1 (); rl_numeric_arg *= save; RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); /* real command */ RL_UNSETSTATE(RL_STATE_MOREINPUT); *nextkey = c; } else if (key == c && (key == 'd' || key == 'y' || key == 'c')) { rl_mark = rl_end; rl_beg_of_line (1, c); _rl_vi_last_motion = c; return (0); } else return (-1); } _rl_vi_last_motion = c; /* Append a blank character temporarily so that the motion routines work right at the end of the line. */ old_end = rl_end; rl_line_buffer[rl_end++] = ' '; rl_line_buffer[rl_end] = '\0'; _rl_dispatch (c, _rl_keymap); /* Remove the blank that we added. */ rl_end = old_end; rl_line_buffer[rl_end] = '\0'; if (rl_point > rl_end) rl_point = rl_end; /* No change in position means the command failed. */ if (rl_mark == rl_point) return (-1); /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next word. If we are not at the end of the line, and we are on a non-whitespace character, move back one (presumably to whitespace). */ if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && !whitespace (rl_line_buffer[rl_point])) rl_point--; /* If cw or cW, back up to the end of a word, so the behaviour of ce or cE is the actual result. Brute-force, no subtlety. */ if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) { /* Don't move farther back than where we started. */ while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) rl_point--; /* Posix.2 says that if cw or cW moves the cursor towards the end of the line, the character under the cursor should be deleted. */ if (rl_point == rl_mark) rl_point++; else { /* Move past the end of the word so that the kill doesn't remove the last letter of the previous word. Only do this if we are not at the end of the line. */ if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) rl_point++; } } if (rl_mark < rl_point) SWAP (rl_point, rl_mark); return (0); }