Reflow text on window resize
This commit is contained in:
		
							parent
							
								
									7414a8a11c
								
							
						
					
					
						commit
						42210e079b
					
				
							
								
								
									
										2
									
								
								chat.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								chat.c
									
									
									
									
									
								
							@ -122,6 +122,8 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
		if (signals[SIGHUP] || signals[SIGINT] || signals[SIGTERM]) {
 | 
							if (signals[SIGHUP] || signals[SIGINT] || signals[SIGTERM]) {
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// FIXME: Display doesn't update properly when receiving many of these
 | 
				
			||||||
 | 
							// until some input?
 | 
				
			||||||
		if (signals[SIGWINCH]) {
 | 
							if (signals[SIGWINCH]) {
 | 
				
			||||||
			signals[SIGWINCH] = 0;
 | 
								signals[SIGWINCH] = 0;
 | 
				
			||||||
			cursesWinch(SIGWINCH);
 | 
								cursesWinch(SIGWINCH);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								ui.c
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								ui.c
									
									
									
									
									
								
							@ -35,6 +35,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "chat.h"
 | 
					#include "chat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Annoying stuff from <term.h>:
 | 
				
			||||||
 | 
					#undef lines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef A_ITALIC
 | 
					#ifndef A_ITALIC
 | 
				
			||||||
#define A_ITALIC A_UNDERLINE
 | 
					#define A_ITALIC A_UNDERLINE
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -43,16 +46,28 @@
 | 
				
			|||||||
#define RIGHT (COLS - 1)
 | 
					#define RIGHT (COLS - 1)
 | 
				
			||||||
#define WINDOW_LINES (LINES - 2)
 | 
					#define WINDOW_LINES (LINES - 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	InputCols = 512,
 | 
					 | 
				
			||||||
	PadLines = 512,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static WINDOW *status;
 | 
					static WINDOW *status;
 | 
				
			||||||
static WINDOW *input;
 | 
					static WINDOW *input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum { BufferCap = 512 };
 | 
				
			||||||
 | 
					struct Buffer {
 | 
				
			||||||
 | 
						time_t times[BufferCap];
 | 
				
			||||||
 | 
						char *lines[BufferCap];
 | 
				
			||||||
 | 
						size_t len;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static_assert(!(BufferCap & (BufferCap - 1)), "BufferCap is power of two");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bufferPush(struct Buffer *buffer, time_t time, const char *line) {
 | 
				
			||||||
 | 
						size_t i = buffer->len++ % BufferCap;
 | 
				
			||||||
 | 
						free(buffer->lines[i]);
 | 
				
			||||||
 | 
						buffer->times[i] = time;
 | 
				
			||||||
 | 
						buffer->lines[i] = strdup(line);
 | 
				
			||||||
 | 
						if (!buffer->lines[i]) err(EX_OSERR, "strdup");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Window {
 | 
					struct Window {
 | 
				
			||||||
	size_t id;
 | 
						size_t id;
 | 
				
			||||||
 | 
						struct Buffer buffer;
 | 
				
			||||||
	WINDOW *pad;
 | 
						WINDOW *pad;
 | 
				
			||||||
	enum Heat heat;
 | 
						enum Heat heat;
 | 
				
			||||||
	int unread;
 | 
						int unread;
 | 
				
			||||||
@ -89,17 +104,15 @@ static struct Window *windowFor(size_t id) {
 | 
				
			|||||||
	for (window = windows.head; window; window = window->next) {
 | 
						for (window = windows.head; window; window = window->next) {
 | 
				
			||||||
		if (window->id == id) return window;
 | 
							if (window->id == id) return window;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	window = malloc(sizeof(*window));
 | 
						window = calloc(1, sizeof(*window));
 | 
				
			||||||
	if (!window) err(EX_OSERR, "malloc");
 | 
						if (!window) err(EX_OSERR, "malloc");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window->id = id;
 | 
						window->id = id;
 | 
				
			||||||
	window->pad = newpad(PadLines, COLS);
 | 
						window->pad = newpad(BufferCap, COLS);
 | 
				
			||||||
	window->heat = Cold;
 | 
					 | 
				
			||||||
	window->unread = 0;
 | 
					 | 
				
			||||||
	window->scroll = PadLines;
 | 
					 | 
				
			||||||
	window->mark = true;
 | 
					 | 
				
			||||||
	scrollok(window->pad, true);
 | 
						scrollok(window->pad, true);
 | 
				
			||||||
	wmove(window->pad, PadLines - 1, 0);
 | 
						wmove(window->pad, BufferCap - 1, 0);
 | 
				
			||||||
 | 
						window->scroll = BufferCap;
 | 
				
			||||||
 | 
						window->mark = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	windowAdd(window);
 | 
						windowAdd(window);
 | 
				
			||||||
	return window;
 | 
						return window;
 | 
				
			||||||
@ -190,7 +203,7 @@ void uiInit(void) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	colorInit();
 | 
						colorInit();
 | 
				
			||||||
	status = newwin(1, COLS, 0, 0);
 | 
						status = newwin(1, COLS, 0, 0);
 | 
				
			||||||
	input = newpad(1, InputCols);
 | 
						input = newpad(1, 512);
 | 
				
			||||||
	keypad(input, true);
 | 
						keypad(input, true);
 | 
				
			||||||
	nodelay(input, true);
 | 
						nodelay(input, true);
 | 
				
			||||||
	windows.active = windowFor(Network);
 | 
						windows.active = windowFor(Network);
 | 
				
			||||||
@ -380,9 +393,11 @@ static void wordWrap(WINDOW *win, const char *str) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void uiWrite(size_t id, enum Heat heat, const time_t *time, const char *str) {
 | 
					void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) {
 | 
				
			||||||
	(void)time;
 | 
					 | 
				
			||||||
	struct Window *window = windowFor(id);
 | 
						struct Window *window = windowFor(id);
 | 
				
			||||||
 | 
						time_t clock = (src ? *src : time(NULL));
 | 
				
			||||||
 | 
						bufferPush(&window->buffer, clock, str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	waddch(window->pad, '\n');
 | 
						waddch(window->pad, '\n');
 | 
				
			||||||
	if (window->mark && heat > Cold) {
 | 
						if (window->mark && heat > Cold) {
 | 
				
			||||||
		if (!window->unread++) {
 | 
							if (!window->unread++) {
 | 
				
			||||||
@ -406,6 +421,25 @@ void uiFormat(
 | 
				
			|||||||
	uiWrite(id, heat, time, buf);
 | 
						uiWrite(id, heat, time, buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void reflow(struct Window *window) {
 | 
				
			||||||
 | 
						werase(window->pad);
 | 
				
			||||||
 | 
						wmove(window->pad, BufferCap - 1, 0);
 | 
				
			||||||
 | 
						size_t len = window->buffer.len;
 | 
				
			||||||
 | 
						for (size_t i = (len > BufferCap ? len - BufferCap : 0); i < len; ++i) {
 | 
				
			||||||
 | 
							waddch(window->pad, '\n');
 | 
				
			||||||
 | 
							wordWrap(window->pad, window->buffer.lines[i % BufferCap]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void resize(void) {
 | 
				
			||||||
 | 
						// FIXME: Only reflow when COLS changes.
 | 
				
			||||||
 | 
						for (struct Window *window = windows.head; window; window = window->next) {
 | 
				
			||||||
 | 
							wresize(window->pad, BufferCap, COLS);
 | 
				
			||||||
 | 
							reflow(window);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						statusUpdate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void inputAdd(struct Style *style, const char *str) {
 | 
					static void inputAdd(struct Style *style, const char *str) {
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
	while (*str) {
 | 
						while (*str) {
 | 
				
			||||||
@ -480,7 +514,7 @@ void uiShowNum(size_t num) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void keyCode(int code) {
 | 
					static void keyCode(int code) {
 | 
				
			||||||
	switch (code) {
 | 
						switch (code) {
 | 
				
			||||||
		break; case KEY_RESIZE:; // TODO
 | 
							break; case KEY_RESIZE:  resize();
 | 
				
			||||||
		break; case KeyFocusIn:  unmark();
 | 
							break; case KeyFocusIn:  unmark();
 | 
				
			||||||
		break; case KeyFocusOut: windows.active->mark = true;
 | 
							break; case KeyFocusOut: windows.active->mark = true;
 | 
				
			||||||
		break; case KeyPasteOn:; // TODO
 | 
							break; case KeyPasteOn:; // TODO
 | 
				
			||||||
@ -490,7 +524,7 @@ static void keyCode(int code) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void keyMeta(wchar_t ch) {
 | 
					static void keyMeta(wchar_t ch) {
 | 
				
			||||||
	switch (ch) {
 | 
						switch (ch) {
 | 
				
			||||||
		break; case L'm': uiWrite(windows.active->id, Cold, NULL, "");
 | 
							break; case L'm': waddch(windows.active->pad, '\n');
 | 
				
			||||||
		break; default: {
 | 
							break; default: {
 | 
				
			||||||
			if (ch >= L'0' && ch <= L'9') uiShowNum(ch - L'0');
 | 
								if (ch >= L'0' && ch <= L'9') uiShowNum(ch - L'0');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user