Store line heat in buffer

master
C. McEnroe 2020-03-31 14:07:21 -04:00
parent 13ae7cec59
commit bfa106b9a0
1 changed files with 38 additions and 35 deletions

73
ui.c
View File

@ -53,26 +53,31 @@ static WINDOW *status;
static WINDOW *marker; static WINDOW *marker;
static WINDOW *input; static WINDOW *input;
struct Line {
enum Heat heat;
time_t time;
char *str;
};
enum { BufferCap = 1024 }; enum { BufferCap = 1024 };
struct Buffer { struct Buffer {
time_t times[BufferCap];
char *lines[BufferCap];
size_t len; size_t len;
struct Line lines[BufferCap];
}; };
static_assert(!(BufferCap & (BufferCap - 1)), "BufferCap is power of two"); static_assert(!(BufferCap & (BufferCap - 1)), "BufferCap is power of two");
static void bufferPush(struct Buffer *buffer, time_t time, const char *line) { static void bufferPush(
size_t i = buffer->len++ % BufferCap; struct Buffer *buffer, enum Heat heat, time_t time, const char *str
free(buffer->lines[i]); ) {
buffer->times[i] = time; struct Line *line = &buffer->lines[buffer->len++ % BufferCap];
buffer->lines[i] = strdup(line); free(line->str);
if (!buffer->lines[i]) err(EX_OSERR, "strdup"); line->heat = heat;
line->time = time;
line->str = strdup(str);
if (!line->str) err(EX_OSERR, "strdup");
} }
static time_t bufferTime(const struct Buffer *buffer, size_t i) { static struct Line bufferLine(const struct Buffer *buffer, size_t i) {
return buffer->times[(buffer->len + i) % BufferCap];
}
static const char *bufferLine(const struct Buffer *buffer, size_t i) {
return buffer->lines[(buffer->len + i) % BufferCap]; return buffer->lines[(buffer->len + i) % BufferCap];
} }
@ -147,7 +152,7 @@ static uint windowFor(uint id) {
static void windowFree(struct Window *window) { static void windowFree(struct Window *window) {
for (size_t i = 0; i < BufferCap; ++i) { for (size_t i = 0; i < BufferCap; ++i) {
free(window->buffer.lines[i]); free(window->buffer.lines[i].str);
} }
delwin(window->pad); delwin(window->pad);
free(window); free(window);
@ -407,7 +412,7 @@ static void statusUpdate(void) {
wmove(status, 0, 0); wmove(status, 0, 0);
for (uint num = 0; num < windows.len; ++num) { for (uint num = 0; num < windows.len; ++num) {
const struct Window *window = windows.ptrs[num]; const struct Window *window = windows.ptrs[num];
if (!window->heat && num != windows.show) continue; if (window->heat < Warm && num != windows.show) continue;
if (num != windows.show) { if (num != windows.show) {
others.unread += window->unreadWarm; others.unread += window->unreadWarm;
if (window->heat > others.heat) others.heat = window->heat; if (window->heat > others.heat) others.heat = window->heat;
@ -581,7 +586,7 @@ static void notify(uint id, const char *str) {
void uiWrite(uint id, enum Heat heat, const time_t *src, const char *str) { void uiWrite(uint id, enum Heat heat, const time_t *src, const char *str) {
struct Window *window = windows.ptrs[windowFor(id)]; struct Window *window = windows.ptrs[windowFor(id)];
time_t ts = (src ? *src : time(NULL)); time_t ts = (src ? *src : time(NULL));
bufferPush(&window->buffer, ts, str); bufferPush(&window->buffer, heat, ts, str);
int lines = 0; int lines = 0;
window->unread++; window->unread++;
@ -623,9 +628,9 @@ static void reflow(struct Window *window) {
int flowed = 0; int flowed = 0;
window->unreadLines = 0; window->unreadLines = 0;
for (size_t i = 0; i < BufferCap; ++i) { for (size_t i = 0; i < BufferCap; ++i) {
const char *line = bufferLine(&window->buffer, i); struct Line line = bufferLine(&window->buffer, i);
if (!line) continue; if (!line.str) continue;
int lines = wordWrap(window->pad, line); int lines = wordWrap(window->pad, line.str);
if (i >= (size_t)(BufferCap - window->unread)) { if (i >= (size_t)(BufferCap - window->unread)) {
window->unreadLines += lines; window->unreadLines += lines;
} }
@ -656,11 +661,10 @@ static void bufferList(const struct Buffer *buffer) {
waiting = true; waiting = true;
for (size_t i = 0; i < BufferCap; ++i) { for (size_t i = 0; i < BufferCap; ++i) {
const char *line = bufferLine(buffer, i); struct Line line = bufferLine(buffer, i);
if (!line) continue; if (!line.str) continue;
time_t time = bufferTime(buffer, i); struct tm *tm = localtime(&line.time);
struct tm *tm = localtime(&time);
if (!tm) err(EX_OSERR, "localtime"); if (!tm) err(EX_OSERR, "localtime");
char buf[sizeof("00:00:00")]; char buf[sizeof("00:00:00")];
@ -670,15 +674,15 @@ static void bufferList(const struct Buffer *buffer) {
bool align = false; bool align = false;
struct Style style = Reset; struct Style style = Reset;
while (*line) { while (*line.str) {
if (*line == '\t') { if (*line.str == '\t') {
printf("%c", (align ? '\t' : ' ')); printf("%c", (align ? '\t' : ' '));
align = true; align = true;
line++; line.str++;
} }
size_t len = styleParse(&style, &line); size_t len = styleParse(&style, (const char **)&line.str);
size_t tab = strcspn(line, "\t"); size_t tab = strcspn(line.str, "\t");
if (tab < len) len = tab; if (tab < len) len = tab;
vid_attr( vid_attr(
@ -686,8 +690,8 @@ static void bufferList(const struct Buffer *buffer) {
colorPair(Colors[style.fg], Colors[style.bg]), colorPair(Colors[style.fg], Colors[style.bg]),
NULL NULL
); );
printf("%.*s", (int)len, line); printf("%.*s", (int)len, line.str);
line += len; line.str += len;
} }
printf("\n"); printf("\n");
} }
@ -1004,11 +1008,10 @@ int uiSave(const char *name) {
if (writeTime(file, window->unread)) return -1; if (writeTime(file, window->unread)) return -1;
if (writeTime(file, window->unreadWarm)) return -1; if (writeTime(file, window->unreadWarm)) return -1;
for (size_t i = 0; i < BufferCap; ++i) { for (size_t i = 0; i < BufferCap; ++i) {
time_t time = bufferTime(&window->buffer, i); struct Line line = bufferLine(&window->buffer, i);
const char *line = bufferLine(&window->buffer, i); if (!line.str) continue;
if (!line) continue; if (writeTime(file, line.time)) return -1;
if (writeTime(file, time)) return -1; if (writeString(file, line.str)) return -1;
if (writeString(file, line)) return -1;
} }
if (writeTime(file, 0)) return -1; if (writeTime(file, 0)) return -1;
} }
@ -1064,7 +1067,7 @@ void uiLoad(const char *name) {
time_t time = readTime(file); time_t time = readTime(file);
if (!time) break; if (!time) break;
readString(file, &buf, &cap); readString(file, &buf, &cap);
bufferPush(&window->buffer, time, buf); bufferPush(&window->buffer, Cold, time, buf);
} }
reflow(window); reflow(window);
waddch(window->pad, '\n'); waddch(window->pad, '\n');