summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-04-24 12:53:02 -0400
committerJakob Kaivo <jkk@ung.org>2022-04-24 12:53:02 -0400
commit3692b934364d8c1646052ef3431d5027baa58bd6 (patch)
tree1435d0b2a2b1a79edec98fceec916954f2551bb7
parenta31fd47001b232fcb6afcf3ddb07cc78e8a8b78c (diff)
switch back to using termios (with help from tput)termios
-rw-r--r--Makefile2
-rw-r--r--more.c190
2 files changed, 106 insertions, 86 deletions
diff --git a/Makefile b/Makefile
index 8f8f64a..da2c470 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ CC=c99
LD=$(CC)
CFLAGS=-Wall -Wextra -Wpedantic -Werror -g
LDFLAGS=
-LDLIBS=-lcurses
+LDLIBS=
SRCDIR=.
OBJDIR=.
BINDIR=$(OBJDIR)
diff --git a/more.c b/more.c
index 83e6077..cf59dce 100644
--- a/more.c
+++ b/more.c
@@ -23,18 +23,18 @@
*/
#define _XOPEN_SOURCE 700
-#include <curses.h>
#include <ctype.h>
#include <errno.h>
#include <libgen.h>
#include <locale.h>
#include <spawn.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <term.h>
+#include <termios.h>
#include <unistd.h>
#include <wordexp.h>
@@ -55,11 +55,13 @@ struct more_file {
int eof;
};
-static int more_clear = 0;
+typedef enum { DISABLE, ENABLE, CLEAR } more_clear_action;
+
+static struct termios more_term;
static int more_fastexit = 0;
static int more_backspace = 1;
-static WINDOW *more_win = NULL;
-static WINDOW *more_status = NULL;
+static int more_lines = 24;
+static FILE *more_in = NULL;
enum {
CTRL_B = 0x02,
@@ -70,6 +72,34 @@ enum {
CTRL_U = 0x15,
};
+static void more_status(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+static void more_clear(more_clear_action action)
+{
+ static char clearcmd[64] = "";
+
+ if (action == ENABLE) {
+ FILE *p = popen("tput clear", "r");
+ if (p == NULL) {
+ return;
+ }
+ fread(clearcmd, 1, sizeof(clearcmd), p);
+ fclose(p);
+ }
+
+ if (clearcmd[0] == '\0') {
+ return;
+ }
+
+ printf("%s", clearcmd);
+}
+
static ssize_t more_getline(struct more_file *mf, size_t lineno)
{
if (mf->nlines <= lineno && mf->nlines != 0) {
@@ -90,8 +120,6 @@ static ssize_t more_getline(struct more_file *mf, size_t lineno)
return -1;
}
- printf("%s\r", mf->buf);
-
if (mf->nlines > 1) {
mf->bytepos[mf->nlines - 1] = mf->bytepos[mf->nlines - 2] + strlen(mf->buf);
} else {
@@ -154,39 +182,38 @@ static void more_close(struct more_file *mf)
static int more_printline(char *s)
{
- int ret = -1;
- /*
- if (strlen(s) == (size_t)COLS) {
- s[COLS - 1] = '\0';
+ static int columns = 0;
+ if (columns == 0) {
+ char *colenv = getenv("COLUMNS");
+ columns = colenv ? atoi(colenv) : 80;
}
- */
- scrollok(more_win, FALSE);
+ int ret = -1;
+
for (size_t i = 0; s[i] != '\0'; i++) {
int attr = 0;
if (more_backspace && s[i + 1] == '\b') {
if (s[i + 2] == '_') {
- attr = A_UNDERLINE;
+ //attr = A_UNDERLINE;
} else if (s[i + 2] == s[i]) {
- attr = A_BOLD;
+ //attr = A_BOLD;
} else {
i++;
continue;
}
}
if (attr) {
- wattron(more_win, attr);
+ //wattron(more_win, attr);
}
- waddch(more_win, s[i]);
- if (i % COLS == 0) {
+ putchar(s[i]);
+ if (i % columns == 0) {
ret++;
}
if (attr) {
- wattroff(more_win, attr);
+ //wattroff(more_win, attr);
i += 2;
}
}
- scrollok(more_win, TRUE);
return ret;
}
@@ -194,9 +221,9 @@ static int more_printline(char *s)
static void more_refresh(struct more_file *mf)
{
int printed = 0;
- wmove(more_win, 0, 0);
+ //wmove(more_win, 0, 0);
- for (size_t i = mf->topline; i + printed < mf->topline + LINES; i++) {
+ for (size_t i = mf->topline; i + printed < mf->topline + more_lines; i++) {
/* FIXME: account for long lines */
if (more_getline(mf, i) == -1) {
@@ -205,15 +232,14 @@ static void more_refresh(struct more_file *mf)
printed += more_printline(mf->buf);
}
- wrefresh(more_win);
}
static void more_scroll(struct more_file *mf, int count, int multiple)
{
int by = count ? count * multiple : multiple;
- if (more_clear && abs(by) > LINES) {
- clear();
+ if (abs(by) > more_lines) {
+ more_clear(CLEAR);
}
if (by < 0) {
@@ -224,7 +250,7 @@ static void more_scroll(struct more_file *mf, int count, int multiple)
mf->topline += by;
}
if (by != 0) {
- wscrl(more_win, by);
+ more_clear(CLEAR);
more_refresh(mf);
}
return;
@@ -232,17 +258,17 @@ static void more_scroll(struct more_file *mf, int count, int multiple)
while (by-- > 0) {
/* FIXME: account for long lines here, too */
- if (more_getline(mf, mf->topline + LINES) < 0) {
+ if (more_getline(mf, mf->topline + more_lines) < 0) {
break;
}
mf->topline++;
- wprintw(more_win, "%s", mf->buf);
+ more_printline(mf->buf);
}
}
static void mark(struct more_file *mf)
{
- int c = wgetch(more_status);
+ int c = fgetc(more_in);
if (islower(c)) {
mf->mark[c - 'a'] = mf->topline;
}
@@ -250,7 +276,7 @@ static void mark(struct more_file *mf)
static void jump(struct more_file *mf)
{
- int c = wgetch(more_status);
+ int c = fgetc(more_in);
if (islower(c)) {
mf->topline = mf->mark[c - 'a'];
more_refresh(mf);
@@ -262,7 +288,7 @@ static void more_help(void)
char path[L_tmpnam + 1];
FILE *f = fopen(tmpnam(path), "w");
if (f == NULL) {
- wprintw(more_status, "error creating help: %s", strerror(errno));
+ fprintf(stderr, "error creating help: %s", strerror(errno));
return;
}
@@ -336,8 +362,6 @@ static void more_invoke_editor(struct more_file *mf)
argv[2] = NULL;
}
- def_prog_mode();
- reset_shell_mode();
pid_t pid;
if (posix_spawnp(&pid, editor, NULL, NULL, argv, environ) == 0) {
size_t line = mf->topline;
@@ -346,23 +370,20 @@ static void more_invoke_editor(struct more_file *mf)
more_open(mf);
mf->topline = line;
} else {
- wprintw(more_status, "%s %s: %s\n", editor, mf->path,
+ fprintf(stderr, "%s %s: %s\n", editor, mf->path,
strerror(errno));
}
-
- reset_prog_mode();
}
static struct more_file more_examine(struct more_file *mf)
{
- wprintw(more_status, "e");
+ //wprintw(more_status, "e");
char filename[1024];
- wgetnstr(more_status, filename, sizeof(filename));
- wclear(more_status);
+ fgets(filename, sizeof(filename), more_in);
wordexp_t we = { 0 };
if (wordexp(filename, &we, WRDE_NOCMD) != 0) {
- wprintw(more_status, "couldn't expand %s", filename);
+ fprintf(stderr, "couldn't expand %s", filename);
return *mf;
}
@@ -374,7 +395,7 @@ static struct more_file more_examine(struct more_file *mf)
wordfree(&we);
if (we.we_wordc > 1) {
- wprintw(more_status, "not opening multiple files");
+ fprintf(stderr, "not opening multiple files");
return *mf;
}
@@ -385,7 +406,7 @@ static struct more_file more_examine(struct more_file *mf)
/*
struct more_file ret = more_open(filename);
if (ret.f == NULL) {
- wprintw(more_status, "%s: %s", filename, strerror(errno));
+ fprintf(stderr, "%s: %s", filename, strerror(errno));
return *mf;
}
@@ -411,8 +432,6 @@ static struct more_file * more_next(struct more_file *mf, int n)
}
more_open(mf);
- wclear(more_win);
- wmove(more_win, 0, 0);
more_refresh(mf);
return mf;
}
@@ -428,19 +447,19 @@ static int more(struct more_file *mf)
int count = 0;
while (mf) {
- int at_eof = (mf->eof && (mf->topline + LINES >= mf->nlines));
- wmove(more_status, 0, 0);
+ int at_eof = (mf->eof && (mf->topline + more_lines >= mf->nlines));
+ //wmove(more_status, 0, 0);
if (at_eof) {
if (more_fastexit && mf->next == NULL) {
return 0;
}
- wprintw(more_status, "%s <EOF>", mf->path);
+ more_status("%s <EOF>", mf->path);
}
- int c = wgetch(more_status);
- wclear(more_status);
+ int c = fgetc(more_in);
switch (c) {
case EOF:
+ perror("fgetc");
exit(2);
break;
@@ -456,7 +475,7 @@ static int more(struct more_file *mf)
}
if (count == 0) {
- count = LINES - 1;
+ count = more_lines - 1;
}
more_scroll(mf, count, 1);
break;
@@ -464,13 +483,13 @@ static int more(struct more_file *mf)
case 'b':
case CTRL_B:
if (count == 0) {
- count = LINES - 1;
+ count = more_lines - 1;
}
more_scroll(mf, count, -1);
break;
case ' ':
- count = count ? count : LINES - 1;
+ count = count ? count : more_lines - 1;
/* FALLTHRU */
case 'j':
case '\n':
@@ -491,7 +510,7 @@ static int more(struct more_file *mf)
mf = more_next(mf, 1);
break;
}
- more_scroll(mf, count, (LINES - 1) / 2);
+ more_scroll(mf, count, (more_lines - 1) / 2);
break;
case 's':
@@ -499,12 +518,12 @@ static int more(struct more_file *mf)
mf = more_next(mf, 1);
}
count = count ? count : 1;
- more_scroll(mf, LINES - 1 + count, 1);
+ more_scroll(mf, more_lines - 1 + count, 1);
break;
case 'u':
case CTRL_U:
- more_scroll(mf, count, -(LINES - 1) / 2);
+ more_scroll(mf, count, -(more_lines - 1) / 2);
break;
case 'G':
@@ -521,7 +540,7 @@ static int more(struct more_file *mf)
/* FALLTHRU */
case 'r':
case CTRL_L:
- wclear(more_win);
+ more_clear(CLEAR);
more_refresh(mf);
break;
@@ -550,10 +569,10 @@ static int more(struct more_file *mf)
break;
case ':':
- waddch(more_status, c);
- int c2 = wgetch(more_status);
-
- wprintw(more_status, "\b \b");
+ //waddch(more_status, c);
+ ;
+ int c2 = fgetc(more_in);
+ //wprintw(more_status, "\b \b");
switch (c2) {
case 'e':
@@ -586,11 +605,11 @@ static int more(struct more_file *mf)
case '=':
case CTRL_G:
- wprintw(more_status, "%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", mf->path, 0, 0, mf->topline, mf->bytepos[mf->topline], mf->nbytes, 100 * mf->bytepos[mf->topline] / mf->nbytes);
+ more_status("%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", mf->path, 0, 0, mf->topline, mf->bytepos[mf->topline], mf->nbytes, 100 * mf->bytepos[mf->topline] / mf->nbytes);
break;
case 'Z':
- if (wgetch(more_status) != 'Z') {
+ if (fgetc(more_in) != 'Z') {
break;
}
/* FALLTHRU */
@@ -616,8 +635,6 @@ static int more(struct more_file *mf)
if (!isdigit(c)) {
count = 0;
}
-
- wrefresh(more_win);
}
return 0;
@@ -706,7 +723,7 @@ static int more_cat(const char *path, void (*loop)(FILE *))
static void more_exit(void)
{
- endwin();
+ tcsetattr(fileno(more_in), TCSANOW, &more_term);
}
int main(int argc, char *argv[])
@@ -722,7 +739,7 @@ int main(int argc, char *argv[])
while ((c = getopt(argc, argv, "ceisun:p:t:")) != -1) {
switch (c) {
case 'c':
- more_clear = 1;
+ more_clear(ENABLE);
break;
case 'e':
@@ -742,7 +759,7 @@ int main(int argc, char *argv[])
break;
case 'n':
- setenv("LINES", optarg, 1);
+ more_lines = atoi(optarg);
break;
case 'p':
@@ -767,30 +784,33 @@ int main(int argc, char *argv[])
return ret;
}
- if (newterm(NULL, stdout, stderr) == NULL) {
- FILE *tty = fopen("/dev/tty", "r");
- if (tty == NULL) {
- perror("more: couldn't open terminal");
- return 1;
- }
- if (newterm(NULL, stdout, tty) == NULL) {
- perror("more: couldn't open terminal");
- return 1;
- }
+ more_in = stderr;
+ if (1 || read(fileno(more_in), NULL, 0) == -1) {
+ more_in = fopen("/dev/tty", "r");
}
- cbreak();
- atexit(more_exit);
+ setbuf(more_in, NULL);
+ tcgetattr(fileno(more_in), &more_term);
+ struct termios tinit = more_term;
+ tinit.c_lflag &= ~(ECHO | ICANON);
+ tinit.c_cc[VMIN] = 1;
+ tinit.c_cc[VTIME] = 0;
+ tcsetattr(fileno(more_in), TCSANOW, &tinit);
+
+ if (more_in == NULL) {
+ perror("more: can't read commands");
+ return 1;
+ }
- more_win = newwin(LINES - 1, 0, 0, 0);
- scrollok(more_win, TRUE);
- more_status = newwin(1, 0, LINES - 1, 0);
- touchwin(stdscr);
+ atexit(more_exit);
- if (more_clear) {
- clear();
+ char *lines = getenv("LINES");
+ if (lines) {
+ more_lines = atoi(lines);
}
+ more_clear(CLEAR);
+
struct more_file *head = NULL;
do {
struct more_file *mf = calloc(1, sizeof(*mf));