summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-04-18 19:12:52 -0400
committerJakob Kaivo <jkk@ung.org>2022-04-18 19:12:52 -0400
commit1fa82850d87a0f5526153655a2368c46ea447a90 (patch)
tree5ffd8c628a4a221b93cd68b36ec82b6e182bd314
parent344424ffafe5e3b310b5595d897579544abdb90d (diff)
switch to curses
-rw-r--r--Makefile11
-rw-r--r--io.c12
-rw-r--r--more.c107
-rw-r--r--more.h6
-rw-r--r--tty.c77
5 files changed, 78 insertions, 135 deletions
diff --git a/Makefile b/Makefile
index 382ed04..58e1d8a 100644
--- a/Makefile
+++ b/Makefile
@@ -8,16 +8,20 @@ CC=c99
LD=$(CC)
CFLAGS=-Wall -Wextra -Wpedantic -Werror -g
LDFLAGS=
-LDLIBS=
+LDLIBS=-lcurses
SRCDIR=.
OBJDIR=.
BINDIR=$(OBJDIR)
+DESTDIR=/usr/local
all: $(BINDIR)/more
clean:
rm -f $(BINDIR)/more $(OBJDIR)/*.o
+install: $(BINDIR)/more
+ cp $(BINDIR)/more $(DESTDIR)/bin
+
$(BINDIR)/more: $(OBJDIR)/io.o
$(OBJDIR)/io.o: $(SRCDIR)/more.h
$(OBJDIR)/io.o: $(SRCDIR)/io.c
@@ -28,10 +32,5 @@ $(OBJDIR)/more.o: $(SRCDIR)/more.h
$(OBJDIR)/more.o: $(SRCDIR)/more.c
$(CC) $(CFLAGS) -o $@ -c $(SRCDIR)/more.c
-$(BINDIR)/more: $(OBJDIR)/tty.o
-$(OBJDIR)/tty.o: $(SRCDIR)/more.h
-$(OBJDIR)/tty.o: $(SRCDIR)/tty.c
- $(CC) $(CFLAGS) -o $@ -c $(SRCDIR)/tty.c
-
$(BINDIR)/more:
$(LD) $(LDFLAGS) -o $@ $(OBJDIR)/*.o $(LDLIBS)
diff --git a/io.c b/io.c
index a253792..2de9a7d 100644
--- a/io.c
+++ b/io.c
@@ -11,16 +11,16 @@
ssize_t more_getline(struct more_file *mf, size_t lineno)
{
if (mf->nlines <= lineno && mf->nlines != 0) {
- fsetpos(mf->f, &(mf->lines[mf->nlines - 1]));
+ fsetpos(mf->f, &(mf->tlines[mf->nlines - 1]));
getline(&(mf->buf), &(mf->nbuf), mf->f);
}
while (mf->nlines <= lineno) {
mf->nlines++;
- mf->lines = realloc(mf->lines, mf->nlines * sizeof(*mf->lines));
+ mf->tlines = realloc(mf->tlines, mf->nlines * sizeof(*mf->tlines));
mf->bytepos = realloc(mf->bytepos, mf->nlines * sizeof(*mf->bytepos));
- fgetpos(mf->f, &(mf->lines[mf->nlines - 1]));
+ fgetpos(mf->f, &(mf->tlines[mf->nlines - 1]));
getline(&(mf->buf), &(mf->nbuf), mf->f);
if (mf->nlines > 1) {
@@ -30,12 +30,12 @@ ssize_t more_getline(struct more_file *mf, size_t lineno)
}
if (mf->backing != mf->f) {
- fgetpos(mf->backing, &(mf->lines[mf->nlines - 1]));
+ fgetpos(mf->backing, &(mf->tlines[mf->nlines - 1]));
fputs(mf->buf, mf->backing);
}
}
- fsetpos(mf->backing, &(mf->lines[lineno]));
+ fsetpos(mf->backing, &(mf->tlines[lineno]));
return getline(&(mf->buf), &(mf->nbuf), mf->backing);
}
@@ -76,6 +76,6 @@ void more_close(struct more_file *mf)
fclose(mf->f);
}
- free(mf->lines);
+ free(mf->tlines);
free(mf->buf);
}
diff --git a/more.c b/more.c
index 108f70b..8b67540 100644
--- a/more.c
+++ b/more.c
@@ -1,9 +1,11 @@
#define _XOPEN_SOURCE 700
+#include <curses.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <term.h>
#include <unistd.h>
#include "more.h"
@@ -19,22 +21,23 @@ enum {
CTRL_U = 0x15,
};
-void refresh(const struct more_tty *mt, struct more_file *mf)
+void man_refresh(struct more_file *mf)
{
- for (size_t i = mf->topline; i < mf->topline + mt->lines; i++) {
+ for (size_t i = mf->topline; i < mf->topline + LINES - 1; i++) {
/* FIXME: account for long lines */
if (more_getline(mf, i) == -1) {
break;
}
- printf("%s", mf->buf);
+ printw("%s", mf->buf);
}
}
-void scroll(const struct more_tty *mt, struct more_file *mf, int count, int multiple)
+void man_scroll(struct more_file *mf, int count, int multiple)
{
int by = count ? count * multiple : multiple;
+ scrl(by);
if (by < 0) {
if ((size_t)(-by) > mf->topline) {
@@ -42,36 +45,38 @@ void scroll(const struct more_tty *mt, struct more_file *mf, int count, int mult
} else {
mf->topline += by;
}
- refresh(mt, mf);
+ man_refresh(mf);
} else while (by-- > 0) {
/* FIXME: account for long lines here, too */
mf->topline++;
- if (more_getline(mf, mf->topline + mt->lines + 1) < 0) {
+ if (more_getline(mf, mf->topline + LINES + 1) < 0) {
break;
}
- printf("%s", mf->buf);
+ printw("%s", mf->buf);
}
+
+ refresh();
}
-void mark(const struct more_tty *mt, struct more_file *mf)
+void mark(struct more_file *mf)
{
- int c = fgetc(mt->tty);
+ int c = getch();
if (islower(c)) {
mf->mark[c - 'a'] = mf->topline;
}
}
-void jump(const struct more_tty *mt, struct more_file *mf)
+void jump(struct more_file *mf)
{
- int c = fgetc(mt->tty);
+ int c = getch();
if (islower(c)) {
mf->topline = mf->mark[c - 'a'];
- refresh(mt, mf);
+ man_refresh(mf);
}
}
-int more(const struct more_tty *mt, const char *path)
+static int more(const char *path)
{
struct more_file mf = more_open(path);
@@ -80,11 +85,11 @@ int more(const struct more_tty *mt, const char *path)
return 1;
}
- refresh(mt, &mf);
+ man_refresh(&mf);
int count = 0;
while (mf.f) {
- int c = fgetc(mt->tty);
+ int c = getch();
switch (c) {
case EOF:
@@ -93,50 +98,50 @@ int more(const struct more_tty *mt, const char *path)
case 'h':
//show_help();
- printf("Help!");
+ printw("Help!");
break;
case 'f':
case CTRL_F:
if (count == 0) {
- count = mt->lines;
+ count = LINES;
}
- scroll(mt, &mf, count, 1);
+ man_scroll(&mf, count, 1);
break;
case 'b':
case CTRL_B:
if (count == 0) {
- count = mt->lines;
+ count = LINES;
}
- scroll(mt, &mf, count, -1);
+ man_scroll(&mf, count, -1);
break;
case ' ':
- count = count ? count : mt->lines;
+ count = count ? count : LINES;
/* FALLTHRU */
case 'j':
case '\n':
- scroll(mt, &mf, count, 1);
+ man_scroll(&mf, count, 1);
break;
case 'k':
- scroll(mt, &mf, count, -1);
+ man_scroll(&mf, count, -1);
break;
case 'd':
case CTRL_D:
- scroll(mt, &mf, count, mt->lines / 2);
+ man_scroll(&mf, count, LINES / 2);
break;
case 's':
count = count ? count : 1;
- scroll(mt, &mf, mt->lines + count, 1);
+ man_scroll(&mf, LINES + count, 1);
break;
case 'u':
case CTRL_U:
- scroll(mt, &mf, count, -mt->lines / 2);
+ man_scroll(&mf, count, -LINES / 2);
break;
case 'G':
@@ -145,7 +150,7 @@ int more(const struct more_tty *mt, const char *path)
}
/* FALLTHRU */
case 'g':
- scroll(mt, &mf, count - mf.topline, 1);
+ man_scroll(&mf, count - mf.topline, 1);
break;
case 'R':
@@ -153,15 +158,15 @@ int more(const struct more_tty *mt, const char *path)
/* FALLTHRU */
case 'r':
case CTRL_L:
- refresh(mt, &mf);
+ man_refresh(&mf);
break;
case 'm':
- mark(mt, &mf);
+ mark(&mf);
break;
case '\'':
- jump(mt, &mf);
+ jump(&mf);
break;
case '/':
@@ -181,9 +186,13 @@ int more(const struct more_tty *mt, const char *path)
break;
case ':': {
- fputc(c, mt->tty);
- int c2 = fgetc(mt->tty);
- fprintf(mt->tty, "\b \b");
+ addch(c);
+ echo();
+ int c2 = getch();
+ noecho();
+
+ printw("\b \b");
+
switch (c2) {
case 'e':
// examine();
@@ -215,11 +224,11 @@ int more(const struct more_tty *mt, const char *path)
case '=':
case CTRL_G:
- printf("%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", path, 0, 0, mf.topline, mf.bytepos[mf.topline], mf.nbytes, 100 * mf.bytepos[mf.topline] / mf.nbytes);
+ printw("%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", path, 0, 0, mf.topline, mf.bytepos[mf.topline], mf.nbytes, 100 * mf.bytepos[mf.topline] / mf.nbytes);
break;
case 'Z':
- if (fgetc(mt->tty) != 'Z') {
+ if (getch() != 'Z') {
break;
}
/* FALLTHRU */
@@ -245,6 +254,8 @@ int more(const struct more_tty *mt, const char *path)
if (!isdigit(c)) {
count = 0;
}
+
+ refresh();
}
more_close(&mf);
@@ -332,6 +343,11 @@ static int more_cat(const char *path, void (*loop)(FILE *))
return 0;
}
+static void more_exit(void)
+{
+ endwin();
+}
+
int main(int argc, char *argv[])
{
int c;
@@ -341,7 +357,6 @@ int main(int argc, char *argv[])
int ignorecase = 0;
int compressempty = 0;
int backspace = 1;
- int lines = 0;
adjust_args(&argc, &argv);
@@ -368,7 +383,7 @@ int main(int argc, char *argv[])
break;
case 'n':
- lines = atoi(optarg);
+ setenv("LINES", optarg, 1);
break;
case 'p':
@@ -393,16 +408,25 @@ int main(int argc, char *argv[])
return ret;
}
- struct more_tty mt = more_open_tty(lines);
-
if (optind >= argc) {
- more(&mt, "-");
+ more("-");
+ }
+
+ initscr();
+ cbreak();
+ noecho();
+ scrollok(stdscr, TRUE);
+
+ atexit(more_exit);
+
+ if (clear) {
+ clear();
}
int min = optind;
int max = argc - 1;
while (optind < argc) {
- int next = more(&mt, argv[optind]);
+ int next = more(argv[optind]);
optind += next;
if (optind < min) {
optind = min;
@@ -412,7 +436,6 @@ int main(int argc, char *argv[])
}
}
- (void)clear;
(void)fastexit;
(void)ignorecase;
(void)backspace;
diff --git a/more.h b/more.h
index 27e7e7a..534dca7 100644
--- a/more.h
+++ b/more.h
@@ -3,15 +3,13 @@
struct more_tty {
FILE *tty;
- int lines;
- int columns;
};
struct more_file {
FILE *f;
FILE *backing;
size_t topline;
- fpos_t *lines;
+ fpos_t *tlines;
size_t nlines;
size_t mark[26];
size_t nbytes;
@@ -20,7 +18,7 @@ struct more_file {
size_t nbuf;
};
-struct more_tty more_open_tty(int lines);
+struct more_tty more_open_tty(int nlines);
struct more_file more_open(const char *path);
void more_close(struct more_file *mf);
ssize_t more_getline(struct more_file *mf, size_t lineno);
diff --git a/tty.c b/tty.c
deleted file mode 100644
index 3752cd7..0000000
--- a/tty.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#define _XOPEN_SOURCE 700
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <termios.h>
-
-#include "more.h"
-
-static FILE *resetty = NULL;
-static struct termios resettings = { 0 };
-
-static void resetterm(void)
-{
- tcsetattr(fileno(resetty), TCSANOW, &resettings);
-}
-
-static int query_term(const char *cap, const char *variable, int def)
-{
- int n = 0;
- char cmd[64];
- snprintf(cmd, sizeof(cmd), "tput %s", cap);
- FILE *f = popen(cmd, "r");
- if (f) {
- if (fscanf(f, "%d", &n) != 1) {
- n = 0;
- }
- pclose(f);
- if (n != 0) {
- return n;
- }
- }
-
- char *value = getenv(variable);
- if (value) {
- n = atoi(value);
- }
- return n ? n : def;
-}
-
-struct more_tty more_open_tty(int lines)
-{
- struct more_tty mt = {
- .tty = stderr,
- .lines = query_term("lines", "LINES", 24),
- .columns = query_term("cols", "COLUMNS", 80),
- };
-
- if (lines > 0) {
- mt.lines = lines;
- }
-
- /* leave room for prompts */
- lines--;
-
- /* FIXME: only open /dev/tty if stderr is not readable */
- // if (!(fcntl(fileno(mt.tty), F_GETFL) & (O_WRONLY | O_RDWR))) {
- mt.tty = fopen("/dev/tty", "rb+");
- // }
- if (mt.tty == NULL) {
- perror("Couldn't open tty for reading");
- exit(1);
- }
-
- setbuf(mt.tty, NULL);
-
- tcgetattr(fileno(mt.tty), &resettings);
- struct termios term = resettings;
- term.c_lflag &= ~(ECHO | ICANON);
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
- tcsetattr(fileno(mt.tty), TCSANOW, &term);
-
- resetty = mt.tty;
- atexit(resetterm);
-
- return mt;
-}