commit cc5e34a83e8cb8c2867cdd76610ccd26277c9f16
parent 604ed6a27d1cf55643b747cb5f65bad5c325badc
Author: hhvn <dev@hhvn.uk>
Date: Wed, 15 Dec 2021 17:55:37 +0000
s/commands.c s/ui.c s/hist.c s/struct.h: /scroll for main window
Diffstat:
4 files changed, 77 insertions(+), 8 deletions(-)
diff --git a/src/commands.c b/src/commands.c
@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
+#include <ctype.h>
#include <regex.h>
#include <pwd.h>
#include <sys/types.h>
@@ -47,6 +49,7 @@ static void command_echo(struct Server *server, char *str);
static void command_grep(struct Server *server, char *str);
static void command_clear(struct Server *server, char *str);
static void command_alias(struct Server *server, char *str);
+static void command_scroll(struct Server *server, char *str);
static char *command_optarg;
enum {
@@ -138,6 +141,11 @@ struct Command commands[] = {
"usage: /alias [<alias> [cmd [...]]]",
" /alias -delete <alias>",
"Add or remove an alias that expands to a command.", NULL}},
+ {"scroll", command_scroll, 0, {
+ "usage: /scroll [-buflist] [-nicklist] [-|+]lines",
+ "Scroll a window (main by default).",
+ "Positive scrolls up, negative down, 0 resets and tracks",
+ "Probably most useful with /bind", NULL}},
{NULL, NULL},
};
@@ -876,6 +884,54 @@ command_clear(struct Server *server, char *str) {
windows[Win_main].refresh = 1;
}
+static void
+command_scroll(struct Server *server, char *str) {
+ int ret, winid = Win_main;
+ long diff;
+ enum { opt_buflist, opt_nicklist };
+ static struct CommandOpts opts[] = {
+ {"buflist", CMD_NARG, opt_buflist},
+ {"nicklist", CMD_NARG, opt_nicklist},
+ {NULL, 0, 0},
+ };
+
+ if (!str)
+ goto narg;
+
+ while (!(*str == '-' && isdigit(*(str+1))) && (ret = command_getopt(&str, opts)) != opt_done) {
+ switch (ret) {
+ case opt_error:
+ return;
+ case opt_buflist:
+ winid = Win_buflist;
+ break;
+ case opt_nicklist:
+ winid = Win_nicklist;
+ break;
+ }
+
+ if (*str == '-' && isdigit(*(str+1)))
+ break;
+ }
+
+ if (!*str)
+ goto narg;
+
+ diff = strtol(str, NULL, 10);
+ if (diff == 0 || diff == LONG_MIN)
+ windows[winid].scroll = -1; /* no scroll, tracking */
+ else if (windows[winid].scroll >= 0)
+ windows[winid].scroll += diff;
+ else
+ windows[winid].scroll = diff;
+
+ windows[winid].refresh = 1;
+ return;
+
+narg:
+ ui_error("/scroll requires argument", NULL);
+}
+
int
command_getopt(char **str, struct CommandOpts *opts) {
char *opt;
diff --git a/src/hist.c b/src/hist.c
@@ -123,8 +123,13 @@ hist_add(struct HistInfo *histinfo, struct Nick *from,
histinfo->history = new;
/* TODO: this triggers way too often, need to have some sort of delay */
- if (selected.history == histinfo)
+ if (selected.history == histinfo) {
+ if (options & HIST_SELF)
+ windows[Win_main].scroll = -1;
+ else if (windows[Win_main].scroll >= 0)
+ windows[Win_main].scroll += 1;
windows[Win_main].refresh = 1;
+ }
if (options & HIST_LOG) {
if (histinfo->server)
diff --git a/src/struct.h b/src/struct.h
@@ -210,6 +210,7 @@ struct Window {
int x, y;
int h, w;
int refresh;
+ int scroll;
enum WindowLocation location;
void (*handler)(void);
WINDOW *window;
diff --git a/src/ui.c b/src/ui.c
@@ -53,11 +53,11 @@ static unsigned short colourmap[HIRC_COLOURS] = {
};
struct Window windows[Win_last] = {
- [Win_dummy] = {.handler = NULL},
- [Win_main] = {.handler = ui_draw_main},
- [Win_input] = {.handler = ui_draw_input},
- [Win_nicklist] = {.handler = ui_draw_nicklist},
- [Win_buflist] = {.handler = ui_draw_buflist},
+ [Win_dummy] = {.handler = NULL, .scroll = -1},
+ [Win_main] = {.handler = ui_draw_main, .scroll = -1},
+ [Win_input] = {.handler = ui_draw_input, .scroll = -1},
+ [Win_nicklist] = {.handler = ui_draw_nicklist, .scroll = -1},
+ [Win_buflist] = {.handler = ui_draw_buflist, .scroll = -1},
};
struct {
@@ -284,6 +284,7 @@ ui_init(void) {
use_default_colors();
raw();
noecho();
+ nonl(); /* get ^j */
input.string[0] = '\0';
memset(input.history, 0, sizeof(input.history));
@@ -432,7 +433,8 @@ ui_read(void) {
if (input.string[input.counter])
input.counter++;
break;
- case '\n':
+ case KEY_ENTER:
+ case '\r':
command_eval(input.string);
/* free checks for null */
free(input.history[INPUT_HIST_MAX - 1]);
@@ -1089,11 +1091,15 @@ void
ui_draw_main(void) {
struct History *p;
int y, lines;
+ int i;
ui_wclear(&windows[Win_main]);
+ for (i=0, p = selected.history->history; p && p->next && i < windows[Win_main].scroll; i++)
+ p = p->next;
+
y = windows[Win_main].h;
- for (p = selected.history->history; p && y > 0; p = p->next) {
+ for (; p && y > 0; p = p->next) {
if (!(p->options & HIST_SHOW))
continue;
if (ui_hist_len(&windows[Win_main], p, &lines) <= 0)
@@ -1133,6 +1139,7 @@ ui_select(struct Server *server, struct Channel *channel) {
windows[Win_nicklist].location = HIDDEN;
else
windows[Win_nicklist].location = config_getl("nicklist.location");
+ windows[Win_main].scroll = -1;
ui_redraw();
}