| |
| |
| |
| |
| |
| |
| #include <psxtypes/psxtypes.h> |
| #include <ntcon/ntcon.h> |
| #include <ntapi/ntapi.h> |
| #include <gdi/gdi.h> |
| |
| #include <ptycon/ptycon.h> |
| #include "ptycon_driver_impl.h" |
| |
| typedef nt_unicode_conversion_params_utf16_to_utf8 uc_conv_params; |
| |
| extern const struct ptyc_vkcode ptyc_vkcode[0x100]; |
| |
| static size_t ptyc_repeat(unsigned char * ch, size_t n, uint16_t count) |
| { |
| unsigned char * dst; |
| int i; |
| |
| if (!--count) |
| return n; |
| |
| if (n == 1) { |
| for (i=count, dst=&ch[n]; i; i--) { |
| dst[0] = ch[0]; |
| dst = &dst[n]; |
| } |
| |
| } else if (n == 2) { |
| for (i=count, dst=&ch[n]; i; i--) { |
| dst[0] = ch[0]; |
| dst[1] = ch[1]; |
| dst = &dst[n]; |
| } |
| |
| } else if (n == 3) { |
| for (i=count, dst=&ch[n]; i; i--) { |
| dst[0] = ch[0]; |
| dst[1] = ch[1]; |
| dst[2] = ch[2]; |
| dst = &dst[n]; |
| } |
| |
| } else if (n == 4) { |
| for (i=count, dst=&ch[n]; i; i--) { |
| dst[0] = ch[0]; |
| dst[1] = ch[1]; |
| dst[2] = ch[2]; |
| dst[3] = ch[3]; |
| dst = &dst[n]; |
| } |
| } |
| |
| return n*count; |
| } |
| |
| static size_t ptyc_translate_virtual_keycode( |
| nt_input_record * rec, |
| unsigned char * ch) |
| { |
| ntapi->tt_generic_memcpy( |
| ch, |
| ptyc_vkcode[rec->key_event.virtual_key_code].mbstr, |
| ptyc_vkcode[rec->key_event.virtual_key_code].mblen); |
| |
| return ptyc_repeat( |
| ch, |
| ptyc_vkcode[rec->key_event.virtual_key_code].mblen, |
| rec->key_event.repeat_count); |
| } |
| |
| static size_t ptyc_translate_keyboard_event( |
| nt_input_record * rec, |
| unsigned char * ch, |
| wchar16_t * wch) |
| { |
| wchar16_t src[2]; |
| wchar16_t recwch; |
| uint32_t nbytes; |
| uc_conv_params params = {0,0,0,0,0,0,0,0,0}; |
| |
| if (!rec->key_event.key_down) |
| return 0; |
| |
| if (!(recwch = rec->key_event.unicode_char)) |
| return ptyc_translate_virtual_keycode( |
| rec,ch); |
| |
| if (recwch == 0x08) |
| recwch = 0x7f; |
| |
| if (*wch) { |
| if ((recwch < 0xDC00) || (recwch >= 0xE000)) { |
| *wch = 0; |
| return 0; |
| } else { |
| src[0] = *wch; |
| src[1] = recwch; |
| *wch = 0; |
| nbytes = 2*sizeof(wchar16_t); |
| } |
| } else if ((recwch >= 0xD800) && (recwch < 0xDC00)) { |
| *wch = recwch; |
| return 0; |
| |
| } else { |
| src[0] = recwch; |
| nbytes = sizeof(wchar16_t); |
| } |
| |
| params.src = src; |
| params.src_size_in_bytes = nbytes; |
| params.dst = ch; |
| params.dst_size_in_bytes = 4; |
| |
| ntapi->uc_convert_unicode_stream_utf16_to_utf8( |
| ¶ms); |
| |
| return ptyc_repeat( |
| ch, |
| params.bytes_written, |
| rec->key_event.repeat_count); |
| } |
| |
| static size_t ptyc_translate_mouse_event( |
| nt_input_record * rec, |
| unsigned char * ch) |
| { |
| (void)rec; |
| (void)ch; |
| return 0; |
| } |
| |
| static size_t ptyc_translate_window_event(nt_input_record * rec) |
| { |
| (void)rec; |
| return 0; |
| } |
| |
| static size_t ptyc_translate_menu_event(nt_input_record * rec) |
| { |
| (void)rec; |
| return 0; |
| } |
| |
| static size_t ptyc_translate_focus_event(nt_input_record * rec) |
| { |
| (void)rec; |
| return 0; |
| } |
| |
| static size_t ptyc_translate_event( |
| nt_input_record * rec, |
| unsigned char * ch, |
| wchar16_t * wch) |
| { |
| switch (rec->event_type) { |
| case NT_KEY_EVENT: |
| return ptyc_translate_keyboard_event( |
| rec,ch,wch); |
| |
| case NT_MOUSE_EVENT: |
| return ptyc_translate_mouse_event( |
| rec,ch); |
| |
| case NT_WINDOW_BUFFER_SIZE_EVENT: |
| return ptyc_translate_window_event(rec); |
| |
| case NT_MENU_EVENT: |
| return ptyc_translate_menu_event(rec); |
| |
| case NT_FOCUS_EVENT: |
| return ptyc_translate_focus_event(rec); |
| } |
| |
| return 0; |
| } |
| |
| int __stdcall ptyc_console_reader(struct ptyc_driver_ctx_impl * ictx) |
| { |
| int32_t status; |
| void * hwait; |
| nt_iosb iosb; |
| uint32_t nevents; |
| size_t nbytes; |
| wchar16_t wch; |
| unsigned char * ch; |
| unsigned i; |
| |
| if ((status = ntapi->tt_create_private_event( |
| &hwait, |
| NT_NOTIFICATION_EVENT, |
| NT_EVENT_NOT_SIGNALED))) |
| return status; |
| |
| do { |
| if (!(ntcon->read_console_input_utf16( |
| ictx->tctx.hin, |
| ictx->tctx.input.events, |
| PTYC_RAW_EVENTS, |
| &nevents))) |
| return NT_STATUS_ALREADY_DISCONNECTED; |
| |
| for (ch=ictx->tctx.input.stream, i=0; i<nevents; i++) |
| ch += ptyc_translate_event( |
| &ictx->tctx.input.events[i], |
| ch,&wch); |
| |
| nbytes = ch - ictx->tctx.input.stream; |
| ch = ictx->tctx.input.stream; |
| |
| for (; nbytes; ) { |
| status = ntapi->pty_write( |
| ictx->cctx.hptm, |
| hwait,0,0,&iosb, |
| ch,(uint32_t)nbytes, |
| 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; |
| } |
| |
| ch += iosb.info; |
| nbytes -= iosb.info; |
| } |
| } while (1); |
| |
| return NT_STATUS_INTERNAL_ERROR; |
| } |