summaryrefslogtreecommitdiffhomepage
path: root/src/console
diff options
context:
space:
mode:
Diffstat (limited to 'src/console')
-rw-r--r--src/console/ptyc_console_writer.c145
1 files changed, 143 insertions, 2 deletions
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;
}