Blame src/console/ptyc_console_reader.c

1bab02
/*********************************************************/
1bab02
/*  ptycon: a pty-console bridge                         */
f25e99
/*  Copyright (C) 2016--2017  SysDeer Technologies, LLC  */
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"
1bab02
029664
typedef nt_unicode_conversion_params_utf16_to_utf8 uc_conv_params;
029664
77a707
extern const struct ptyc_vkcode ptyc_vkcode[0x100];
77a707
5ee033
static size_t ptyc_repeat(unsigned char * ch, size_t n, uint16_t count)
5ee033
{
5ee033
	unsigned char * dst;
5ee033
	int		i;
5ee033
5ee033
	if (!--count)
5ee033
		return n;
5ee033
5ee033
	if (n == 1) {
5ee033
		for (i=count, dst=&ch[n]; i; i--) {
5ee033
			dst[0] = ch[0];
5ee033
			dst = &dst[n];
5ee033
		}
5ee033
5ee033
	} else if (n == 2) {
5ee033
		for (i=count, dst=&ch[n]; i; i--) {
5ee033
			dst[0] = ch[0];
5ee033
			dst[1] = ch[1];
5ee033
			dst = &dst[n];
5ee033
		}
5ee033
5ee033
	} else if (n == 3) {
5ee033
		for (i=count, dst=&ch[n]; i; i--) {
5ee033
			dst[0] = ch[0];
5ee033
			dst[1] = ch[1];
5ee033
			dst[2] = ch[2];
5ee033
			dst = &dst[n];
5ee033
		}
5ee033
5ee033
	} else if (n == 4) {
5ee033
		for (i=count, dst=&ch[n]; i; i--) {
5ee033
			dst[0] = ch[0];
5ee033
			dst[1] = ch[1];
5ee033
			dst[2] = ch[2];
5ee033
			dst[3] = ch[3];
5ee033
			dst = &dst[n];
5ee033
		}
5ee033
	}
5ee033
5ee033
	return n*count;
5ee033
}
5ee033
77a707
static size_t ptyc_translate_virtual_keycode(
77a707
	nt_input_record *	rec,
77a707
	unsigned char *		ch)
77a707
{
77a707
	ntapi->tt_generic_memcpy(
77a707
		ch,
77a707
		ptyc_vkcode[rec->key_event.virtual_key_code].mbstr,
77a707
		ptyc_vkcode[rec->key_event.virtual_key_code].mblen);
77a707
77a707
	return ptyc_repeat(
77a707
		ch,
77a707
		ptyc_vkcode[rec->key_event.virtual_key_code].mblen,
77a707
		rec->key_event.repeat_count);
77a707
}
77a707
029664
static size_t ptyc_translate_keyboard_event(
029664
	nt_input_record *	rec,
029664
	unsigned char *		ch,
029664
	wchar16_t *		wch)
029664
{
029664
	wchar16_t	src[2];
029664
	wchar16_t	recwch;
029664
	uint32_t	nbytes;
029664
	uc_conv_params	params = {0,0,0,0,0,0,0,0,0};
029664
029664
	if (!rec->key_event.key_down)
029664
		return 0;
029664
029664
	if (!(recwch = rec->key_event.unicode_char))
77a707
		return ptyc_translate_virtual_keycode(
77a707
			rec,ch);
029664
083e87
	if (recwch == 0x08)
083e87
		recwch = 0x7f;
083e87
029664
	if (*wch) {
029664
		if ((recwch < 0xDC00) || (recwch >= 0xE000)) {
029664
			*wch = 0;
029664
			return 0;
029664
		} else {
029664
			src[0] = *wch;
029664
			src[1] = recwch;
029664
			*wch   = 0;
029664
			nbytes = 2*sizeof(wchar16_t);
029664
		}
029664
	} else if ((recwch >= 0xD800) && (recwch < 0xDC00)) {
029664
		*wch = recwch;
029664
		return 0;
029664
029664
	} else {
029664
		src[0] = recwch;
029664
		nbytes = sizeof(wchar16_t);
029664
	}
029664
029664
	params.src		 = src;
029664
	params.src_size_in_bytes = nbytes;
029664
	params.dst		 = ch;
029664
	params.dst_size_in_bytes = 4;
029664
029664
	ntapi->uc_convert_unicode_stream_utf16_to_utf8(
029664
		&params);
029664
5ee033
	return ptyc_repeat(
5ee033
		ch,
5ee033
		params.bytes_written,
5ee033
		rec->key_event.repeat_count);
029664
}
029664
029664
static size_t ptyc_translate_mouse_event(
029664
	nt_input_record *	rec,
029664
	unsigned char *		ch)
029664
{
029664
	(void)rec;
029664
	(void)ch;
029664
	return 0;
029664
}
029664
029664
static size_t ptyc_translate_window_event(nt_input_record * rec)
029664
{
029664
	(void)rec;
029664
	return 0;
029664
}
029664
029664
static size_t ptyc_translate_menu_event(nt_input_record * rec)
029664
{
029664
	(void)rec;
029664
	return 0;
029664
}
029664
029664
static size_t ptyc_translate_focus_event(nt_input_record * rec)
029664
{
029664
	(void)rec;
029664
	return 0;
029664
}
029664
029664
static size_t ptyc_translate_event(
029664
	nt_input_record *	rec,
029664
	unsigned char *		ch,
029664
	wchar16_t *		wch)
029664
{
029664
	switch (rec->event_type) {
029664
		case NT_KEY_EVENT:
029664
			return ptyc_translate_keyboard_event(
029664
				rec,ch,wch);
029664
029664
		case NT_MOUSE_EVENT:
029664
			return ptyc_translate_mouse_event(
029664
				rec,ch);
029664
029664
		case NT_WINDOW_BUFFER_SIZE_EVENT:
029664
			return ptyc_translate_window_event(rec);
029664
029664
		case NT_MENU_EVENT:
029664
			return ptyc_translate_menu_event(rec);
029664
029664
		case NT_FOCUS_EVENT:
029664
			return ptyc_translate_focus_event(rec);
029664
	}
029664
029664
	return 0;
029664
}
029664
5399d4
int __stdcall ptyc_console_reader(struct ptyc_driver_ctx_impl * ictx)
1bab02
{
029664
	int32_t		status;
029664
	void *		hwait;
029664
	nt_iosb		iosb;
029664
	uint32_t	nevents;
029664
	size_t		nbytes;
029664
	wchar16_t	wch;
029664
	unsigned char *	ch;
029664
	unsigned	i;
029664
029664
	if ((status = ntapi->tt_create_private_event(
029664
			&hwait,
029664
			NT_NOTIFICATION_EVENT,
029664
			NT_EVENT_NOT_SIGNALED)))
029664
		return status;
029664
029664
	do {
029664
		if (!(ntcon->read_console_input_utf16(
029664
				ictx->tctx.hin,
029664
				ictx->tctx.input.events,
029664
				PTYC_RAW_EVENTS,
029664
				&nevents)))
029664
			return NT_STATUS_ALREADY_DISCONNECTED;
029664
029664
		for (ch=ictx->tctx.input.stream, i=0; i
029664
			ch += ptyc_translate_event(
029664
				&ictx->tctx.input.events[i],
029664
				ch,&wch;;
029664
029664
		nbytes = ch - ictx->tctx.input.stream;
029664
		ch     = ictx->tctx.input.stream;
029664
029664
		for (; nbytes; ) {
029664
			status = ntapi->pty_write(
029664
				ictx->cctx.hptm,
1317da
				hwait,0,0,&iosb,
1317da
				ch,(uint32_t)nbytes,
029664
				0,0);
029664
029664
			if (status == NT_STATUS_PENDING)
029664
				status = ntapi->zw_wait_for_single_object(
029664
					hwait,NT_SYNC_ALERTABLE,0);
029664
029664
			if (status || iosb.status) {
029664
				ntapi->zw_close(hwait);
029664
				return status ? status : iosb.status;
029664
			}
029664
029664
			ch     += iosb.info;
029664
			nbytes -= iosb.info;
029664
		}
029664
	} while (1);
029664
029664
	return NT_STATUS_INTERNAL_ERROR;
1bab02
}