Compare commits
	
		
			5 Commits
		
	
	
		
			1639235a48
			...
			d7b0b447b7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d7b0b447b7 | |||
| 25ad5ae0ec | |||
| 10f6072da9 | |||
| aceac26cbb | |||
| e250ae8255 | 
							
								
								
									
										19
									
								
								README.adoc
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.adoc
									
									
									
									
									
								
							| @ -23,15 +23,16 @@ command aliases, SOCKS proxying, SASL EXTERNAL authentication using TLS client | ||||
| certificates, a remote relay interface, or basic support for Lua scripting. | ||||
| As a unique bonus, you can launch a full text editor from within. | ||||
| 
 | ||||
| xF | ||||
| -- | ||||
| The X11 frontend for 'xC', making use of its networked relay interface. | ||||
| It's currently in development, and is hidden behind a CMake option. | ||||
| 
 | ||||
| xP | ||||
| -- | ||||
| The web frontend for 'xC', making use of its networked relay interface. | ||||
| It's currently rather elementary, and can be built from within its directory. | ||||
| So far it's quite basic, yet usable.  Build it using `make` in its directory, | ||||
| and run it from within the _public_ subdirectory. | ||||
| 
 | ||||
| xF | ||||
| -- | ||||
| The X11 frontend for 'xC', making use of its networked relay interface. | ||||
| It's currently in development, and hidden behind a CMake option. | ||||
| 
 | ||||
| xD | ||||
| -- | ||||
| @ -72,15 +73,15 @@ Building | ||||
| Build-only dependencies: | ||||
|  CMake, pkg-config, asciidoctor or asciidoc, awk, liberty (included) + | ||||
| Common runtime dependencies: openssl + | ||||
| Additionally for 'xC': curses, libffi, + | ||||
|  readline >= 6.0 or libedit >= 2013-07-12, lua >= 5.3 (optional) + | ||||
| Additionally for 'xC': curses, libffi, readline >= 6.0 or libedit >= 2013-07-12, | ||||
|  lua >= 5.3 (optional) + | ||||
| Additionally for 'xF': x11, xft | ||||
| 
 | ||||
|  $ git clone --recursive https://git.janouch.name/p/xK.git | ||||
|  $ mkdir xK/build | ||||
|  $ cd xK/build | ||||
|  $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo \ | ||||
|             -DWANT_READLINE=ON -DWANT_LIBEDIT=OFF -DWANT_LUA=ON | ||||
|             -DWANT_READLINE=ON -DWANT_LIBEDIT=OFF -DWITH_LUA=ON | ||||
|  $ make | ||||
| 
 | ||||
| To install the application, you can do either the usual: | ||||
|  | ||||
							
								
								
									
										1
									
								
								xC-proto
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								xC-proto
									
									
									
									
									
								
							| @ -69,6 +69,7 @@ struct EventMessage { | ||||
| 			ERROR, | ||||
| 			JOIN, | ||||
| 			PART, | ||||
| 			ACTION, | ||||
| 		} rendition; | ||||
| 		// Unix timestamp in seconds. | ||||
| 		u64 when; | ||||
|  | ||||
							
								
								
									
										22
									
								
								xC.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								xC.c
									
									
									
									
									
								
							| @ -1480,7 +1480,7 @@ struct formatter_item | ||||
| { | ||||
| 	enum formatter_item_type type : 16; ///< Type of this item
 | ||||
| 	int attribute                 : 16; ///< Attribute ID or a TEXT_* mask
 | ||||
| 	int color;                          ///< Colour
 | ||||
| 	int color;                          ///< Colour ([256 << 16] | 16)
 | ||||
| 	char *text;                         ///< String
 | ||||
| }; | ||||
| 
 | ||||
| @ -1536,6 +1536,7 @@ enum buffer_line_rendition | ||||
| 	BUFFER_LINE_ERROR,                  ///< Error message
 | ||||
| 	BUFFER_LINE_JOIN,                   ///< Join arrow
 | ||||
| 	BUFFER_LINE_PART,                   ///< Part arrow
 | ||||
| 	BUFFER_LINE_ACTION,                 ///< Highlighted asterisk
 | ||||
| }; | ||||
| 
 | ||||
| struct buffer_line | ||||
| @ -3114,6 +3115,9 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer, | ||||
| 	union relay_item_data *p = e->items = xcalloc (len * 6, sizeof *e->items); | ||||
| 	for (struct formatter_item *i = line->items; len--; i++) | ||||
| 	{ | ||||
| 		// XXX: See attr_printer_decode_color(), this is a footgun.
 | ||||
| 		int16_t c16  = i->color; | ||||
| 		int16_t c256 = i->color >> 16; | ||||
| 		switch (i->type) | ||||
| 		{ | ||||
| 		case FORMATTER_ITEM_TEXT: | ||||
| @ -3125,11 +3129,11 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer, | ||||
| 			(p++)->kind = RELAY_ITEM_RESET; | ||||
| 			break; | ||||
| 		case FORMATTER_ITEM_FG_COLOR: | ||||
| 			p->fg_color.color = i->color; | ||||
| 			p->fg_color.color = c256 <= 0 ? c16 : c256; | ||||
| 			(p++)->kind = RELAY_ITEM_FG_COLOR; | ||||
| 			break; | ||||
| 		case FORMATTER_ITEM_BG_COLOR: | ||||
| 			p->bg_color.color = i->color; | ||||
| 			p->bg_color.color = c256 <= 0 ? c16 : c256; | ||||
| 			(p++)->kind = RELAY_ITEM_BG_COLOR; | ||||
| 			break; | ||||
| 		case FORMATTER_ITEM_SIMPLE: | ||||
| @ -4475,6 +4479,7 @@ buffer_line_flush (struct buffer_line *line, struct formatter *f, FILE *output, | ||||
| 	case BUFFER_LINE_ERROR:   formatter_add (f, "#a=!=#r ", ATTR_ERROR);  break; | ||||
| 	case BUFFER_LINE_JOIN:    formatter_add (f, "#a-->#r ", ATTR_JOIN);   break; | ||||
| 	case BUFFER_LINE_PART:    formatter_add (f, "#a<--#r ", ATTR_PART);   break; | ||||
| 	case BUFFER_LINE_ACTION:  formatter_add (f, " #a*#r  ", ATTR_ACTION); break; | ||||
| 	} | ||||
| 
 | ||||
| 	for (struct formatter_item *iter = line->items; iter->type; iter++) | ||||
| @ -4691,16 +4696,16 @@ log_full (struct app_context *ctx, struct server *s, struct buffer *buffer, | ||||
| #define log_outcoming_privmsg(s, buffer, prefixes, who, text)                  \ | ||||
| 	log_server ((s), (buffer), 0, 0, "<#s#n> #m", (prefixes), (who), (text)) | ||||
| #define log_outcoming_action(s, buffer, who, text)                             \ | ||||
| 	log_server ((s), (buffer), 0, 0, " #a*#r  #n #m", \ | ||||
| 		ATTR_ACTION, (who), (text)) | ||||
| 	log_server ((s), (buffer), 0, BUFFER_LINE_ACTION, "#n #m", (who), (text)) | ||||
| 
 | ||||
| #define log_outcoming_orphan_notice(s, target, text)                           \ | ||||
| 	log_server_status ((s), (s)->buffer, "Notice -> #n: #m", (target), (text)) | ||||
| #define log_outcoming_orphan_privmsg(s, target, text)                          \ | ||||
| 	log_server_status ((s), (s)->buffer, "MSG(#n): #m", (target), (text)) | ||||
| 	log_server ((s), (s)->buffer, 0, BUFFER_LINE_STATUS,                       \ | ||||
| 		"MSG(#n): #m", (target), (text)) | ||||
| #define log_outcoming_orphan_action(s, target, text)                           \ | ||||
| 	log_server_status ((s), (s)->buffer, "MSG(#n):  #a*#r  #m", (target),      \ | ||||
| 		ATTR_ACTION, (text)) | ||||
| 	log_server ((s), (s)->buffer, 0, BUFFER_LINE_ACTION,                       \ | ||||
| 		"MSG(#n): #m", (target), (text)) | ||||
| 
 | ||||
| #define log_ctcp_query(s, target, tag)                                         \ | ||||
| 	log_server_status ((s), (s)->buffer, "CTCP query to #S: #S", target, tag) | ||||
| @ -8763,6 +8768,7 @@ irc_process_numeric (struct server *s, | ||||
| 		if (msg->params.len == 2) | ||||
| 			irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]); | ||||
| 		break; | ||||
| 	case IRC_RPL_MOTDSTART: | ||||
| 	case IRC_RPL_MOTD: | ||||
| 		if (copy.len) | ||||
| 			irc_adjust_motd (©.vector[0]); | ||||
|  | ||||
| @ -79,6 +79,9 @@ body { | ||||
| .mark.part { | ||||
| 	color: red; | ||||
| } | ||||
| .mark.action { | ||||
| 	color: darkred; | ||||
| } | ||||
| .content { | ||||
| 	padding: .1rem .3rem; | ||||
| 	white-space: pre-wrap; | ||||
|  | ||||
| @ -1,3 +1,40 @@ | ||||
| // Copyright (c) 2022, Přemysl Eric Janouch <p@janouch.name>
 | ||||
| // SPDX-License-Identifier: 0BSD
 | ||||
| 
 | ||||
| // --- Colours -----------------------------------------------------------------
 | ||||
| 
 | ||||
| let palette = [ | ||||
| 	'#000', '#800', '#080', '#880', '#008', '#808', '#088', '#ccc', | ||||
| 	'#888', '#f00', '#0f0', '#ff0', '#00f', '#f0f', '#0ff', '#fff', | ||||
| ] | ||||
| palette.length = 256 | ||||
| for (let i = 0; i < 216; i++) { | ||||
| 	let r = i / 36 >> 0, g = (i / 6 >> 0) % 6, b = i % 6 | ||||
| 	r = !r ? '00' : (55 + 40 * r).toString(16) | ||||
| 	g = !g ? '00' : (55 + 40 * g).toString(16) | ||||
| 	b = !b ? '00' : (55 + 40 * b).toString(16) | ||||
| 	palette[16 + i] = `#${r}${g}${b}` | ||||
| } | ||||
| for (let i = 0; i < 24; i++) { | ||||
| 	let g = ('0' + (8 + i * 10).toString(16)).slice(-2) | ||||
| 	palette[232 + i] = `#${g}${g}${g}` | ||||
| } | ||||
| 
 | ||||
| function applyColor(fg, bg, inverse) { | ||||
| 	if (inverse) | ||||
| 		[fg, bg] = [bg >= 0 ? bg : 15, fg >= 0 ? fg : 0] | ||||
| 
 | ||||
| 	let style = '' | ||||
| 	if (fg >= 0) | ||||
| 		style += `color: ${palette[fg]};` | ||||
| 	if (bg >= 0) | ||||
| 		style += `background-color: ${palette[bg]};` | ||||
| 	if (style) | ||||
| 		return style | ||||
| } | ||||
| 
 | ||||
| // ---- Event processing -------------------------------------------------------
 | ||||
| 
 | ||||
| // TODO: Probably reset state on disconnect, and indicate to user.
 | ||||
| let socket = new WebSocket(proxy) | ||||
| 
 | ||||
| @ -59,6 +96,8 @@ socket.onmessage = function(event) { | ||||
| 	m.redraw() | ||||
| } | ||||
| 
 | ||||
| // ---- UI ---------------------------------------------------------------------
 | ||||
| 
 | ||||
| let BufferList = { | ||||
| 	view: vnode => { | ||||
| 		let items = [] | ||||
| @ -86,6 +125,7 @@ let Content = { | ||||
| 		case 'Error':  content.push(m('span.mark.error',  {}, '⚠')); break | ||||
| 		case 'Join':   content.push(m('span.mark.join',   {}, '→')); break | ||||
| 		case 'Part':   content.push(m('span.mark.part',   {}, '←')); break | ||||
| 		case 'Action': content.push(m('span.mark.action', {}, '✶')); break | ||||
| 		} | ||||
| 
 | ||||
| 		let classes = new Set() | ||||
| @ -95,22 +135,33 @@ let Content = { | ||||
| 			else | ||||
| 				classes.add(c) | ||||
| 		} | ||||
| 		let fg = -1, bg = -1, inverse = false | ||||
| 		line.items.forEach(item => { | ||||
| 			// TODO: Colours.
 | ||||
| 			switch (item.kind) { | ||||
| 			case 'Text': | ||||
| 				// TODO: Detect and transform links.
 | ||||
| 				content.push(m('span', { | ||||
| 					class: Array.from(classes.keys()).join(' '), | ||||
| 					style: applyColor(fg, bg, inverse), | ||||
| 				}, item.text)) | ||||
| 				break | ||||
| 			case 'Reset': | ||||
| 				classes.clear() | ||||
| 				fg = bg = -1 | ||||
| 				inverse = false | ||||
| 				break | ||||
| 			case 'FgColor': | ||||
| 				fg = item.color | ||||
| 				break | ||||
| 			case 'BgColor': | ||||
| 				bg = item.color | ||||
| 				break | ||||
| 			case 'FlipInverse': | ||||
| 				inverse = !inverse | ||||
| 				break | ||||
| 			case 'FlipBold':       flip('b'); break | ||||
| 			case 'FlipItalic':     flip('i'); break | ||||
| 			case 'FlipUnderline':  flip('u'); break | ||||
| 			case 'FlipInverse':    flip('i'); break | ||||
| 			case 'FlipCrossedOut': flip('s'); break | ||||
| 			case 'FlipMonospace':  flip('m'); break | ||||
| 			} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user