Added support for the Win32 Console interface to the main DOSVM event
loop. Cleaned up event dispatching code a bit.
This commit is contained in:
parent
9f5ef0b410
commit
d5cab2a058
|
@ -32,7 +32,7 @@ typedef struct _DOSTASK {
|
||||||
HANDLE hReadPipe,hXPipe,hConInput,hConOutput;
|
HANDLE hReadPipe,hXPipe,hConInput,hConOutput;
|
||||||
int read_pipe,write_pipe;
|
int read_pipe,write_pipe;
|
||||||
pid_t task;
|
pid_t task;
|
||||||
int sig_sent;
|
int sig_sent,entered,idling;
|
||||||
struct _DOSEVENT *pending,*current;
|
struct _DOSEVENT *pending,*current;
|
||||||
DOSSYSTEM *sys;
|
DOSSYSTEM *sys;
|
||||||
} DOSTASK, *LPDOSTASK;
|
} DOSTASK, *LPDOSTASK;
|
||||||
|
|
|
@ -22,9 +22,11 @@
|
||||||
#include "wine/winbase16.h"
|
#include "wine/winbase16.h"
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
#include "wingdi.h"
|
#include "wingdi.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
#include "wincon.h"
|
||||||
|
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
#include "msdos.h"
|
#include "msdos.h"
|
||||||
|
@ -196,7 +198,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
|
||||||
LPDOSTASK lpDosTask = MZ_Current();
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
LPDOSEVENT event, cur, prev;
|
LPDOSEVENT event, cur, prev;
|
||||||
|
|
||||||
if (lpDosTask) {
|
if (lpDosTask && lpDosTask->entered) {
|
||||||
event = malloc(sizeof(DOSEVENT));
|
event = malloc(sizeof(DOSEVENT));
|
||||||
if (!event) {
|
if (!event) {
|
||||||
ERR_(int)("out of memory allocating event entry\n");
|
ERR_(int)("out of memory allocating event entry\n");
|
||||||
|
@ -216,14 +218,26 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
|
||||||
if (prev) prev->next = event;
|
if (prev) prev->next = event;
|
||||||
else lpDosTask->pending = event;
|
else lpDosTask->pending = event;
|
||||||
|
|
||||||
/* get dosmod's attention to the new event, except for irq==0 where we already have it */
|
/* get dosmod's attention to the new event, if necessary */
|
||||||
if (irq && !lpDosTask->sig_sent) {
|
if (!lpDosTask->sig_sent) {
|
||||||
TRACE_(int)("new event queued, signalling dosmod\n");
|
TRACE_(int)("new event queued, signalling dosmod\n");
|
||||||
kill(lpDosTask->task,SIGUSR2);
|
kill(lpDosTask->task,SIGUSR2);
|
||||||
lpDosTask->sig_sent++;
|
lpDosTask->sig_sent++;
|
||||||
} else {
|
} else {
|
||||||
TRACE_(int)("new event queued\n");
|
TRACE_(int)("new event queued\n");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* DOS subsystem not running */
|
||||||
|
/* (this probably means that we're running a win16 app
|
||||||
|
* which uses DPMI to thunk down to DOS services) */
|
||||||
|
if (irq<0) {
|
||||||
|
/* callback event, perform it with dummy context */
|
||||||
|
CONTEXT86 context;
|
||||||
|
memset(&context,0,sizeof(context));
|
||||||
|
(*relay)(lpDosTask,&context,data);
|
||||||
|
} else {
|
||||||
|
ERR_(int)("IRQ without DOS task: should not happen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +280,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
|
||||||
TRACE_(int)("DOS module caught signal %d\n",sig);
|
TRACE_(int)("DOS module caught signal %d\n",sig);
|
||||||
if ((sig==SIGALRM) || (sig==SIGUSR2)) {
|
if ((sig==SIGALRM) || (sig==SIGUSR2)) {
|
||||||
if (sig==SIGALRM) {
|
if (sig==SIGALRM) {
|
||||||
|
lpDosTask->sig_sent++;
|
||||||
DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
|
DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
|
||||||
}
|
}
|
||||||
if (lpDosTask->pending) {
|
if (lpDosTask->pending) {
|
||||||
|
@ -277,7 +292,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
|
||||||
TRACE_(int)("no events are pending, clearing Pending flag\n");
|
TRACE_(int)("no events are pending, clearing Pending flag\n");
|
||||||
CLR_PEND(&context);
|
CLR_PEND(&context);
|
||||||
}
|
}
|
||||||
if (sig==SIGUSR2) lpDosTask->sig_sent--;
|
lpDosTask->sig_sent--;
|
||||||
}
|
}
|
||||||
else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) {
|
else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) {
|
||||||
do_exception( sig, &context );
|
do_exception( sig, &context );
|
||||||
|
@ -320,11 +335,36 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
|
static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask)
|
||||||
|
{
|
||||||
|
INPUT_RECORD msg;
|
||||||
|
DWORD res;
|
||||||
|
BYTE scan;
|
||||||
|
|
||||||
|
if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res)) {
|
||||||
|
switch (msg.EventType) {
|
||||||
|
case KEY_EVENT:
|
||||||
|
scan = msg.Event.KeyEvent.wVirtualScanCode;
|
||||||
|
if (!msg.Event.KeyEvent.bKeyDown) scan |= 0x80;
|
||||||
|
|
||||||
|
/* check whether extended bit is set,
|
||||||
|
* and if so, queue the extension prefix */
|
||||||
|
if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) {
|
||||||
|
INT_Int09SendScan(0xE0,0);
|
||||||
|
}
|
||||||
|
INT_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME_(int)("unhandled console event: %d\n", msg.EventType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
|
||||||
{
|
{
|
||||||
BYTE scan = 0;
|
BYTE scan = 0;
|
||||||
|
|
||||||
fprintf(stderr,"got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
|
TRACE_(int)("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
|
||||||
if ((msg->message>=WM_MOUSEFIRST)&&
|
if ((msg->message>=WM_MOUSEFIRST)&&
|
||||||
(msg->message<=WM_MOUSELAST)) {
|
(msg->message<=WM_MOUSELAST)) {
|
||||||
INT_Int33Message(msg->message,msg->wParam,msg->lParam);
|
INT_Int33Message(msg->message,msg->wParam,msg->lParam);
|
||||||
|
@ -354,8 +394,13 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
|
||||||
LPDOSTASK lpDosTask = MZ_Current();
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
MSG msg;
|
MSG msg;
|
||||||
DWORD waitret;
|
DWORD waitret;
|
||||||
|
HANDLE objs[2];
|
||||||
|
int objc;
|
||||||
BOOL got_msg = FALSE;
|
BOOL got_msg = FALSE;
|
||||||
|
|
||||||
|
objs[0]=GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
objs[1]=hObject;
|
||||||
|
objc=hObject?2:1;
|
||||||
do {
|
do {
|
||||||
/* check for messages (waste time before the response check below) */
|
/* check for messages (waste time before the response check below) */
|
||||||
while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
|
while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
|
||||||
|
@ -365,6 +410,15 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
|
||||||
Callout.DispatchMessageA(&msg);
|
Callout.DispatchMessageA(&msg);
|
||||||
got_msg = TRUE;
|
got_msg = TRUE;
|
||||||
}
|
}
|
||||||
|
if (!got_msg) {
|
||||||
|
/* check for console input */
|
||||||
|
INPUT_RECORD msg;
|
||||||
|
DWORD num;
|
||||||
|
if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) {
|
||||||
|
DOSVM_ProcessConsole(lpDosTask);
|
||||||
|
got_msg = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (read_pipe == -1) {
|
if (read_pipe == -1) {
|
||||||
if (got_msg) break;
|
if (got_msg) break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -376,15 +430,16 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
|
||||||
if (select(read_pipe+1,&readfds,NULL,NULL,&timeout)>0)
|
if (select(read_pipe+1,&readfds,NULL,NULL,&timeout)>0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* check for data from win32 console device */
|
|
||||||
|
|
||||||
/* nothing yet, block while waiting for something to do */
|
/* nothing yet, block while waiting for something to do */
|
||||||
waitret=MsgWaitForMultipleObjects(1,&hObject,FALSE,INFINITE,QS_ALLINPUT);
|
waitret=MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT);
|
||||||
if (waitret==(DWORD)-1) {
|
if (waitret==(DWORD)-1) {
|
||||||
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
|
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
|
||||||
}
|
}
|
||||||
if (read_pipe != -1) {
|
if ((read_pipe != -1) && hObject) {
|
||||||
if (waitret==WAIT_OBJECT_0) break;
|
if (waitret==(WAIT_OBJECT_0+1)) break;
|
||||||
|
}
|
||||||
|
if (waitret==WAIT_OBJECT_0) {
|
||||||
|
DOSVM_ProcessConsole(lpDosTask);
|
||||||
}
|
}
|
||||||
} while (TRUE);
|
} while (TRUE);
|
||||||
}
|
}
|
||||||
|
@ -424,7 +479,9 @@ int DOSVM_Enter( CONTEXT86 *context )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* main exchange loop */
|
/* main exchange loop */
|
||||||
|
lpDosTask->entered++;
|
||||||
do {
|
do {
|
||||||
|
TRACE_(module)("thread is: %lx\n",GetCurrentThreadId());
|
||||||
stat = VM86_ENTER;
|
stat = VM86_ENTER;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
/* transmit VM86 structure to dosmod task */
|
/* transmit VM86 structure to dosmod task */
|
||||||
|
@ -449,6 +506,10 @@ int DOSVM_Enter( CONTEXT86 *context )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
TRACE_(module)("dosmod return code=%d\n",stat);
|
TRACE_(module)("dosmod return code=%d\n",stat);
|
||||||
|
if (stat==DOSMOD_LEFTIDLE) {
|
||||||
|
lpDosTask->idling--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((len=read(lpDosTask->read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
|
if ((len=read(lpDosTask->read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
|
||||||
if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
|
if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
|
||||||
|
@ -471,6 +532,7 @@ int DOSVM_Enter( CONTEXT86 *context )
|
||||||
} else sig=0;
|
} else sig=0;
|
||||||
/* got response */
|
/* got response */
|
||||||
} while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0);
|
} while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0);
|
||||||
|
lpDosTask->entered--;
|
||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
#define CP(x,y) y##_reg(context) = VM86.regs.x
|
#define CP(x,y) y##_reg(context) = VM86.regs.x
|
||||||
|
@ -616,6 +678,16 @@ void DOSVM_SetTimer( unsigned ticks ) {}
|
||||||
unsigned DOSVM_GetTimer( void ) { return 0; }
|
unsigned DOSVM_GetTimer( void ) { return 0; }
|
||||||
void DOSVM_SetSystemData( int id, void *data ) { free(data); }
|
void DOSVM_SetSystemData( int id, void *data ) { free(data); }
|
||||||
void* DOSVM_GetSystemData( int id ) { return NULL; }
|
void* DOSVM_GetSystemData( int id ) { return NULL; }
|
||||||
void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data) {}
|
void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data)
|
||||||
|
{
|
||||||
|
if (irq<0) {
|
||||||
|
/* callback event, perform it with dummy context */
|
||||||
|
CONTEXT86 context;
|
||||||
|
memset(&context,0,sizeof(context));
|
||||||
|
(*relay)(lpDosTask,&context,data);
|
||||||
|
} else {
|
||||||
|
ERR_(int)("IRQ without DOS task: should not happen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue