From 640ed378d69292813ed5bfa55a4139a1734ed787 Mon Sep 17 00:00:00 2001
From: midipix <writeonce@midipix.org>
Date: Tue, 12 Jul 2016 03:32:50 -0400
Subject: console: added initial writer (client-to-terminal) logic.

---
 src/console/ptyc_console_writer.c | 145 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 2 deletions(-)

(limited to 'src/console')

diff --git a/src/console/ptyc_console_writer.c b/src/console/ptyc_console_writer.c
index a0ea461..046e675 100644
--- a/src/console/ptyc_console_writer.c
+++ b/src/console/ptyc_console_writer.c
@@ -12,8 +12,149 @@
 #include <ptycon/ptycon.h>
 #include "ptycon_driver_impl.h"
 
+static ptyc_term_handler	ptyc_screen_handler;
+static ptyc_term_handler	ptyc_ctrl_handler;
+static ptyc_term_handler	ptyc_flush_screen_buffer;
+
 int ptyc_console_writer(struct ptyc_driver_ctx_impl * ictx)
 {
-	(void)ictx;
-	return ntapi->tt_wait_for_dummy_event();
+	int32_t						status;
+	nt_iosb						iosb;
+	size_t						nsteps;
+	void *						hwait;
+	unsigned char *					inbuf;
+	struct ptyc_term_ctx *				tctx;
+	nt_unicode_conversion_params_utf8_to_utf16	uc_params;
+
+	if ((status = ntapi->tt_create_private_event(
+			&hwait,
+			NT_NOTIFICATION_EVENT,
+			NT_EVENT_NOT_SIGNALED)))
+		return status;
+
+	tctx				= &ictx->tctx;
+	inbuf				= (unsigned char *)&tctx->data.in[1];
+
+	uc_params.dst_size_in_bytes	= sizeof(tctx->data.out);
+	uc_params.leftover_count	= 0;
+	uc_params.leftover_bytes	= 0;
+
+	tctx->handler			= ptyc_screen_handler;
+	tctx->char_handler		= ptyc_screen_handler;
+	tctx->ctrl_handler		= ptyc_ctrl_handler;
+	tctx->ctrl_handlers[0]		= ptyc_esi_handlers;
+	tctx->wch_con			= tctx->data.screen;
+
+	do {
+		uc_params.code_points	= 0;
+		uc_params.addr_failed	= 0;
+		uc_params.bytes_written	= 0;
+
+		status = ntapi->pty_read(
+			ictx->cctx.hptm,
+			hwait,0,0,
+			&iosb,
+			inbuf,
+			sizeof(tctx->data.in) - sizeof(uintptr_t),
+			0,0);
+
+		if (status == NT_STATUS_PENDING)
+			status = ntapi->zw_wait_for_single_object(
+				hwait,NT_SYNC_ALERTABLE,0);
+
+		if (status || iosb.status) {
+			ntapi->zw_close(hwait);
+			return status ? status : iosb.status;
+		}
+
+		/* account for leftover bytes from the previous conversion */
+		tctx->data.in[0]		= uc_params.leftover_bytes;
+		uc_params.src			= inbuf - uc_params.leftover_bytes;
+		uc_params.src_size_in_bytes	= iosb.info + uc_params.leftover_count;
+		uc_params.dst			= tctx->data.out;
+
+
+		/* utf-8 --> utf-16 */
+		status = ntapi->uc_convert_unicode_stream_utf8_to_utf16(
+			&uc_params);
+
+		/* process the converted (utf-16) stream */
+		tctx->wch_pty = tctx->data.out;
+		nsteps        = uc_params.bytes_written / sizeof(wchar16_t);
+
+		for (; nsteps; nsteps--)
+			tctx->handler = (ptyc_term_handler *)tctx->handler(tctx);
+
+		/* output to console */
+		ptyc_flush_screen_buffer(tctx);
+	} while (1);
+
+	return NT_STATUS_INTERNAL_ERROR;
+}
+
+
+static void * __fastcall ptyc_screen_handler(struct ptyc_term_ctx * tctx)
+{
+	if (*tctx->wch_pty == '\x1b') {
+		/* output all pending characters */
+		ptyc_flush_screen_buffer(tctx);
+
+		/* advance stream pointer */
+		tctx->wch_pty++;
+
+		/* set initial control state */
+		tctx->ctrl_state = PTYC_CTRL_STATE_ESI;
+		tctx->ctrl_cap   = PTYC_ESI_ARRAY_SIZE;
+
+		/* switch mode */
+		return tctx->ctrl_handler;
+	} else {
+		/* copy character to the screen buffer */
+		*tctx->wch_con = *tctx->wch_pty;
+
+		/* advance the screen and stream pointers */
+		tctx->wch_con++;
+		tctx->wch_pty++;
+
+		/* retain mode */
+		return ptyc_screen_handler;
+	}
+}
+
+
+static void * __fastcall ptyc_ctrl_handler(struct ptyc_term_ctx * tctx)
+{
+	ptyc_term_handler * const *	handlers;
+	ptyc_term_handler *		handler;
+	unsigned			idx;
+
+	idx = (*tctx->wch_pty < tctx->ctrl_cap)
+			? *tctx->wch_pty
+			: tctx->ctrl_cap - 1;
+
+	handlers = tctx->ctrl_handlers[tctx->ctrl_state];
+	handler  = handlers[idx];
+
+	return handler(tctx);
+}
+
+
+static void * __fastcall ptyc_flush_screen_buffer(struct ptyc_term_ctx * tctx)
+{
+	uint32_t ncunits;
+	uint32_t nwritten;
+
+	if (!(ncunits = (uint32_t)(tctx->wch_con - tctx->data.screen)))
+		return tctx->wch_con;
+
+	ntcon->write_console_utf16(
+		tctx->hout,
+		tctx->data.screen,
+		ncunits,
+		&nwritten,
+		0);
+
+	tctx->wch_con = tctx->data.screen;
+
+	return tctx->wch_con;
 }
-- 
cgit v1.2.3