| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static ptyc_term_handler ptyc_screen_handler; |
| static ptyc_term_handler ptyc_ctrl_handler; |
| static ptyc_term_handler ptyc_flush_screen_buffer; |
| |
| int __stdcall ptyc_console_writer(struct ptyc_driver_ctx_impl * ictx) |
| { |
| 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) |
| if (!(status = ntapi->zw_wait_for_single_object( |
| hwait,NT_SYNC_ALERTABLE,0))) |
| status = iosb.status; |
| |
| if (status) |
| return ptyc_set_status(&ictx->ctx,status); |
| |
| |
| tctx->data.in[0] = uc_params.leftover_bytes; |
| uc_params.src = inbuf - uc_params.leftover_count; |
| uc_params.src_size_in_bytes = iosb.info + uc_params.leftover_count; |
| uc_params.dst = tctx->data.out; |
| |
| |
| |
| status = ntapi->uc_convert_unicode_stream_utf8_to_utf16( |
| &uc_params); |
| |
| |
| 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); |
| |
| |
| 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') { |
| |
| ptyc_flush_screen_buffer(tctx); |
| |
| |
| tctx->wch_pty++; |
| |
| |
| tctx->ctrl_state = PTYC_CTRL_STATE_ESI; |
| tctx->ctrl_cap = PTYC_ESI_ARRAY_SIZE; |
| |
| |
| return tctx->ctrl_handler; |
| } else { |
| |
| if (*tctx->wch_pty == 0x7) |
| if (!(tctx->drvflags & PTYC_DRIVER_BELL)) |
| return ptyc_screen_handler; |
| |
| |
| *tctx->wch_con = *tctx->wch_pty; |
| |
| |
| tctx->wch_con++; |
| tctx->wch_pty++; |
| |
| |
| 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); |
| |
| |
| if (ncunits <= 4) { |
| ntcon->get_console_screen_buffer_info( |
| tctx->hout, |
| &tctx->screen_info); |
| |
| ntcon->set_console_cursor_position( |
| tctx->hout, |
| tctx->screen_info.cursor_position); |
| } |
| |
| tctx->wch_con = tctx->data.screen; |
| |
| return tctx->wch_con; |
| } |