|
|
1bab02 |
/*********************************************************/
|
|
|
1bab02 |
/* ptycon: a pty-console bridge */
|
|
|
1f983d |
/* Copyright (C) 2016--2017 Z. Gilboa */
|
|
|
1bab02 |
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
|
|
|
1bab02 |
/*********************************************************/
|
|
|
1bab02 |
|
|
|
1bab02 |
#include <psxtypes/psxtypes.h>
|
|
|
1bab02 |
#include <ntcon/ntcon.h>
|
|
|
1bab02 |
#include <ntapi/ntapi.h>
|
|
|
1bab02 |
#include <gdi/gdi.h>
|
|
|
1bab02 |
|
|
|
1bab02 |
#include <ptycon/ptycon.h>
|
|
|
1bab02 |
#include "ptycon_driver_impl.h"
|
|
|
6db2d7 |
#include "ptycon_status_impl.h"
|
|
|
1bab02 |
|
|
|
640ed3 |
static ptyc_term_handler ptyc_screen_handler;
|
|
|
640ed3 |
static ptyc_term_handler ptyc_ctrl_handler;
|
|
|
640ed3 |
static ptyc_term_handler ptyc_flush_screen_buffer;
|
|
|
640ed3 |
|
|
|
5399d4 |
int __stdcall ptyc_console_writer(struct ptyc_driver_ctx_impl * ictx)
|
|
|
1bab02 |
{
|
|
|
640ed3 |
int32_t status;
|
|
|
640ed3 |
nt_iosb iosb;
|
|
|
640ed3 |
size_t nsteps;
|
|
|
640ed3 |
void * hwait;
|
|
|
640ed3 |
unsigned char * inbuf;
|
|
|
640ed3 |
struct ptyc_term_ctx * tctx;
|
|
|
640ed3 |
nt_unicode_conversion_params_utf8_to_utf16 uc_params;
|
|
|
640ed3 |
|
|
|
640ed3 |
if ((status = ntapi->tt_create_private_event(
|
|
|
640ed3 |
&hwait,
|
|
|
640ed3 |
NT_NOTIFICATION_EVENT,
|
|
|
640ed3 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
640ed3 |
return status;
|
|
|
640ed3 |
|
|
|
640ed3 |
tctx = &ictx->tctx;
|
|
|
640ed3 |
inbuf = (unsigned char *)&tctx->data.in[1];
|
|
|
640ed3 |
|
|
|
640ed3 |
uc_params.dst_size_in_bytes = sizeof(tctx->data.out);
|
|
|
640ed3 |
uc_params.leftover_count = 0;
|
|
|
640ed3 |
uc_params.leftover_bytes = 0;
|
|
|
640ed3 |
|
|
|
640ed3 |
tctx->handler = ptyc_screen_handler;
|
|
|
640ed3 |
tctx->char_handler = ptyc_screen_handler;
|
|
|
640ed3 |
tctx->ctrl_handler = ptyc_ctrl_handler;
|
|
|
640ed3 |
tctx->ctrl_handlers[0] = ptyc_esi_handlers;
|
|
|
640ed3 |
tctx->wch_con = tctx->data.screen;
|
|
|
640ed3 |
|
|
|
640ed3 |
do {
|
|
|
640ed3 |
uc_params.code_points = 0;
|
|
|
640ed3 |
uc_params.addr_failed = 0;
|
|
|
640ed3 |
uc_params.bytes_written = 0;
|
|
|
640ed3 |
|
|
|
640ed3 |
status = ntapi->pty_read(
|
|
|
640ed3 |
ictx->cctx.hptm,
|
|
|
640ed3 |
hwait,0,0,
|
|
|
640ed3 |
&iosb,
|
|
|
640ed3 |
inbuf,
|
|
|
640ed3 |
sizeof(tctx->data.in) - sizeof(uintptr_t),
|
|
|
640ed3 |
0,0);
|
|
|
640ed3 |
|
|
|
640ed3 |
if (status == NT_STATUS_PENDING)
|
|
|
6db2d7 |
if (!(status = ntapi->zw_wait_for_single_object(
|
|
|
6db2d7 |
hwait,NT_SYNC_ALERTABLE,0)))
|
|
|
6db2d7 |
status = iosb.status;
|
|
|
640ed3 |
|
|
|
6db2d7 |
if (status)
|
|
|
6db2d7 |
return ptyc_set_status(&ictx->ctx,status);
|
|
|
640ed3 |
|
|
|
640ed3 |
/* account for leftover bytes from the previous conversion */
|
|
|
640ed3 |
tctx->data.in[0] = uc_params.leftover_bytes;
|
|
|
da425a |
uc_params.src = inbuf - uc_params.leftover_count;
|
|
|
640ed3 |
uc_params.src_size_in_bytes = iosb.info + uc_params.leftover_count;
|
|
|
640ed3 |
uc_params.dst = tctx->data.out;
|
|
|
640ed3 |
|
|
|
640ed3 |
|
|
|
640ed3 |
/* utf-8 --> utf-16 */
|
|
|
640ed3 |
status = ntapi->uc_convert_unicode_stream_utf8_to_utf16(
|
|
|
640ed3 |
&uc_params);
|
|
|
640ed3 |
|
|
|
640ed3 |
/* process the converted (utf-16) stream */
|
|
|
640ed3 |
tctx->wch_pty = tctx->data.out;
|
|
|
640ed3 |
nsteps = uc_params.bytes_written / sizeof(wchar16_t);
|
|
|
640ed3 |
|
|
|
640ed3 |
for (; nsteps; nsteps--)
|
|
|
640ed3 |
tctx->handler = (ptyc_term_handler *)tctx->handler(tctx);
|
|
|
640ed3 |
|
|
|
640ed3 |
/* output to console */
|
|
|
640ed3 |
ptyc_flush_screen_buffer(tctx);
|
|
|
640ed3 |
} while (1);
|
|
|
640ed3 |
|
|
|
640ed3 |
return NT_STATUS_INTERNAL_ERROR;
|
|
|
640ed3 |
}
|
|
|
640ed3 |
|
|
|
640ed3 |
|
|
|
640ed3 |
static void * __fastcall ptyc_screen_handler(struct ptyc_term_ctx * tctx)
|
|
|
640ed3 |
{
|
|
|
640ed3 |
if (*tctx->wch_pty == '\x1b') {
|
|
|
640ed3 |
/* output all pending characters */
|
|
|
640ed3 |
ptyc_flush_screen_buffer(tctx);
|
|
|
640ed3 |
|
|
|
640ed3 |
/* advance stream pointer */
|
|
|
640ed3 |
tctx->wch_pty++;
|
|
|
640ed3 |
|
|
|
640ed3 |
/* set initial control state */
|
|
|
640ed3 |
tctx->ctrl_state = PTYC_CTRL_STATE_ESI;
|
|
|
640ed3 |
tctx->ctrl_cap = PTYC_ESI_ARRAY_SIZE;
|
|
|
640ed3 |
|
|
|
640ed3 |
/* switch mode */
|
|
|
640ed3 |
return tctx->ctrl_handler;
|
|
|
640ed3 |
} else {
|
|
|
79c2fe |
/* filter out bell key? */
|
|
|
79c2fe |
if (*tctx->wch_pty == 0x7)
|
|
|
79c2fe |
if (!(tctx->drvflags & PTYC_DRIVER_BELL))
|
|
|
79c2fe |
return ptyc_screen_handler;
|
|
|
79c2fe |
|
|
|
640ed3 |
/* copy character to the screen buffer */
|
|
|
640ed3 |
*tctx->wch_con = *tctx->wch_pty;
|
|
|
640ed3 |
|
|
|
640ed3 |
/* advance the screen and stream pointers */
|
|
|
640ed3 |
tctx->wch_con++;
|
|
|
640ed3 |
tctx->wch_pty++;
|
|
|
640ed3 |
|
|
|
640ed3 |
/* retain mode */
|
|
|
640ed3 |
return ptyc_screen_handler;
|
|
|
640ed3 |
}
|
|
|
640ed3 |
}
|
|
|
640ed3 |
|
|
|
640ed3 |
|
|
|
640ed3 |
static void * __fastcall ptyc_ctrl_handler(struct ptyc_term_ctx * tctx)
|
|
|
640ed3 |
{
|
|
|
640ed3 |
ptyc_term_handler * const * handlers;
|
|
|
640ed3 |
ptyc_term_handler * handler;
|
|
|
640ed3 |
unsigned idx;
|
|
|
640ed3 |
|
|
|
640ed3 |
idx = (*tctx->wch_pty < tctx->ctrl_cap)
|
|
|
640ed3 |
? *tctx->wch_pty
|
|
|
640ed3 |
: tctx->ctrl_cap - 1;
|
|
|
640ed3 |
|
|
|
640ed3 |
handlers = tctx->ctrl_handlers[tctx->ctrl_state];
|
|
|
640ed3 |
handler = handlers[idx];
|
|
|
640ed3 |
|
|
|
640ed3 |
return handler(tctx);
|
|
|
640ed3 |
}
|
|
|
640ed3 |
|
|
|
640ed3 |
|
|
|
640ed3 |
static void * __fastcall ptyc_flush_screen_buffer(struct ptyc_term_ctx * tctx)
|
|
|
640ed3 |
{
|
|
|
640ed3 |
uint32_t ncunits;
|
|
|
640ed3 |
uint32_t nwritten;
|
|
|
640ed3 |
|
|
|
640ed3 |
if (!(ncunits = (uint32_t)(tctx->wch_con - tctx->data.screen)))
|
|
|
640ed3 |
return tctx->wch_con;
|
|
|
640ed3 |
|
|
|
640ed3 |
ntcon->write_console_utf16(
|
|
|
640ed3 |
tctx->hout,
|
|
|
640ed3 |
tctx->data.screen,
|
|
|
640ed3 |
ncunits,
|
|
|
640ed3 |
&nwritten,
|
|
|
640ed3 |
0);
|
|
|
640ed3 |
|
|
|
eb4b7f |
/* heuristics: interactive input? */
|
|
|
eb4b7f |
if (ncunits <= 4) {
|
|
|
eb4b7f |
ntcon->get_console_screen_buffer_info(
|
|
|
eb4b7f |
tctx->hout,
|
|
|
eb4b7f |
&tctx->screen_info);
|
|
|
eb4b7f |
|
|
|
eb4b7f |
ntcon->set_console_cursor_position(
|
|
|
eb4b7f |
tctx->hout,
|
|
|
eb4b7f |
tctx->screen_info.cursor_position);
|
|
|
eb4b7f |
}
|
|
|
2ded43 |
|
|
|
640ed3 |
tctx->wch_con = tctx->data.screen;
|
|
|
640ed3 |
|
|
|
640ed3 |
return tctx->wch_con;
|
|
|
1bab02 |
}
|