Compare commits
	
		
			No commits in common. "f2d8de3ab92321419005b6f2bd6834dacda4cdb7" and "e6bf88673f31e62050333f98d6bcd407ac34c13d" have entirely different histories.
		
	
	
		
			f2d8de3ab9
			...
			e6bf88673f
		
	
		
							
								
								
									
										9
									
								
								xC.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								xC.c
									
									
									
									
									
								
							| @ -15010,28 +15010,21 @@ process_formatting_escape (const struct pollfd *fd, struct app_context *ctx) | |||||||
| 
 | 
 | ||||||
| 	if (buf->len != 1) | 	if (buf->len != 1) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 |  | ||||||
| 	// Letters mostly taken from their caret escapes + HTML element names.
 |  | ||||||
| 	// Additionally, 'm' stands for mono, 'x' for cross, 'r' for reset.
 |  | ||||||
| 	switch (buf->str[0]) | 	switch (buf->str[0]) | ||||||
| 	{ | 	{ | ||||||
| 	case 'b' ^ 96: | 	case 'b' ^ 96: | ||||||
| 	case 'b': CALL_ (ctx->input, insert, "\x02"); break; | 	case 'b': CALL_ (ctx->input, insert, "\x02"); break; | ||||||
| 	case 'c': CALL_ (ctx->input, insert, "\x03"); break; | 	case 'c': CALL_ (ctx->input, insert, "\x03"); break; | ||||||
| 	case 'q': |  | ||||||
| 	case 'm': CALL_ (ctx->input, insert, "\x11"); break; |  | ||||||
| 	case 'v': CALL_ (ctx->input, insert, "\x16"); break; |  | ||||||
| 	case 'i' ^ 96: | 	case 'i' ^ 96: | ||||||
| 	case 'i': | 	case 'i': | ||||||
| 	case ']': CALL_ (ctx->input, insert, "\x1d"); break; | 	case ']': CALL_ (ctx->input, insert, "\x1d"); break; | ||||||
| 	case 's' ^ 96: |  | ||||||
| 	case 's': |  | ||||||
| 	case 'x' ^ 96: | 	case 'x' ^ 96: | ||||||
| 	case 'x': | 	case 'x': | ||||||
| 	case '^': CALL_ (ctx->input, insert, "\x1e"); break; | 	case '^': CALL_ (ctx->input, insert, "\x1e"); break; | ||||||
| 	case 'u' ^ 96: | 	case 'u' ^ 96: | ||||||
| 	case 'u': | 	case 'u': | ||||||
| 	case '_': CALL_ (ctx->input, insert, "\x1f"); break; | 	case '_': CALL_ (ctx->input, insert, "\x1f"); break; | ||||||
|  | 	case 'v': CALL_ (ctx->input, insert, "\x16"); break; | ||||||
| 	case 'r': | 	case 'r': | ||||||
| 	case 'o': CALL_ (ctx->input, insert, "\x0f"); break; | 	case 'o': CALL_ (ctx->input, insert, "\x0f"); break; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -69,16 +69,12 @@ body { | |||||||
| .toolbar { | .toolbar { | ||||||
| 	display: flex; | 	display: flex; | ||||||
| 	align-items: baseline; | 	align-items: baseline; | ||||||
| 	margin-right: -.3em; | 	column-gap: .3em; | ||||||
| } |  | ||||||
| .indicator { |  | ||||||
| 	margin: 0 .3em; |  | ||||||
| } | } | ||||||
| button { | button { | ||||||
| 	font: inherit; | 	font: inherit; | ||||||
| 	background: transparent; | 	background: transparent; | ||||||
| 	border: 1px solid transparent; | 	border: 1px solid transparent; | ||||||
| 	padding: 0 .3em; |  | ||||||
| } | } | ||||||
| button:focus { | button:focus { | ||||||
| 	border: 1px dashed #000; | 	border: 1px dashed #000; | ||||||
|  | |||||||
| @ -435,7 +435,7 @@ for (let i = 0; i < 24; i++) { | |||||||
| let linkRE = [ | let linkRE = [ | ||||||
| 	/https?:\/\//, | 	/https?:\/\//, | ||||||
| 	/([^\[\](){}<>"'\s]|\([^\[\](){}<>"'\s]*\))+/, | 	/([^\[\](){}<>"'\s]|\([^\[\](){}<>"'\s]*\))+/, | ||||||
| 	/([^\[\](){}<>"'\s,.:]|\([^\[\](){}<>"'\s]*\))/, | 	/[^\[\](){}<>"'\s,.:]/, | ||||||
| ].map(r => r.source).join('') | ].map(r => r.source).join('') | ||||||
| 
 | 
 | ||||||
| let BufferList = { | let BufferList = { | ||||||
| @ -631,7 +631,7 @@ let Buffer = { | |||||||
| 		return m('.buffer', {onscroll: event => { | 		return m('.buffer', {onscroll: event => { | ||||||
| 			const dom = event.target | 			const dom = event.target | ||||||
| 			bufferAutoscroll = | 			bufferAutoscroll = | ||||||
| 				dom.scrollTop + dom.clientHeight + 1 >= dom.scrollHeight | 				dom.scrollTop + dom.clientHeight + 0.5 >= dom.scrollHeight | ||||||
| 		}}, lines) | 		}}, lines) | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| @ -687,26 +687,9 @@ let BufferContainer = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| let Toolbar = { | let Toolbar = { | ||||||
| 	format: formatting => { |  | ||||||
| 		let textarea = document.getElementById('input') |  | ||||||
| 		if (textarea !== null) |  | ||||||
| 			Input.format(textarea, formatting) |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	view: vnode => { | 	view: vnode => { | ||||||
| 		let indicators = [] |  | ||||||
| 		if (bufferLog === undefined && !bufferAutoscroll) |  | ||||||
| 			indicators.push(m('.indicator', {}, '⇩')) |  | ||||||
| 		if (Input.formatting) |  | ||||||
| 			indicators.push(m('.indicator', {}, '#')) |  | ||||||
| 		return m('.toolbar', {}, [ | 		return m('.toolbar', {}, [ | ||||||
| 			indicators, | 			bufferLog === undefined && !bufferAutoscroll ? '⇩' : undefined, | ||||||
| 			m('button', {onclick: event => Toolbar.format('\u0002')}, |  | ||||||
| 				m('b', {}, 'B')), |  | ||||||
| 			m('button', {onclick: event => Toolbar.format('\u001D')}, |  | ||||||
| 				m('i', {}, 'I')), |  | ||||||
| 			m('button', {onclick: event => Toolbar.format('\u001F')}, |  | ||||||
| 				m('u', {}, 'U')), |  | ||||||
| 			m('button', {onclick: event => bufferToggleLog()}, | 			m('button', {onclick: event => bufferToggleLog()}, | ||||||
| 				bufferLog === undefined ? 'Log' : 'Hide log'), | 				bufferLog === undefined ? 'Log' : 'Hide log'), | ||||||
| 		]) | 		]) | ||||||
| @ -915,21 +898,6 @@ let Input = { | |||||||
| 		return true | 		return true | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	formatting: false, |  | ||||||
| 
 |  | ||||||
| 	format: (textarea, formatting) => { |  | ||||||
| 		const [start, end] = [textarea.selectionStart, textarea.selectionEnd] |  | ||||||
| 		if (start === end) { |  | ||||||
| 			textarea.setRangeText(formatting) |  | ||||||
| 			textarea.setSelectionRange( |  | ||||||
| 				start + formatting.length, end + formatting.length) |  | ||||||
| 		} else { |  | ||||||
| 			textarea.setRangeText( |  | ||||||
| 				formatting + textarea.value.substr(start, end) + formatting) |  | ||||||
| 		} |  | ||||||
| 		textarea.focus() |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	onKeyDown: event => { | 	onKeyDown: event => { | ||||||
| 		// TODO: And perhaps on other actions, too.
 | 		// TODO: And perhaps on other actions, too.
 | ||||||
| 		rpc.send({command: 'Active'}) | 		rpc.send({command: 'Active'}) | ||||||
| @ -941,29 +909,7 @@ let Input = { | |||||||
| 		let textarea = event.currentTarget | 		let textarea = event.currentTarget | ||||||
| 		let handled = false | 		let handled = false | ||||||
| 		let success = true | 		let success = true | ||||||
| 		if (Input.formatting) { | 		if (hasShortcutModifiers(event)) { | ||||||
| 			Input.formatting = false |  | ||||||
| 
 |  | ||||||
| 			// Like process_formatting_escape() within xC.
 |  | ||||||
| 			handled = true |  | ||||||
| 			switch (event.key) { |  | ||||||
| 			case 'b': Input.format(textarea, '\u0002'); break |  | ||||||
| 			case 'c': Input.format(textarea, '\u0003'); break |  | ||||||
| 			case 'q': |  | ||||||
| 			case 'm': Input.format(textarea, '\u0011'); break |  | ||||||
| 			case 'v': Input.format(textarea, '\u0016'); break |  | ||||||
| 			case 'i': |  | ||||||
| 			case ']': Input.format(textarea, '\u001D'); break |  | ||||||
| 			case 's': |  | ||||||
| 			case 'x': |  | ||||||
| 			case '^': Input.format(textarea, '\u001E'); break |  | ||||||
| 			case 'u': |  | ||||||
| 			case '_': Input.format(textarea, '\u001F'); break |  | ||||||
| 			case 'r': |  | ||||||
| 			case 'o': Input.format(textarea, '\u000F'); break |  | ||||||
| 			default: success = false |  | ||||||
| 			} |  | ||||||
| 		} else if (hasShortcutModifiers(event)) { |  | ||||||
| 			handled = true | 			handled = true | ||||||
| 			switch (event.key) { | 			switch (event.key) { | ||||||
| 			case 'b': success = Input.backward(textarea);    break | 			case 'b': success = Input.backward(textarea);    break | ||||||
| @ -975,7 +921,6 @@ let Input = { | |||||||
| 			case '>': success = Input.last(b, textarea);     break | 			case '>': success = Input.last(b, textarea);     break | ||||||
| 			case 'p': success = Input.previous(b, textarea); break | 			case 'p': success = Input.previous(b, textarea); break | ||||||
| 			case 'n': success = Input.next(b, textarea);     break | 			case 'n': success = Input.next(b, textarea);     break | ||||||
| 			case 'm': success = Input.formatting = true;     break |  | ||||||
| 			default:  handled = false | 			default:  handled = false | ||||||
| 			} | 			} | ||||||
| 		} else if (!event.altKey && !event.ctrlKey && !event.metaKey && | 		} else if (!event.altKey && !event.ctrlKey && !event.metaKey && | ||||||
| @ -993,20 +938,15 @@ let Input = { | |||||||
| 			event.preventDefault() | 			event.preventDefault() | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	onStateChange: event => { |  | ||||||
| 		Completions.reset() |  | ||||||
| 		Input.formatting = false |  | ||||||
| 	}, |  | ||||||
| 
 |  | ||||||
| 	view: vnode => { | 	view: vnode => { | ||||||
| 		return m('textarea#input', { | 		return m('textarea#input', { | ||||||
| 			rows: 1, | 			rows: 1, | ||||||
| 			onkeydown: Input.onKeyDown, | 			onkeydown: Input.onKeyDown, | ||||||
| 			oninput: Input.onStateChange, | 			oninput: event => Completions.reset(), | ||||||
| 			// Sadly only supported in Firefox as of writing.
 | 			// Sadly only supported in Firefox as of writing.
 | ||||||
| 			onselectionchange: Input.onStateChange, | 			onselectionchange: event => Completions.reset(), | ||||||
| 			// The list of completions is scrollable without receiving focus.
 | 			// The list of completions is scrollable without receiving focus.
 | ||||||
| 			onblur: Input.onStateChange, | 			onblur: event => Completions.reset(), | ||||||
| 		}) | 		}) | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user