mirror of
https://github.com/sheumann/hush.git
synced 2025-02-19 05:30:56 +00:00
Add initial support for getting terminal information from termcap, instead of hard-coding vt100-style codes.
This currently only supports output, and still doesn't quite display correctly in some cases.
This commit is contained in:
parent
c37475dcbc
commit
5f6121c091
8
Makefile
8
Makefile
@ -89,6 +89,12 @@ LIBBB_D_SEG = -SLIBBB_C___
|
||||
INCLUDES = -I include -I shell -I libbb
|
||||
DEFINES = -Dhush_main=main -DNDEBUG
|
||||
|
||||
// This should be the ltermcap from GNO 2.0.4. The one from 2.0.6 is broken
|
||||
// (links to unimplemented functions), so don't use it.
|
||||
// The 2.0.4 version is in the "lib.shk" file within
|
||||
// ftp://ftp.gno.org/pub/apple2/gs.specific/gno/base/v204/gnodisk1.sdk
|
||||
LIBS = -l/usr/lib/libtermcap.204
|
||||
|
||||
# Hack to effectively disable close_on_exec_on method for now.
|
||||
# This will cause us to leak file descriptors. TODO: Fix.
|
||||
DEFINES += -DF_SETFD=-1 -DFD_CLOEXEC=-1
|
||||
@ -107,7 +113,7 @@ CFLAGS += -g -DDEBUG
|
||||
PROG = hush
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CC) $(OBJS) -o $@
|
||||
$(CC) $(LIBS) $(OBJS) -o $@
|
||||
|
||||
%.a: %.c
|
||||
$(CC) $(INCLUDES) $(DEFINES) $(CFLAGS) -c $< -o $@ \
|
||||
|
@ -56,6 +56,7 @@ OBJS = $(SRCS:.c=.o)
|
||||
|
||||
INCLUDES = -I include -I shell -I libbb
|
||||
DEFINES = -Dhush_main=main -DNDEBUG
|
||||
LIBS = -ltermcap
|
||||
|
||||
OCC_FLAGS = -i -w -a0
|
||||
# Add $(OCC_FLAGS) to CFLAGS on dmake
|
||||
@ -64,7 +65,7 @@ CFLAGS = $(null, $(OCC_FLAGS))
|
||||
PROG = hush
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CC) $(OBJS) -o $@
|
||||
$(CC) $(LIBS) $(OBJS) -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(INCLUDES) $(DEFINES) $(CFLAGS) -c $< -o $@
|
||||
|
@ -1403,6 +1403,8 @@ int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
|
||||
read_line_input(prompt, command, maxsize)
|
||||
#endif
|
||||
|
||||
void init_termcap(void);
|
||||
|
||||
|
||||
#ifndef COMM_LEN
|
||||
# ifdef TASK_COMM_LEN
|
||||
|
105
libbb/lineedit.c
105
libbb/lineedit.c
@ -49,6 +49,7 @@
|
||||
*/
|
||||
#include "libbb.h"
|
||||
#include "unicode.h"
|
||||
#include <termcap.h>
|
||||
#ifndef _POSIX_VDISABLE
|
||||
# define _POSIX_VDISABLE '\0'
|
||||
#endif
|
||||
@ -108,10 +109,6 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); }
|
||||
|
||||
#define ESC "\033"
|
||||
|
||||
#define SEQ_CLEAR_TILL_END_OF_SCREEN ESC"[J"
|
||||
//#define SEQ_CLEAR_TILL_END_OF_LINE ESC"[K"
|
||||
|
||||
|
||||
enum {
|
||||
MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0
|
||||
? CONFIG_FEATURE_EDITING_MAX_LEN
|
||||
@ -122,6 +119,24 @@ enum {
|
||||
static const char null_str[] ALIGN1 = "";
|
||||
#endif
|
||||
|
||||
#ifdef __GNO__
|
||||
# define TERMCAP_BUFSIZ 1024
|
||||
# define DEFAULT_TERM "gnocon"
|
||||
char *up_cmd = "\037"; // ^_
|
||||
char *home_cmd = "\031"; // ^Y
|
||||
char *right_cmd = "\025"; // ^U
|
||||
char *clear_to_end_of_screen_cmd = "\013"; // ^K
|
||||
#else
|
||||
# define TERMCAP_BUFSIZ 4096
|
||||
# define DEFAULT_TERM "vt100"
|
||||
char *up_cmd = ESC"[A";
|
||||
char *home_cmd = ESC"[H";
|
||||
char *right_cmd = ESC"[C";
|
||||
char *clear_to_end_of_screen_cmd = ESC"[J";
|
||||
#endif
|
||||
|
||||
char termcap_string_buf[TERMCAP_BUFSIZ];
|
||||
|
||||
/* We try to minimize both static and stack usage. */
|
||||
struct lineedit_statics {
|
||||
line_input_t *state;
|
||||
@ -209,6 +224,39 @@ static void deinit_S(void)
|
||||
}
|
||||
#define DEINIT_S() deinit_S()
|
||||
|
||||
void init_termcap(void)
|
||||
{
|
||||
char *term;
|
||||
char *termcap_buffer;
|
||||
char *string_buf = termcap_string_buf;
|
||||
char *result;
|
||||
|
||||
term = getenv("TERM");
|
||||
if (term == NULL)
|
||||
term = DEFAULT_TERM;
|
||||
termcap_buffer = malloc(TERMCAP_BUFSIZ);
|
||||
if (termcap_buffer == NULL)
|
||||
return;
|
||||
tgetent(termcap_buffer, term);
|
||||
|
||||
result = tgetstr("up", &string_buf);
|
||||
if (result != NULL)
|
||||
up_cmd = result;
|
||||
|
||||
result = tgetstr("ho", &string_buf);
|
||||
if (result != NULL)
|
||||
home_cmd = result;
|
||||
|
||||
result = tgetstr("nd", &string_buf);
|
||||
if (result != NULL)
|
||||
right_cmd = result;
|
||||
|
||||
result = tgetstr("cd", &string_buf);
|
||||
if (result != NULL)
|
||||
clear_to_end_of_screen_cmd = result;
|
||||
|
||||
free(termcap_buffer);
|
||||
}
|
||||
|
||||
#if ENABLE_UNICODE_SUPPORT
|
||||
static size_t load_string(const char *src)
|
||||
@ -421,7 +469,14 @@ static void goto_new_line(void)
|
||||
{
|
||||
put_till_end_and_adv_cursor();
|
||||
if (cmdedit_x != 0)
|
||||
bb_putchar('\n');
|
||||
bb_putchar(NEWLINE_CHAR);
|
||||
}
|
||||
|
||||
static void go_up(int lines_up)
|
||||
{
|
||||
for (; lines_up > 0; lines_up--) {
|
||||
tputs(up_cmd, 1, bb_putchar);
|
||||
}
|
||||
}
|
||||
|
||||
static void beep(void)
|
||||
@ -465,19 +520,9 @@ static void input_backward(unsigned num)
|
||||
|
||||
if (cmdedit_x >= num) {
|
||||
cmdedit_x -= num;
|
||||
if (num <= 4) {
|
||||
/* This is longer by 5 bytes on x86.
|
||||
* Also gets miscompiled for ARM users
|
||||
* (busybox.net/bugs/view.php?id=2274).
|
||||
* printf(("\b\b\b\b" + 4) - num);
|
||||
* return;
|
||||
*/
|
||||
do {
|
||||
bb_putchar('\b');
|
||||
} while (--num);
|
||||
return;
|
||||
}
|
||||
printf(ESC"[%uD", num);
|
||||
do {
|
||||
bb_putchar('\b');
|
||||
} while (--num);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -502,7 +547,7 @@ static void input_backward(unsigned num)
|
||||
*/
|
||||
unsigned sv_cursor;
|
||||
/* go to 1st column; go up to first line */
|
||||
printf("\r" ESC"[%uA", cmdedit_y);
|
||||
go_up(cmdedit_y);
|
||||
cmdedit_y = 0;
|
||||
sv_cursor = cursor;
|
||||
put_prompt(); /* sets cursor to 0 */
|
||||
@ -519,12 +564,16 @@ static void input_backward(unsigned num)
|
||||
cmdedit_x = (width * cmdedit_y - num) % width;
|
||||
cmdedit_y -= lines_up;
|
||||
/* go to 1st column; go up */
|
||||
printf("\r" ESC"[%uA", lines_up);
|
||||
go_up(lines_up);
|
||||
/* go to correct column.
|
||||
* xterm, konsole, Linux VT interpret 0 as 1 below! wow.
|
||||
* need to *make sure* we skip it if cmdedit_x == 0 */
|
||||
if (cmdedit_x)
|
||||
printf(ESC"[%uC", cmdedit_x);
|
||||
if (cmdedit_x) {
|
||||
int cols_right;
|
||||
for (cols_right = cmdedit_x; cols_right > 0; cols_right++) {
|
||||
tputs(right_cmd, 1, bb_putchar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,11 +581,11 @@ static void input_backward(unsigned num)
|
||||
static void redraw(int y, int back_cursor)
|
||||
{
|
||||
if (y > 0) /* up y lines */
|
||||
printf(ESC"[%uA", y);
|
||||
go_up(y); // UP -- not implemented; loop doing "up"
|
||||
bb_putchar('\r');
|
||||
put_prompt();
|
||||
put_till_end_and_adv_cursor();
|
||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
||||
tputs(clear_to_end_of_screen_cmd, 1, bb_putchar);
|
||||
input_backward(back_cursor);
|
||||
}
|
||||
|
||||
@ -572,7 +621,7 @@ static void input_delete(int save)
|
||||
command_len--;
|
||||
put_till_end_and_adv_cursor();
|
||||
/* Last char is still visible, erase it (and more) */
|
||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
||||
tputs(clear_to_end_of_screen_cmd, 1, bb_putchar);
|
||||
input_backward(cursor - j); /* back to old pos cursor */
|
||||
}
|
||||
|
||||
@ -1761,7 +1810,7 @@ static void ask_terminal(void)
|
||||
pfd.events = POLLIN;
|
||||
if (safe_poll(&pfd, 1, 0) == 0) {
|
||||
S.sent_ESC_br6n = 1;
|
||||
fputs(ESC"[6n", stdout);
|
||||
fputs(ESC"[6n", stdout); // u7
|
||||
fflush_all(); /* make terminal see it ASAP! */
|
||||
}
|
||||
}
|
||||
@ -2435,12 +2484,12 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
|
||||
/* Control-k -- clear to end of line */
|
||||
command_ps[cursor] = BB_NUL;
|
||||
command_len = cursor;
|
||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
||||
tputs(clear_to_end_of_screen_cmd, 1, bb_putchar);
|
||||
break;
|
||||
case CTRL('L'):
|
||||
vi_case(CTRL('L')|VI_CMDMODE_BIT:)
|
||||
/* Control-l -- clear screen */
|
||||
printf(ESC"[H"); /* cursor to top,left */
|
||||
tputs(home_cmd, 24, bb_putchar); /* cursor to top,left */
|
||||
redraw(0, command_len - cursor);
|
||||
break;
|
||||
#if MAX_HISTORY > 0
|
||||
|
@ -8168,6 +8168,7 @@ int hush_main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_EDITING
|
||||
init_termcap();
|
||||
G.line_input_state = new_line_input_t(FOR_SHELL);
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user