diff --git a/src/cioxtrn/Makefile b/src/cioxtrn/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8e5a02deab126cccaac6992e81aa8a3ee8a86dbf --- /dev/null +++ b/src/cioxtrn/Makefile @@ -0,0 +1,11 @@ +WITHOUT_SDL=yes +SRC_ROOT = .. +!include ${SRC_ROOT}\build\Common.bmake + +CFLAGS = $(CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) +LDFLAGS = $(LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) +CFLAGS = $(CFLAGS) -W + +$(CIOXTRN): $(OBJS) + @echo Linking $@ + ${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) -e$@ $(OBJS) $(CIOLIB-MT_LIBS) $(XPDEV-MT_LIBS) diff --git a/src/cioxtrn/cioxtrn.c b/src/cioxtrn/cioxtrn.c new file mode 100644 index 0000000000000000000000000000000000000000..ee060ff9a67948cc021e44ba44d7610c544b6b83 --- /dev/null +++ b/src/cioxtrn/cioxtrn.c @@ -0,0 +1,251 @@ +#include <Windows.h> +#include <stdio.h> +#include "genwrap.h" +#include "ciolib.h" + +HANDLE console_output; +HANDLE console_input; +int terminate=0; +int input_thread_running=0; +int output_thread_running=0; + +void input_thread(void *args) +{ + int key; + INPUT_RECORD ckey; + int alt=0; + DWORD d; + SHORT s; + + input_thread_running=1; + while(!terminate) { + key=getch(); + if(key==0 || key == 0xff) + key|=getch()<<8; + if(key==1) { + if(alt==0) { + alt=1; + ckey.Event.KeyEvent.bKeyDown=TRUE; + ckey.Event.KeyEvent.dwControlKeyState = LEFT_ALT_PRESSED; + } + else { + alt=0; + ckey.Event.KeyEvent.bKeyDown=FALSE; + ckey.Event.KeyEvent.dwControlKeyState = 0; + } + ckey.Event.KeyEvent.wRepeatCount=1; + ckey.Event.KeyEvent.wVirtualKeyCode=VK_MENU; /* ALT key */ + ckey.Event.KeyEvent.wVirtualScanCode=MapVirtualKey(VK_MENU, 0); + ckey.Event.KeyEvent.uChar.AsciiChar=0; + d=0; + while(!d) { + if(!WriteConsoleInput(console_input, &ckey, 1, &d)) + d=0; + } + if(alt) + continue; + } + + ckey.Event.KeyEvent.bKeyDown=TRUE; + ckey.Event.KeyEvent.wRepeatCount=1; + if(key < 256) { + s=VkKeyScan(key); + + /* No translation */ + if(s==-1) + continue; + + ckey.Event.KeyEvent.wVirtualKeyCode = s&0xff; + ckey.Event.KeyEvent.dwControlKeyState=0; + if(s&0x0100) + ckey.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED; + if(s&0x0200) + ckey.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; + if(s&0x0400) + ckey.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; + + ckey.Event.KeyEvent.wVirtualScanCode=MapVirtualKey(s & 0xff, 0); + ckey.Event.KeyEvent.uChar.AsciiChar=key; + } + else { + ckey.Event.KeyEvent.wVirtualKeyCode=MapVirtualKey(key, 1); + ckey.Event.KeyEvent.wVirtualScanCode=key; + ckey.Event.KeyEvent.uChar.AsciiChar=0; + + if(key<' ') + ckey.Event.KeyEvent.dwControlKeyState=LEFT_CTRL_PRESSED; + else + ckey.Event.KeyEvent.dwControlKeyState=0; + } + if(alt) + ckey.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; + + ckey.EventType=KEY_EVENT; + d=0; + while(!d) { + if(!WriteConsoleInput(console_input, &ckey, 1, &d)) + d=0; + } + ckey.Event.KeyEvent.bKeyDown=FALSE; + d=0; + while(!d) { + if(!WriteConsoleInput(console_input, &ckey, 1, &d)) + d=0; + } + if(alt) { + ckey.Event.KeyEvent.bKeyDown=FALSE; + ckey.Event.KeyEvent.wRepeatCount=1; + ckey.Event.KeyEvent.wVirtualKeyCode=VK_MENU; /* ALT key */ + ckey.Event.KeyEvent.wVirtualScanCode=MapVirtualKey(VK_MENU, 0); + ckey.Event.KeyEvent.uChar.AsciiChar=0; + ckey.Event.KeyEvent.dwControlKeyState = LEFT_ALT_PRESSED; + d=0; + while(!d) { + if(!WriteConsoleInput(console_input, &ckey, 1, &d)) + d=0; + } + alt=0; + } + } + input_thread_running=0; +} + +void output_thread(void *args) +{ + SMALL_RECT screen_area; + CHAR_INFO from_screen[80*24]; + unsigned char write_buf[80*24*2]; + unsigned char current_screen[80*24*2]; + CONSOLE_SCREEN_BUFFER_INFO console_output_info; + COORD size; + COORD pos; + int i,j; + + pos.X=0; + pos.Y=0; + size.X=80; + size.Y=24; + + output_thread_running=1; + while(!terminate) { + SLEEP(10); + + /* Read the console screen buffer */ + screen_area.Left=0; + screen_area.Right=79; + screen_area.Top=0; + screen_area.Bottom=23; + ReadConsoleOutput(console_output, from_screen, size, pos, &screen_area); + + /* Translate to a ciolib buffer */ + j=0; + for(i=0; i<sizeof(from_screen)/sizeof(CHAR_INFO); i++) { + write_buf[j++]=from_screen[i].Char.AsciiChar; + write_buf[j++]=from_screen[i].Attributes & 0xff; + } + + /* Compare against the current screen */ + gettext(1,1,80,24,current_screen); + if(memcmp(current_screen,write_buf,sizeof(write_buf))) + puttext(1,1,80,24,write_buf); + + /* Update cursor position */ + if(GetConsoleScreenBufferInfo(console_output, &console_output_info)) + gotoxy(console_output_info.dwCursorPosition.X+1,console_output_info.dwCursorPosition.Y+1); + } + output_thread_running=0; +} + +int WINAPI WinMain(HINSTANCE inst, HINSTANCE pinst, char *cmd, int cshow) +{ + PROCESS_INFORMATION process_info; + STARTUPINFO startup_info; + COORD size; + SMALL_RECT screen_area; + HANDLE ntvdm; + DWORD d; + SECURITY_ATTRIBUTES sec_attrib; + + initciolib(CIOLIB_MODE_ANSI); + FreeConsole(); + + if(!AllocConsole()) + return(1); + + memset(&sec_attrib,0,sizeof(sec_attrib)); + sec_attrib.nLength=sizeof(sec_attrib); + sec_attrib.bInheritHandle=TRUE; + + console_output=CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_attrib, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0L); + if(console_output==INVALID_HANDLE_VALUE) { + printf("CONOUT Error: %u\r\n",GetLastError()); + return(1); + } + console_input=CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_attrib, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0L); + if(console_input==INVALID_HANDLE_VALUE) { + printf("CONIN Error: %u\r\n",GetLastError()); + return(1); + } + + size.X=80; + size.Y=24; + screen_area.Left=0; + screen_area.Right=79; + screen_area.Top=0; + screen_area.Bottom=23; + + SetConsoleCP(437); + SetConsoleOutputCP(437); + + /* Size console to size */ + SetConsoleScreenBufferSize(console_output, size); + SetConsoleWindowInfo(console_output, TRUE, &screen_area); + SetConsoleScreenBufferSize(console_output, size); + + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb=sizeof(startup_info); + startup_info.hStdInput=console_input; + startup_info.hStdOutput=console_output; + startup_info.hStdError=console_output; + startup_info.dwFlags = STARTF_USESTDHANDLES; + + if(!CreateProcess(NULL /* Read name from command line */ + , cmd + , NULL + , NULL + , TRUE /* Inherit Handles */ + , CREATE_SEPARATE_WOW_VDM + , NULL + , NULL + , &startup_info + , &process_info + )) { + printf("Error: %u\r\n",GetLastError()); + return(1); + } + CloseHandle(process_info.hThread); + ntvdm=OpenProcess(PROCESS_TERMINATE, FALSE, process_info.dwProcessId); + + /* Handle input */ + _beginthread(input_thread,0,NULL); + /* Handle output */ + _beginthread(output_thread,0,NULL); + + while(1) { + if(GetExitCodeProcess(process_info.hProcess, &d)) { + if(d != STILL_ACTIVE) { + terminate=1; + while(input_thread_running || output_thread_running) + SLEEP(1); + TerminateProcess(ntvdm,0); + CloseHandle(ntvdm); + CloseHandle(console_output); + CloseHandle(console_input); + CloseHandle(process_info.hProcess); + FreeConsole(); + return(0); + } + } + SLEEP(1); + } +} diff --git a/src/cioxtrn/objects.mk b/src/cioxtrn/objects.mk new file mode 100644 index 0000000000000000000000000000000000000000..5651ece6c35754f316d40ca4c382d49decdbd135 --- /dev/null +++ b/src/cioxtrn/objects.mk @@ -0,0 +1,2 @@ +OBJS = \ + $(MTOBJODIR)$(DIRSEP)cioxtrn$(OFILE) diff --git a/src/cioxtrn/targets.mk b/src/cioxtrn/targets.mk new file mode 100644 index 0000000000000000000000000000000000000000..3d2efd819d6abce0329fdb703aadc175aad8b2ac --- /dev/null +++ b/src/cioxtrn/targets.mk @@ -0,0 +1,4 @@ +CIOXTRN = $(EXEODIR)$(DIRSEP)cioxtrn$(EXEFILE) + +all: $(OBJODIR) $(MTOBJODIR) $(EXEODIR) $(CIOXTRN) +