aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-05-27 14:12:47 -0700
committerBruce Hill <bruce@bruce-hill.com>2019-05-27 14:12:47 -0700
commite12759b48cd792c12b796d023f6364c07d208ab6 (patch)
treef16a9181e5e83e9870ef18fc3900ed25996c6394
parent4aa93906e707822e65cf275db4f856fcee97cdea (diff)
Switched to use file pointers instead of file descriptors.
-rw-r--r--bb.c258
1 files changed, 98 insertions, 160 deletions
diff --git a/bb.c b/bb.c
index dfc751b..16ed2e4 100644
--- a/bb.c
+++ b/bb.c
@@ -32,7 +32,6 @@
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define MIN(a,b) ((a) > (b) ? (b) : (a))
-#define writez(fd, str) write(fd, str, strlen(str))
#define IS_SELECTED(p) (((p)->atme) != NULL)
#define LLREMOVE(e) do { \
if ((e)->next) { \
@@ -43,13 +42,13 @@
(e)->atme = NULL; \
} while (0)
-#define alt_screen() writez(termfd, "\033[?1049h")
-#define default_screen() writez(termfd, "\033[?1049l")
-#define hide_cursor() writez(termfd, "\033[?25l");
-#define show_cursor() writez(termfd, "\033[?25h");
+#define alt_screen() fputs("\033[?1049h", tty_out)
+#define default_screen() fputs("\033[?1049l", tty_out)
+#define hide_cursor() fputs("\033[?25l", tty_out);
+#define show_cursor() fputs("\033[?25h", tty_out);
#define err(...) do { \
- if (termfd) { \
+ if (tty_out) { \
default_screen(); \
close_term(); \
} \
@@ -120,8 +119,6 @@ static void close_term(void);
static void* memcheck(void *p);
static int unprintables(char *s);
static int run_cmd_on_selection(bb_state_t *s, const char *cmd);
-static void term_move(int x, int y);
-static void bwrite_escaped(int fd, const char *str, const char *reset_color);
static void render(bb_state_t *s, int lazy);
static int compare_files(void *r, const void *v1, const void *v2);
static int find_file(bb_state_t *s, const char *name);
@@ -144,8 +141,8 @@ extern const char *CURSOR_COLOR, *LINKDIR_COLOR, *DIR_COLOR, *LINK_COLOR, *NORMA
extern const int KEY_DELAY;
// Global variables
-static struct termios orig_termios;
-static int termfd = 0;
+static struct termios orig_termios, bb_termios;
+static FILE *tty_out = NULL, *tty_in = NULL;
static int termwidth, termheight;
static int mouse_x, mouse_y;
static char *cmdfilename = NULL;
@@ -159,39 +156,41 @@ void update_term_size(int sig)
{
(void)sig;
struct winsize sz = {0};
- ioctl(termfd, TIOCGWINSZ, &sz);
+ ioctl(fileno(tty_in), TIOCGWINSZ, &sz);
termwidth = sz.ws_col;
termheight = sz.ws_row;
}
void init_term(void)
{
- termfd = open("/dev/tty", O_RDWR);
- tcgetattr(termfd, &orig_termios);
- struct termios tios;
- memcpy(&tios, &orig_termios, sizeof(tios));
- tios.c_iflag &= ~(unsigned long)(
+ tty_in = fopen("/dev/tty", "r");
+ tty_out = fopen("/dev/tty", "w");
+ tcgetattr(fileno(tty_out), &orig_termios);
+ memcpy(&bb_termios, &orig_termios, sizeof(bb_termios));
+ bb_termios.c_iflag &= ~(unsigned long)(
IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
- tios.c_oflag &= (unsigned long)~OPOST;
- tios.c_lflag &= (unsigned long)~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- tios.c_cflag &= (unsigned long)~(CSIZE | PARENB);
- tios.c_cflag |= (unsigned long)CS8;
- tios.c_cc[VMIN] = 0;
- tios.c_cc[VTIME] = 0;
- tcsetattr(termfd, TCSAFLUSH, &tios);
+ bb_termios.c_oflag &= (unsigned long)~OPOST;
+ bb_termios.c_lflag &= (unsigned long)~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ bb_termios.c_cflag &= (unsigned long)~(CSIZE | PARENB);
+ bb_termios.c_cflag |= (unsigned long)CS8;
+ bb_termios.c_cc[VMIN] = 0;
+ bb_termios.c_cc[VTIME] = 0;
+ tcsetattr(fileno(tty_out), TCSAFLUSH, &bb_termios);
update_term_size(0);
signal(SIGWINCH, update_term_size);
// Initiate mouse tracking and disable text wrapping:
- writez(termfd, "\033[?1000h\033[?1002h\033[?1015h\033[?1006h\033[?7l");
+ fputs("\033[?1000h\033[?1002h\033[?1015h\033[?1006h\033[?7l", tty_out);
}
void cleanup_and_exit(int sig)
{
(void)sig;
- if (termfd) {
- tcsetattr(termfd, TCSAFLUSH, &orig_termios);
- close(termfd);
- termfd = 0;
+ if (tty_out) {
+ tcsetattr(fileno(tty_out), TCSAFLUSH, &orig_termios);
+ fclose(tty_out);
+ tty_out = NULL;
+ fclose(tty_in);
+ tty_in = NULL;
}
// Restore default screen, show cursor and re-enable text wrapping
printf("\033[?1000l\033[?1002l\033[?1015l\033[?1006l\033[?1049l\033[?7h\033[?25h\n");
@@ -205,11 +204,13 @@ void close_term(void)
signal(SIGWINCH, SIG_IGN);
// Disable mouse tracking and re-enable text wrapping
- writez(termfd, "\033[?1000l\033[?1002l\033[?1015l\033[?1006l\033[?7h");
+ fputs("\033[?1000l\033[?1002l\033[?1015l\033[?1006l\033[?7h", tty_out);
- tcsetattr(termfd, TCSAFLUSH, &orig_termios);
- close(termfd);
- termfd = 0;
+ tcsetattr(fileno(tty_out), TCSAFLUSH, &orig_termios);
+ fclose(tty_out);
+ tty_out = NULL;
+ fclose(tty_in);
+ tty_in = NULL;
}
void* memcheck(void *p)
@@ -270,73 +271,20 @@ int run_cmd_on_selection(bb_state_t *s, const char *cmd)
return status;
}
-void term_move(int x, int y)
-{
- static char buf[32] = {0};
- int len = snprintf(buf, sizeof(buf), "\033[%d;%dH", y+1, x+1);
- if (len > 0)
- write(termfd, buf, (size_t)len);
-}
+#define term_move(x, y) fprintf(tty_out, "\033[%d;%dH", (int)(y)+1, (int)(x)+1)
-static char *screenbuf = NULL;
-#define SCREENBUF_SIZE ((size_t)((2*getpagesize()) - 128))
-static size_t screenbufpos = 0;
-static inline void bflush(int fd)
-{
- if (screenbufpos == 0) return;
- ssize_t wrote;
- size_t i = 0;
- while (screenbufpos > 0 && (wrote = write(fd, &screenbuf[i], screenbufpos - i)) > 0) {
- i += (size_t)wrote;
- }
- screenbufpos = 0;
-}
-static ssize_t bwrite(int fd, const char *str, size_t n)
-{
- if (screenbufpos + n >= SCREENBUF_SIZE)
- bflush(fd);
- memcpy(screenbuf + screenbufpos, str, n);
- screenbufpos += n;
- return (ssize_t)n;
-}
-static ssize_t bwritez(int fd, const char *str)
-{
- return bwrite(fd, str, strlen(str));
-}
-static void bmove(int fd, int x, int y)
-{
- static char buf[32] = {0};
- int len = snprintf(buf, sizeof(buf), "\033[%d;%dH", y+1, x+1);
- if (len > 0)
- bwrite(fd, buf, (size_t)len);
-}
-static void bwrite_escaped(int fd, const char *str, const char *color)
+static void fputs_escaped(FILE *f, const char *str, const char *color)
{
static const char *escapes = " abtnvfr e";
- size_t maxcharlen = (size_t)strlen(color) + 10;
for (const char *c = str; *c; ++c) {
- if (SCREENBUF_SIZE - screenbufpos < maxcharlen)
- bflush(fd);
- if ((*c & 0xE0) == 0xC0 && (c[1] & 0xC0) == 0x80) { // UTF8 2-byte
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *c;
- } else if ((*c & 0xF0) == 0xE0 && (c[1] & 0xC0) == 0x80
- && (c[2] & 0xC0) == 0x80) { // UTF8 3-byte
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *c;
- } else if ((*c & 0xF8) == 0xF0 && (c[1] & 0xC0) == 0x80
- && (c[2] & 0xC0) == 0x80 && (c[3] & 0xC0) == 0x80 ) { // UTF8 4-byte
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *(c++);
- screenbuf[screenbufpos++] = *c;
+ if (*c < 0) {
+ fputc(*c, f);
} else if (*c > 0 && *c <= '\x1b' && escapes[(int)*c] != ' ') { // "\n", etc.
- screenbufpos += (size_t)sprintf(&screenbuf[screenbufpos], "\033[31m\\%c%s", escapes[(int)*c], color);
+ fprintf(f, "\033[31m\\%c%s", escapes[(int)*c], color);
} else if (!(' ' <= *c && *c <= '~')) { // "\x02", etc.
- screenbufpos += (size_t)sprintf(&screenbuf[screenbufpos], "\033[31m\\x%02X%s", *c, color);
+ fprintf(f, "\033[31m\\x%02X%s", *c, color);
} else {
- screenbuf[screenbufpos++] = *c;
+ fputc(*c, f);
}
}
}
@@ -344,7 +292,6 @@ static void bwrite_escaped(int fd, const char *str, const char *color)
void render(bb_state_t *s, int lazy)
{
- bflush(termfd);
static int lastcursor = -1, lastscroll = -1;
char buf[64];
if (lastcursor == -1 || lastscroll == -1)
@@ -353,11 +300,9 @@ void render(bb_state_t *s, int lazy)
if (lazy) {
// Use terminal scrolling:
if (lastscroll > s->scroll) {
- int n = sprintf(buf, "\033[3;%dr\033[%dT\033[1;%dr", termheight-1, lastscroll - s->scroll, termheight);
- bwrite(termfd, buf, (size_t)n);
+ fprintf(tty_out, "\033[3;%dr\033[%dT\033[1;%dr", termheight-1, lastscroll - s->scroll, termheight);
} else if (lastscroll < s->scroll) {
- int n = sprintf(buf, "\033[3;%dr\033[%dS\033[1;%dr", termheight-1, s->scroll - lastscroll, termheight);
- bwrite(termfd, buf, (size_t)n);
+ fprintf(tty_out, "\033[3;%dr\033[%dS\033[1;%dr", termheight-1, s->scroll - lastscroll, termheight);
}
}
colnamew = termwidth - 1;
@@ -380,14 +325,14 @@ void render(bb_state_t *s, int lazy)
if (!lazy) {
// Path
- bmove(termfd,0,0);
+ term_move(0,0);
const char *color = "\033[0;1;37m";
- bwrite_escaped(termfd, s->path, color);
- bwritez(termfd, " \033[K\033[0m");
+ fputs_escaped(tty_out, s->path, color);
+ fputs(" \033[K\033[0m", tty_out);
// Columns
- bmove(termfd,0,1);
- bwritez(termfd, "\033[41m \033[0;44;30m");
+ term_move(0,1);
+ fputs("\033[41m \033[0;44;30m", tty_out);
for (char *col = s->columns; *col; ++col) {
const char *colname;
int colwidth = 0;
@@ -413,14 +358,14 @@ void render(bb_state_t *s, int lazy)
default:
continue;
}
- if (col != s->columns) bwritez(termfd, " │ ");
- if (DESCENDING(s->sort) != *col) bwritez(termfd, " ");
- else if (IS_REVERSED(s->sort)) bwritez(termfd, RSORT_INDICATOR);
- else bwritez(termfd, SORT_INDICATOR);
- for (ssize_t i = bwritez(termfd, colname); i < colwidth-1; i++)
- bwrite(termfd, " ", 1);
+ if (col != s->columns) fputs(" │ ", tty_out);
+ if (DESCENDING(s->sort) != *col) fputs(" ", tty_out);
+ else if (IS_REVERSED(s->sort)) fputs(RSORT_INDICATOR, tty_out);
+ else fputs(SORT_INDICATOR, tty_out);
+ for (ssize_t i = fputs(colname, tty_out); i < colwidth-1; i++)
+ fputc(' ', tty_out);
}
- bwritez(termfd, " \033[K\033[0m");
+ fputs(" \033[K\033[0m", tty_out);
}
entry_t **files = s->files;
@@ -436,18 +381,18 @@ void render(bb_state_t *s, int lazy)
int y;
do_render:
y = i - s->scroll + 2;
- bmove(termfd,0, y);
+ term_move(0, y);
if (i >= s->nfiles) {
- bwritez(termfd, "\033[K");
+ fputs("\033[K", tty_out);
continue;
}
entry_t *entry = files[i];
{ // Selection box:
if (IS_SELECTED(entry))
- bwritez(termfd, "\033[41m \033[0m");
+ fputs("\033[41m \033[0m", tty_out);
else
- bwritez(termfd, " ");
+ fputs(" ", tty_out);
}
const char *color;
@@ -461,17 +406,16 @@ void render(bb_state_t *s, int lazy)
color = LINK_COLOR;
else
color = NORMAL_COLOR;
- bwritez(termfd, color);
+ fputs(color, tty_out);
int x = 1;
for (char *col = s->columns; *col; ++col) {
- sprintf(buf, "\033[%d;%dH\033[K", y+1, x+1);
- bwritez(termfd, buf);
+ fprintf(tty_out, "\033[%d;%dH\033[K", y+1, x+1);
if (col != s->columns) {
- if (i == s->cursor) bwritez(termfd, " │");
- else bwritez(termfd, " \033[37;2m│\033[22m");
- bwritez(termfd, color);
- bwritez(termfd, " ");
+ if (i == s->cursor) fputs(" │", tty_out);
+ else fputs(" \033[37;2m│\033[22m", tty_out);
+ fputs(color, tty_out);
+ fputs(" ", tty_out);
x += 3;
}
switch (*col) {
@@ -483,27 +427,26 @@ void render(bb_state_t *s, int lazy)
bytes /= 1024;
j++;
}
- sprintf(buf, "%6.*f%c", j > 0 ? 1 : 0, bytes, units[j]);
- bwritez(termfd, buf);
+ fprintf(tty_out, "%6.*f%c", j > 0 ? 1 : 0, bytes, units[j]);
x += colsizew;
break;
}
case 'm':
strftime(buf, sizeof(buf), "%l:%M%p %b %e %Y", localtime(&(entry->info.st_mtime)));
- bwritez(termfd, buf);
+ fputs(buf, tty_out);
x += coldatew;
break;
case 'c':
strftime(buf, sizeof(buf), "%l:%M%p %b %e %Y", localtime(&(entry->info.st_ctime)));
- bwritez(termfd, buf);
+ fputs(buf, tty_out);
x += coldatew;
break;
case 'a':
strftime(buf, sizeof(buf), "%l:%M%p %b %e %Y", localtime(&(entry->info.st_atime)));
- bwritez(termfd, buf);
+ fputs(buf, tty_out);
x += coldatew;
break;
@@ -512,46 +455,47 @@ void render(bb_state_t *s, int lazy)
buf[1] = '0' + ((entry->info.st_mode >> 6) & 7);
buf[2] = '0' + ((entry->info.st_mode >> 3) & 7);
buf[3] = '0' + ((entry->info.st_mode >> 0) & 7);
- bwrite(termfd, buf, 4);
+ buf[4] = '\0';
+ fputs(buf, tty_out);
x += colpermw;
break;
case 'n': {
if (entry->d_escname)
- bwrite_escaped(termfd, entry->d_name, color);
+ fputs_escaped(tty_out, entry->d_name, color);
else
- bwritez(termfd, entry->d_name);
+ fputs(entry->d_name, tty_out);
if (entry->d_isdir) {
- bwritez(termfd, "/");
+ fputs("/", tty_out);
}
if (entry->d_linkname) {
- bwritez(termfd, "\033[2m -> ");
+ fputs("\033[2m -> ", tty_out);
if (entry->d_esclink)
- bwrite_escaped(termfd, entry->d_linkname, color);
+ fputs_escaped(tty_out, entry->d_linkname, color);
else
- bwritez(termfd, entry->d_linkname);
+ fputs(entry->d_linkname, tty_out);
if (entry->d_isdir) {
- bwritez(termfd, "/");
+ fputs("/", tty_out);
}
- bwritez(termfd, "\033[22m");
+ fputs("\033[22m", tty_out);
}
x += colnamew;
break;
}
}
}
- bwritez(termfd, " \033[K\033[0m"); // Reset color and attributes
+ fputs(" \033[K\033[0m", tty_out); // Reset color and attributes
}
static const char *help = "Press '?' to see key bindings ";
- bmove(termfd,0, termheight - 1);
- bwritez(termfd, "\033[K");
- bmove(termfd,MAX(0, termwidth - (int)strlen(help)), termheight - 1);
- bwritez(termfd, help);
+ term_move(0, termheight - 1);
+ fputs("\033[K", tty_out);
+ term_move(MAX(0, termwidth - (int)strlen(help)), termheight - 1);
+ fputs(help, tty_out);
lastcursor = s->cursor;
lastscroll = s->scroll;
- bflush(termfd);
+ fflush(tty_out);
// TODO: show selection and dotfile setting and anything else?
}
@@ -1075,7 +1019,6 @@ entry_t *explore(const char *path)
int lastwidth = termwidth, lastheight = termheight;
int lazy = 0, check_cmds = 1;
- screenbuf = valloc((size_t)SCREENBUF_SIZE);
init_term();
alt_screen();
hide_cursor();
@@ -1157,7 +1100,7 @@ entry_t *explore(const char *path)
int key;
get_keyboard_input:
- key = term_getkey(termfd, &mouse_x, &mouse_y, KEY_DELAY);
+ key = term_getkey(fileno(tty_in), &mouse_x, &mouse_y, KEY_DELAY);
switch (key) {
case KEY_MOUSE_LEFT: {
struct timespec clicktime;
@@ -1227,32 +1170,29 @@ entry_t *explore(const char *path)
case KEY_CTRL_H: {
term_move(0,termheight-1);
- writez(termfd, "\033[K\033[33;1mPress any key...\033[0m");
- while ((key = term_getkey(termfd, &mouse_x, &mouse_y, 1000)) == -1)
+ fputs("\033[K\033[33;1mPress any key...\033[0m", tty_out);
+ while ((key = term_getkey(fileno(tty_in), &mouse_x, &mouse_y, 1000)) == -1)
;
term_move(0,termheight-1);
- writez(termfd, "\033[K\033[1m<\033[33m");
+ fputs("\033[K\033[1m<\033[33m", tty_out);
const char *name = keyname(key);
- char buf[32] = {(char)key};
- if (name) writez(termfd, name);
+ if (name) fputs(name, tty_out);
else if (' ' <= key && key <= '~')
- write(termfd, buf, 1);
- else {
- sprintf(buf, "\033[31m\\x%02X", key);
- writez(termfd, buf);
- }
+ fputc((char)key, tty_out);
+ else
+ fprintf(tty_out, "\033[31m\\x%02X", key);
- writez(termfd, "\033[0;1m> is bound to: \033[34;1m");
+ fputs("\033[0;1m> is bound to: \033[34;1m", tty_out);
for (int i = 0; bindings[i].keys[0] > 0; i++) {
for (int j = 0; bindings[i].keys[j]; j++) {
if (key == bindings[i].keys[j]) {
- writez(termfd, bindings[i].description);
- writez(termfd, "\033[0m");
+ fputs(bindings[i].description, tty_out);
+ fputs("\033[0m", tty_out);
goto next_input;
}
}
}
- writez(termfd, "--- nothing ---\033[0m");
+ fputs("--- nothing ---\033[0m", tty_out);
goto next_input;
}
@@ -1296,7 +1236,7 @@ entry_t *explore(const char *path)
goto get_keyboard_input;
}
term_move(0, termheight-1);
- //writez(termfd, "\033[K");
+ //fputs("\033[K", tty_out);
if (binding->flags & NORMAL_TERM)
default_screen();
if (binding->flags & NORMAL_TERM || binding->flags & SHOW_CURSOR)
@@ -1325,7 +1265,6 @@ entry_t *explore(const char *path)
default_screen();
show_cursor();
close_term();
- free(screenbuf);
return firstselected;
}
@@ -1357,9 +1296,8 @@ void print_bindings(int verbose)
printf("\033[0m\033[%dG\033[34;1m%s\033[0m", _width/2 + 1, bindings[i].description);
if (verbose) {
printf("\n\033[%dG\033[0;32m", MAX(1, (_width - (int)strlen(bindings[i].command))/2));
+ fputs_escaped(stdout, bindings[i].command, "\033[0;32m");
fflush(stdout);
- bwrite_escaped(STDOUT_FILENO, bindings[i].command, "\033[0;32m");
- bflush(STDOUT_FILENO);
}
printf("\033[0m\n");
}