Various small cleanup in ui.c
This commit is contained in:
		
							parent
							
								
									460207440b
								
							
						
					
					
						commit
						026a8ca979
					
				
							
								
								
									
										197
									
								
								ui.c
									
									
									
									
									
								
							
							
						
						
									
										197
									
								
								ui.c
									
									
									
									
									
								
							| @ -79,14 +79,14 @@ static const char *bufferLine(const struct Buffer *buffer, size_t i) { | ||||
| enum { WindowLines = BufferCap }; | ||||
| struct Window { | ||||
| 	uint id; | ||||
| 	struct Buffer buffer; | ||||
| 	WINDOW *pad; | ||||
| 	int scroll; | ||||
| 	bool mark; | ||||
| 	enum Heat heat; | ||||
| 	uint unreadTotal; | ||||
| 	uint unread; | ||||
| 	uint unreadWarm; | ||||
| 	uint unreadLines; | ||||
| 	struct Buffer buffer; | ||||
| }; | ||||
| 
 | ||||
| static struct { | ||||
| @ -186,36 +186,6 @@ static short colorPair(short fg, short bg) { | ||||
| 	return colorPairs++; | ||||
| } | ||||
| 
 | ||||
| // XXX: Assuming terminals will be fine with these even if they're unsupported,
 | ||||
| // since they're "private" modes.
 | ||||
| static const char *EnterFocusMode = "\33[?1004h"; | ||||
| static const char *ExitFocusMode  = "\33[?1004l"; | ||||
| static const char *EnterPasteMode = "\33[?2004h"; | ||||
| static const char *ExitPasteMode  = "\33[?2004l"; | ||||
| 
 | ||||
| // Gain use of C-q, C-s, C-c, C-z, C-y, C-v, C-o.
 | ||||
| static void acquireKeys(void) { | ||||
| 	struct termios term; | ||||
| 	int error = tcgetattr(STDOUT_FILENO, &term); | ||||
| 	if (error) err(EX_OSERR, "tcgetattr"); | ||||
| 	term.c_iflag &= ~IXON; | ||||
| 	term.c_cc[VINTR] = _POSIX_VDISABLE; | ||||
| 	term.c_cc[VSUSP] = _POSIX_VDISABLE; | ||||
| #ifdef VDSUSP | ||||
| 	term.c_cc[VDSUSP] = _POSIX_VDISABLE; | ||||
| #endif | ||||
| 	term.c_cc[VLNEXT] = _POSIX_VDISABLE; | ||||
| 	term.c_cc[VDISCARD] = _POSIX_VDISABLE; | ||||
| 	error = tcsetattr(STDOUT_FILENO, TCSADRAIN, &term); | ||||
| 	if (error) err(EX_OSERR, "tcsetattr"); | ||||
| } | ||||
| 
 | ||||
| static void errExit(void) { | ||||
| 	putp(ExitFocusMode); | ||||
| 	putp(ExitPasteMode); | ||||
| 	reset_shell_mode(); | ||||
| } | ||||
| 
 | ||||
| #define ENUM_KEY \ | ||||
| 	X(KeyMeta0, "\0330", "\33)") \ | ||||
| 	X(KeyMeta1, "\0331", "\33!") \ | ||||
| @ -248,6 +218,36 @@ enum { | ||||
| #undef X | ||||
| }; | ||||
| 
 | ||||
| // Gain use of C-q, C-s, C-c, C-z, C-y, C-v, C-o.
 | ||||
| static void acquireKeys(void) { | ||||
| 	struct termios term; | ||||
| 	int error = tcgetattr(STDOUT_FILENO, &term); | ||||
| 	if (error) err(EX_OSERR, "tcgetattr"); | ||||
| 	term.c_iflag &= ~IXON; | ||||
| 	term.c_cc[VINTR] = _POSIX_VDISABLE; | ||||
| 	term.c_cc[VSUSP] = _POSIX_VDISABLE; | ||||
| #ifdef VDSUSP | ||||
| 	term.c_cc[VDSUSP] = _POSIX_VDISABLE; | ||||
| #endif | ||||
| 	term.c_cc[VLNEXT] = _POSIX_VDISABLE; | ||||
| 	term.c_cc[VDISCARD] = _POSIX_VDISABLE; | ||||
| 	error = tcsetattr(STDOUT_FILENO, TCSADRAIN, &term); | ||||
| 	if (error) err(EX_OSERR, "tcsetattr"); | ||||
| } | ||||
| 
 | ||||
| // XXX: Assuming terminals will be fine with these even if they're unsupported,
 | ||||
| // since they're "private" modes.
 | ||||
| static const char *EnterFocusMode = "\33[?1004h"; | ||||
| static const char *ExitFocusMode  = "\33[?1004l"; | ||||
| static const char *EnterPasteMode = "\33[?2004h"; | ||||
| static const char *ExitPasteMode  = "\33[?2004l"; | ||||
| 
 | ||||
| static void errExit(void) { | ||||
| 	putp(ExitFocusMode); | ||||
| 	putp(ExitPasteMode); | ||||
| 	reset_shell_mode(); | ||||
| } | ||||
| 
 | ||||
| void uiInit(void) { | ||||
| 	initscr(); | ||||
| 	cbreak(); | ||||
| @ -273,7 +273,7 @@ void uiInit(void) { | ||||
| 	short fg = 8 + COLOR_BLACK; | ||||
| 	wbkgd(marker, '~' | colorAttr(fg) | COLOR_PAIR(colorPair(fg, -1))); | ||||
| 
 | ||||
| 	input = newpad(1, 512); | ||||
| 	input = newpad(1, 1024); | ||||
| 	if (!input) err(EX_OSERR, "newpad"); | ||||
| 	keypad(input, true); | ||||
| 	nodelay(input, true); | ||||
| @ -357,7 +357,7 @@ static const short Colors[ColorCap] = { | ||||
| 
 | ||||
| enum { B = '\2', C = '\3', O = '\17', R = '\26', I = '\35', U = '\37' }; | ||||
| 
 | ||||
| static void styleParse(struct Style *style, const char **str, size_t *len) { | ||||
| static size_t styleParse(struct Style *style, const char **str) { | ||||
| 	switch (**str) { | ||||
| 		break; case B: (*str)++; style->attr ^= A_BOLD; | ||||
| 		break; case O: (*str)++; *style = Reset; | ||||
| @ -379,14 +379,13 @@ static void styleParse(struct Style *style, const char **str, size_t *len) { | ||||
| 			if (isdigit(**str)) style->bg = style->bg * 10 + *(*str)++ - '0'; | ||||
| 		} | ||||
| 	} | ||||
| 	*len = strcspn(*str, (const char[]) { B, C, O, R, I, U, '\0' }); | ||||
| 	return strcspn(*str, (const char[]) { B, C, O, R, I, U, '\0' }); | ||||
| } | ||||
| 
 | ||||
| static void statusAdd(const char *str) { | ||||
| 	size_t len; | ||||
| 	struct Style style = Reset; | ||||
| 	while (*str) { | ||||
| 		styleParse(&style, &str, &len); | ||||
| 		size_t len = styleParse(&style, &str); | ||||
| 		wattr_set( | ||||
| 			status, | ||||
| 			style.attr | colorAttr(Colors[style.fg]), | ||||
| @ -399,16 +398,18 @@ static void statusAdd(const char *str) { | ||||
| } | ||||
| 
 | ||||
| static void statusUpdate(void) { | ||||
| 	int otherUnread = 0; | ||||
| 	enum Heat otherHeat = Cold; | ||||
| 	wmove(status, 0, 0); | ||||
| 	struct { | ||||
| 		uint unread; | ||||
| 		enum Heat heat; | ||||
| 	} others = { 0, Cold }; | ||||
| 
 | ||||
| 	wmove(status, 0, 0); | ||||
| 	for (uint num = 0; num < windows.len; ++num) { | ||||
| 		const struct Window *window = windows.ptrs[num]; | ||||
| 		if (!window->heat && num != windows.show) continue; | ||||
| 		if (num != windows.show) { | ||||
| 			otherUnread += window->unreadWarm; | ||||
| 			if (window->heat > otherHeat) otherHeat = window->heat; | ||||
| 			others.unread += window->unreadWarm; | ||||
| 			if (window->heat > others.heat) others.heat = window->heat; | ||||
| 		} | ||||
| 		int trunc; | ||||
| 		char buf[256]; | ||||
| @ -433,10 +434,10 @@ static void statusUpdate(void) { | ||||
| 			window->unreadWarm, (window->heat > Warm ? "!" : "") | ||||
| 		); | ||||
| 	} | ||||
| 	if (otherUnread) { | ||||
| 	if (others.unread) { | ||||
| 		catf( | ||||
| 			title, sizeof(title), " (+%d%s)", | ||||
| 			otherUnread, (otherHeat > Warm ? "!" : "") | ||||
| 			others.unread, (others.heat > Warm ? "!" : "") | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| @ -444,7 +445,7 @@ static void statusUpdate(void) { | ||||
| static void mark(struct Window *window) { | ||||
| 	if (window->scroll) return; | ||||
| 	window->mark = true; | ||||
| 	window->unreadTotal = 0; | ||||
| 	window->unread = 0; | ||||
| 	window->unreadWarm = 0; | ||||
| 	window->unreadLines = 0; | ||||
| } | ||||
| @ -508,9 +509,9 @@ static int wordWidth(const char *str) { | ||||
| static int wordWrap(WINDOW *win, const char *str) { | ||||
| 	int y, x, width; | ||||
| 	getmaxyx(win, y, width); | ||||
| 	waddch(win, '\n'); | ||||
| 
 | ||||
| 	size_t len; | ||||
| 	int lines = 0; | ||||
| 	int lines = 1; | ||||
| 	int align = 0; | ||||
| 	struct Style style = Reset; | ||||
| 	while (*str) { | ||||
| @ -538,9 +539,10 @@ static int wordWrap(WINDOW *win, const char *str) { | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		styleParse(&style, &str, &len); | ||||
| 		size_t len = styleParse(&style, &str); | ||||
| 		size_t ws = strcspn(str, "\t "); | ||||
| 		if (ws < len) len = ws; | ||||
| 		if (!len) continue; | ||||
| 
 | ||||
| 		wattr_set( | ||||
| 			win, | ||||
| @ -562,9 +564,8 @@ static void notify(uint id, const char *str) { | ||||
| 	utilPush(&util, idNames[id]); | ||||
| 	char buf[1024] = ""; | ||||
| 	while (*str) { | ||||
| 		size_t len; | ||||
| 		struct Style style = Reset; | ||||
| 		styleParse(&style, &str, &len); | ||||
| 		size_t len = styleParse(&style, &str); | ||||
| 		catf(buf, sizeof(buf), "%.*s", (int)len, str); | ||||
| 		str += len; | ||||
| 	} | ||||
| @ -584,23 +585,24 @@ static void notify(uint id, const char *str) { | ||||
| 
 | ||||
| void uiWrite(uint id, enum Heat heat, const time_t *src, const char *str) { | ||||
| 	struct Window *window = windows.ptrs[windowFor(id)]; | ||||
| 	time_t clock = (src ? *src : time(NULL)); | ||||
| 	bufferPush(&window->buffer, clock, str); | ||||
| 	time_t ts = (src ? *src : time(NULL)); | ||||
| 	bufferPush(&window->buffer, ts, str); | ||||
| 
 | ||||
| 	int lines = 1; | ||||
| 	waddch(window->pad, '\n'); | ||||
| 	window->unreadTotal++; | ||||
| 	int lines = 0; | ||||
| 	window->unread++; | ||||
| 	if (window->mark && heat > Cold) { | ||||
| 		if (window->heat < heat) window->heat = heat; | ||||
| 		if (!window->unreadWarm++) { | ||||
| 			waddch(window->pad, '\n'); | ||||
| 			lines++; | ||||
| 			waddch(window->pad, '\n'); | ||||
| 		} | ||||
| 		if (heat > window->heat) window->heat = heat; | ||||
| 		statusUpdate(); | ||||
| 	} | ||||
| 
 | ||||
| 	lines += wordWrap(window->pad, str); | ||||
| 	window->unreadLines += lines; | ||||
| 	if (window->scroll) windowScroll(window, lines); | ||||
| 
 | ||||
| 	if (window->mark && heat > Warm) { | ||||
| 		beep(); | ||||
| 		notify(id, str); | ||||
| @ -622,18 +624,19 @@ void uiFormat( | ||||
| static void reflow(struct Window *window) { | ||||
| 	werase(window->pad); | ||||
| 	wmove(window->pad, 0, 0); | ||||
| 
 | ||||
| 	int flowed = 0; | ||||
| 	window->unreadLines = 0; | ||||
| 	for (size_t i = 0; i < BufferCap; ++i) { | ||||
| 		const char *line = bufferLine(&window->buffer, i); | ||||
| 		if (!line) continue; | ||||
| 		waddch(window->pad, '\n'); | ||||
| 		int lines = 1 + wordWrap(window->pad, line); | ||||
| 		if (i >= (size_t)(BufferCap - window->unreadTotal)) { | ||||
| 		int lines = wordWrap(window->pad, line); | ||||
| 		if (i >= (size_t)(BufferCap - window->unread)) { | ||||
| 			window->unreadLines += lines; | ||||
| 		} | ||||
| 		flowed += lines; | ||||
| 	} | ||||
| 
 | ||||
| 	if (flowed < WindowLines) { | ||||
| 		wscrl(window->pad, -(WindowLines - 1 - flowed)); | ||||
| 		wmove(window->pad, WindowLines - 1, RIGHT); | ||||
| @ -656,19 +659,20 @@ static void resize(void) { | ||||
| static void bufferList(const struct Buffer *buffer) { | ||||
| 	uiHide(); | ||||
| 	waiting = true; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < BufferCap; ++i) { | ||||
| 		time_t time = bufferTime(buffer, i); | ||||
| 		const char *line = bufferLine(buffer, i); | ||||
| 		if (!line) continue; | ||||
| 
 | ||||
| 		time_t time = bufferTime(buffer, i); | ||||
| 		struct tm *tm = localtime(&time); | ||||
| 		if (!tm) continue; | ||||
| 		char buf[sizeof("[00:00:00]")]; | ||||
| 		strftime(buf, sizeof(buf), "[%T]", tm); | ||||
| 		vid_attr(colorAttr(Colors[Gray]), colorPair(Colors[Gray], -1), NULL); | ||||
| 		printf("%s ", buf); | ||||
| 		if (!tm) err(EX_OSERR, "localtime"); | ||||
| 
 | ||||
| 		char buf[sizeof("00:00:00")]; | ||||
| 		strftime(buf, sizeof(buf), "%T", tm); | ||||
| 		vid_attr(colorAttr(Colors[Gray]), colorPair(Colors[Gray], -1), NULL); | ||||
| 		printf("[%s] ", buf); | ||||
| 
 | ||||
| 		size_t len; | ||||
| 		bool align = false; | ||||
| 		struct Style style = Reset; | ||||
| 		while (*line) { | ||||
| @ -677,15 +681,18 @@ static void bufferList(const struct Buffer *buffer) { | ||||
| 				align = true; | ||||
| 				line++; | ||||
| 			} | ||||
| 			styleParse(&style, &line, &len); | ||||
| 
 | ||||
| 			size_t len = styleParse(&style, &line); | ||||
| 			size_t tab = strcspn(line, "\t"); | ||||
| 			if (tab < len) len = tab; | ||||
| 			if (!len) continue; | ||||
| 
 | ||||
| 			vid_attr( | ||||
| 				style.attr | colorAttr(Colors[style.fg]), | ||||
| 				colorPair(Colors[style.fg], Colors[style.bg]), | ||||
| 				NULL | ||||
| 			); | ||||
| 			if (len) printf("%.*s", (int)len, line); | ||||
| 			printf("%.*s", (int)len, line); | ||||
| 			line += len; | ||||
| 		} | ||||
| 		printf("\n"); | ||||
| @ -693,10 +700,9 @@ static void bufferList(const struct Buffer *buffer) { | ||||
| } | ||||
| 
 | ||||
| static void inputAdd(struct Style *style, const char *str) { | ||||
| 	size_t len; | ||||
| 	while (*str) { | ||||
| 		const char *code = str; | ||||
| 		styleParse(style, &str, &len); | ||||
| 		size_t len = styleParse(style, &str); | ||||
| 		wattr_set(input, A_BOLD | A_REVERSE, 0, NULL); | ||||
| 		switch (*code) { | ||||
| 			break; case B: waddch(input, 'B'); | ||||
| @ -707,6 +713,7 @@ static void inputAdd(struct Style *style, const char *str) { | ||||
| 			break; case U: waddch(input, 'U'); | ||||
| 		} | ||||
| 		if (str - code > 1) waddnstr(input, &code[1], str - &code[1]); | ||||
| 		if (!len) continue; | ||||
| 		wattr_set( | ||||
| 			input, | ||||
| 			style->attr | colorAttr(Colors[style->fg]), | ||||
| @ -719,52 +726,58 @@ static void inputAdd(struct Style *style, const char *str) { | ||||
| } | ||||
| 
 | ||||
| static void inputUpdate(void) { | ||||
| 	uint id = windows.ptrs[windows.show]->id; | ||||
| 	size_t pos; | ||||
| 	char *buf = editBuffer(&pos); | ||||
| 	uint id = windows.ptrs[windows.show]->id; | ||||
| 
 | ||||
| 	const char *skip = NULL; | ||||
| 	struct Style init = { .fg = self.color, .bg = Default }; | ||||
| 	struct Style rest = Reset; | ||||
| 	const char *prefix = ""; | ||||
| 	const char *prompt = self.nick; | ||||
| 	const char *suffix = ""; | ||||
| 	if (NULL != (skip = commandIsPrivmsg(id, buf))) { | ||||
| 	const char *skip = buf; | ||||
| 	struct Style stylePrompt = { .fg = self.color, .bg = Default }; | ||||
| 	struct Style styleInput = Reset; | ||||
| 
 | ||||
| 	const char *privmsg = commandIsPrivmsg(id, buf); | ||||
| 	const char *notice = commandIsNotice(id, buf); | ||||
| 	const char *action = commandIsAction(id, buf); | ||||
| 	if (privmsg) { | ||||
| 		prefix = "<"; suffix = "> "; | ||||
| 	} else if (NULL != (skip = commandIsNotice(id, buf))) { | ||||
| 		skip = privmsg; | ||||
| 	} else if (notice) { | ||||
| 		prefix = "-"; suffix = "- "; | ||||
| 		rest.fg = LightGray; | ||||
| 	} else if (NULL != (skip = commandIsAction(id, buf))) { | ||||
| 		init.attr |= A_ITALIC; | ||||
| 		styleInput.fg = LightGray; | ||||
| 		skip = notice; | ||||
| 	} else if (action) { | ||||
| 		prefix = "* "; suffix = " "; | ||||
| 		rest.attr |= A_ITALIC; | ||||
| 		stylePrompt.attr |= A_ITALIC; | ||||
| 		styleInput.attr |= A_ITALIC; | ||||
| 		skip = action; | ||||
| 	} else if (id == Debug && buf[0] != '/') { | ||||
| 		skip = buf; | ||||
| 		init.fg = Gray; | ||||
| 		prompt = "<< "; | ||||
| 		stylePrompt.fg = Gray; | ||||
| 	} else { | ||||
| 		prompt = ""; | ||||
| 	} | ||||
| 	if (skip && skip > &buf[pos]) { | ||||
| 		skip = NULL; | ||||
| 	if (skip > &buf[pos]) { | ||||
| 		prefix = prompt = suffix = ""; | ||||
| 		skip = buf; | ||||
| 	} | ||||
| 
 | ||||
| 	int y, x; | ||||
| 	wmove(input, 0, 0); | ||||
| 	wattr_set( | ||||
| 		input, | ||||
| 		init.attr | colorAttr(Colors[init.fg]), | ||||
| 		colorPair(Colors[init.fg], Colors[init.bg]), | ||||
| 		stylePrompt.attr | colorAttr(Colors[stylePrompt.fg]), | ||||
| 		colorPair(Colors[stylePrompt.fg], Colors[stylePrompt.bg]), | ||||
| 		NULL | ||||
| 	); | ||||
| 	waddstr(input, prefix); | ||||
| 	waddstr(input, prompt); | ||||
| 	waddstr(input, suffix); | ||||
| 	struct Style style = rest; | ||||
| 	struct Style style = styleInput; | ||||
| 	char p = buf[pos]; | ||||
| 	buf[pos] = '\0'; | ||||
| 	inputAdd(&style, (skip ? skip : buf)); | ||||
| 	inputAdd(&style, skip); | ||||
| 	getyx(input, y, x); | ||||
| 	buf[pos] = p; | ||||
| 	inputAdd(&style, &buf[pos]); | ||||
| @ -954,7 +967,7 @@ void uiRead(void) { | ||||
| } | ||||
| 
 | ||||
| static const time_t Signatures[] = { | ||||
| 	0x6C72696774616301, // no heat, unreadTotal, unreadWarm
 | ||||
| 	0x6C72696774616301, // no heat, unread, unreadWarm
 | ||||
| 	0x6C72696774616302, | ||||
| }; | ||||
| 
 | ||||
| @ -981,7 +994,7 @@ int uiSave(const char *name) { | ||||
| 		const struct Window *window = windows.ptrs[num]; | ||||
| 		if (writeString(file, idNames[window->id])) return -1; | ||||
| 		if (writeTime(file, window->heat)) return -1; | ||||
| 		if (writeTime(file, window->unreadTotal)) return -1; | ||||
| 		if (writeTime(file, window->unread)) return -1; | ||||
| 		if (writeTime(file, window->unreadWarm)) return -1; | ||||
| 		for (size_t i = 0; i < BufferCap; ++i) { | ||||
| 			time_t time = bufferTime(&window->buffer, i); | ||||
| @ -1033,7 +1046,7 @@ void uiLoad(const char *name) { | ||||
| 		struct Window *window = windows.ptrs[windowFor(idFor(buf))]; | ||||
| 		if (version > 0) { | ||||
| 			window->heat = readTime(file); | ||||
| 			window->unreadTotal = readTime(file); | ||||
| 			window->unread = readTime(file); | ||||
| 			window->unreadWarm = readTime(file); | ||||
| 		} | ||||
| 		for (;;) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user