*/
/*
- Usage and known bugs:
- Terminal key codes are not extensive, and more will probably
- need to be added. This version was created on Debian GNU/Linux 2.x.
- Delete, Backspace, Home, End, and the arrow keys were tested
- to work in an Xterm and console. Ctrl-A also works as Home.
- Ctrl-E also works as End.
-
- Small bugs (simple effect):
- - not true viewing if terminal size (x*y symbols) less
- size (prompt + editor's line + 2 symbols)
- - not true viewing if length prompt less terminal width
+ * Usage and known bugs:
+ * Terminal key codes are not extensive, and more will probably
+ * need to be added. This version was created on Debian GNU/Linux 2.x.
+ * Delete, Backspace, Home, End, and the arrow keys were tested
+ * to work in an Xterm and console. Ctrl-A also works as Home.
+ * Ctrl-E also works as End.
+ *
+ * lineedit does not know that the terminal escape sequences do not
+ * take up space on the screen. The redisplay code assumes, unless
+ * told otherwise, that each character in the prompt is a printable
+ * character that takes up one character position on the screen.
+ * You need to tell lineedit that some sequences of characters
+ * in the prompt take up no screen space. Compatibly with readline,
+ * use the \[ escape to begin a sequence of non-printing characters,
+ * and the \] escape to signal the end of such a sequence. Example:
+ *
+ * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
*/
#include "libbb.h"
volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
sighandler_t previous_SIGWINCH_handler;
-
- int cmdedit_x; /* real x terminal position */
- int cmdedit_y; /* pseudoreal y terminal position */
- int cmdedit_prmt_len; /* length of prompt (without colors etc) */
+ unsigned cmdedit_x; /* real x terminal position */
+ unsigned cmdedit_y; /* pseudoreal y terminal position */
+ unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */
unsigned cursor;
unsigned command_len;
{
bb_putchar(c);
}
- if (++cmdedit_x >= (int)cmdedit_termw) {
+ if (++cmdedit_x >= cmdedit_termw) {
/* terminal is scrolled down */
cmdedit_y++;
cmdedit_x = 0;
return;
cursor -= num;
- if ((unsigned)cmdedit_x >= num) {
+ if (cmdedit_x >= num) {
cmdedit_x -= num;
if (num <= 4) {
/* This is longer by 5 bytes on x86.
- * Also gets mysteriously
- * miscompiled for some ARM users.
+ * Also gets miscompiled for ARM users
+ * (busybox.net/bugs/view.php?id=2274).
* printf(("\b\b\b\b" + 4) - num);
* return;
*/
/* Need to go one or more lines up */
num -= cmdedit_x;
- count_y = 1 + (num / cmdedit_termw);
- cmdedit_y -= count_y;
- cmdedit_x = cmdedit_termw * count_y - num;
+ {
+ unsigned w = cmdedit_termw; /* volatile var */
+ count_y = 1 + (num / w);
+ cmdedit_y -= count_y;
+ cmdedit_x = w * count_y - num;
+ }
/* go to 1st column; go up; go to correct column */
printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x);
}
static void put_prompt(void)
{
out1str(cmdedit_prompt);
- cmdedit_x = cmdedit_prmt_len;
cursor = 0;
-// Huh? what if cmdedit_prmt_len >= width?
- cmdedit_y = 0; /* new quasireal y */
+ {
+ unsigned w = cmdedit_termw; /* volatile var */
+ cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
+ cmdedit_x = cmdedit_prmt_len % w;
+ }
}
/* draw prompt, editor line, and clear tail */
}
#endif
- strcpy(command_ps + j, command_ps + j + 1);
+ overlapping_strcpy(command_ps + j, command_ps + j + 1);
command_len--;
input_end(); /* rewrite new line */
cmdedit_set_out_char(' '); /* erase char */
static void add_match(char *matched)
{
- int nm = num_matches;
- int nm1 = nm + 1;
-
- matches = xrealloc(matches, nm1 * sizeof(char *));
- matches[nm] = matched;
+ matches = xrealloc_vector(matches, 4, num_matches);
+ matches[num_matches] = matched;
num_matches++;
}
/* NB: do not trash old history if file can't be opened */
- fp = fopen(fromfile, "r");
+ fp = fopen_for_read(fromfile);
if (fp) {
/* clean up old history */
for (hi = state->cnt_history; hi > 0;) {
{
FILE *fp;
- fp = fopen(tofile, "w");
+ fp = fopen_for_write(tofile);
if (fp) {
int i;
static void win_changed(int nsig)
{
- int width;
+ unsigned width;
get_terminal_width_height(0, &width, NULL);
cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
if (nsig == SIGWINCH)
* 0 on ctrl-C (the line entered is still returned in 'command'),
* >0 length of input string, including terminating '\n'
*/
-int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
+int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
{
#if ENABLE_FEATURE_TAB_COMPLETION
smallint lastWasTab = FALSE;
#endif
- unsigned int ic;
+ unsigned ic;
unsigned char c;
smallint break_out = 0;
#if ENABLE_FEATURE_EDITING_VI
vi_case(CTRL('U')|vbit:)
/* Control-U -- Clear line before cursor */
if (cursor) {
- strcpy(command, command + cursor);
+ overlapping_strcpy(command, command + cursor);
command_len -= cursor;
redraw(cmdedit_y, command_len);
}
return command_len;
}
-line_input_t *new_line_input_t(int flags)
+line_input_t* FAST_FUNC new_line_input_t(int flags)
{
line_input_t *n = xzalloc(sizeof(*n));
n->flags = flags;
#else
#undef read_line_input
-int read_line_input(const char* prompt, char* command, int maxsize)
+int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
{
fputs(prompt, stdout);
fflush(stdout);