Release 0.2.0
Tue Jul 13 20:31:31 1993 Bob Amstadt (bob at pooh)
* [global.c]
Completed global memory pool API
Sun Jul 11 16:59:52 1993 Alexandre Julliard
* [message.c] [user.c] [user.spec] [windows.h]
Added emulation of Windows message queue.
Thu Jul 8 19:29:27 1993 Bob Amstadt (bob at pooh)
* [build.c] Original by Bob Amstadt
* [callback.c] Original by Bob Amstadt, updates by
Alexandre Julliard
* [dump.c] Original by Bob Amstadt
* [global.c] Original by Bob Amstadt
* [heap.c] Original by Bob Amstadt
* [kernel.c] Original by Bob Amstadt
* [ldt.c] Original by Bob Amstadt
* [ldtlib.c] Original by Bob Amstadt
* [relay.c] Original by Bob Amstadt
* [resource.c] Original by Bob Amstadt, updates by
Alexandre Juliard
* [selector.c] Original by Bob Amstadt, updates by Eric Youngdale
* [user.c] Original by Bob Amstadt
* [wine.c] Original by Bob Amstadt, updates by Eric Youngdale and
Alexandre Julliard
* [wintcl.c] Original by Regents of the University of California,
updates by Peter MacDonald and Alexandre Julliard
* [callback.h] Original by Bob Amstadt
* [dlls.h] Original by Bob Amstadt
* [heap.h] Original by Bob Amstadt
* [neexe.h] Original by Bob Amstadt
* [prototypes.h] Original by Bob Amstadt, updates by
Eric Youngdale
* [segmem.h] Original by Bob Amstadt
* [tkInt.h] Original by Regents of the University of California
* [windows.h] Original by Peter MacDonald, updates by
Alexandre Julliard and Bob Amstadt
* [wine.h] Original by Eric Youngdale
* [kernel.spec] Original by Bob Amstadt, updates by
Alexandre Julliard
* [gdi.spec] Original by Bob Amstadt, updates by
Alexandre Julliard
* [shell.spec] Original by Bob Amstadt
* [unixlib.spec] Original by Bob Amstadt
* [user.spec] Original by Bob Amstadt, updates by Alexandre Julliard
* [win87em.spec] Original by Bob Amstadt
* [Windows.tcl] Original by Peter MacDonald, updates by
Alexandre Julliard
* [build-spec.txt] Original by Bob Amstadt
* [if1632.S] Original by Bob Amstadt, updates by Eric Youngdale
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..8407996
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,53 @@
+Tue Jul 13 20:31:31 1993 Bob Amstadt (bob at pooh)
+
+ * [global.c]
+ Completed global memory pool API
+
+Sun Jul 11 16:59:52 1993 Alexandre Julliard
+
+ * [message.c] [user.c] [user.spec] [windows.h]
+ Added emulation of Windows message queue.
+
+Thu Jul 8 19:29:27 1993 Bob Amstadt (bob at pooh)
+
+ * [build.c] Original by Bob Amstadt
+ * [callback.c] Original by Bob Amstadt, updates by
+ Alexandre Julliard
+ * [dump.c] Original by Bob Amstadt
+ * [global.c] Original by Bob Amstadt
+ * [heap.c] Original by Bob Amstadt
+ * [kernel.c] Original by Bob Amstadt
+ * [ldt.c] Original by Bob Amstadt
+ * [ldtlib.c] Original by Bob Amstadt
+ * [relay.c] Original by Bob Amstadt
+ * [resource.c] Original by Bob Amstadt, updates by
+ Alexandre Juliard
+ * [selector.c] Original by Bob Amstadt, updates by Eric Youngdale
+ * [user.c] Original by Bob Amstadt
+ * [wine.c] Original by Bob Amstadt, updates by Eric Youngdale and
+ Alexandre Julliard
+ * [wintcl.c] Original by Regents of the University of California,
+ updates by Peter MacDonald and Alexandre Julliard
+ * [callback.h] Original by Bob Amstadt
+ * [dlls.h] Original by Bob Amstadt
+ * [heap.h] Original by Bob Amstadt
+ * [neexe.h] Original by Bob Amstadt
+ * [prototypes.h] Original by Bob Amstadt, updates by
+ Eric Youngdale
+ * [segmem.h] Original by Bob Amstadt
+ * [tkInt.h] Original by Regents of the University of California
+ * [windows.h] Original by Peter MacDonald, updates by
+ Alexandre Julliard and Bob Amstadt
+ * [wine.h] Original by Eric Youngdale
+ * [kernel.spec] Original by Bob Amstadt, updates by
+ Alexandre Julliard
+ * [gdi.spec] Original by Bob Amstadt, updates by
+ Alexandre Julliard
+ * [shell.spec] Original by Bob Amstadt
+ * [unixlib.spec] Original by Bob Amstadt
+ * [user.spec] Original by Bob Amstadt, updates by Alexandre Julliard
+ * [win87em.spec] Original by Bob Amstadt
+ * [Windows.tcl] Original by Peter MacDonald, updates by
+ Alexandre Julliard
+ * [build-spec.txt] Original by Bob Amstadt
+ * [if1632.S] Original by Bob Amstadt, updates by Eric Youngdale
diff --git a/Makefile b/Makefile
index 43a4683..f386ccd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-g -DDEBUG_RESOURCE -DDEBUG_HEAP -I./
+CFLAGS=-g -DDEBUG_RESOURCE -I./
######################################################################
# FILES:
@@ -19,10 +19,10 @@
OBJS=$(MUST_BE_LINKED_FIRST) \
callback.o dump.o global.o heap.o ldt.o kernel.o relay.o resource.o \
- selector.o user.o wine.o wintcl.o
+ selector.o message.o user.o wine.o class.o win.o widgets.o event.o xt.o
TARGET=wine
-LIBS=-L. -L/usr/X386/lib -L/dasd3/usr/lib -lldt -ltk -ltcl -lX11
+LIBS=-L. -L/usr/X386/lib -lldt -lXt -lX11
all: $(TARGET)
diff --git a/README b/README
index 078934f..0a911df 100644
--- a/README
+++ b/README
@@ -2,14 +2,28 @@
warranty. It is my intent to cover this code with the Gnu Public
License.
-So here goes release 0.1.0 of the Windows loader. It will do some
+So here goes release 0.2.0 of the Windows loader. It will do some
relocations and then run the program. I have successfully loaded
the Windows solitaire game. Try it. It currently stops a call to
GetObject().
+WHAT'S NEW with version 0.2.0:
+ - Alexandre Julliard has provided a replacement for the Tcl code.
+ The new code uses Xlib and Xt directly with no intervening
+ interpretted language. This should reduce the learning
+ curve for casual hackers.
+ - I changed all GLOBAL_ names to Global.
+
+WHAT'S NEW with version 0.1.1:
+ - I have completed global memory allocation, but I don't like it.
+ It is not 100% compatible with Windows. I need some more kernel
+ modifications for 100% compatibility.
+ - Alexandre Julliard has provided written better emulation for
+ the Windows message queue.
+
WHAT'S NEW with version 0.1.0:
- - Integrated patches from Alexandre.
- - Minor bug fix in if1632.S
+ - Latest patches from Alexandre Julliard.
+ - minor bug fix in if1632.S
WHAT'S NEW with version 0.0.5:
- Patches from Alexandre Julliard. Some integration with Tcl.
@@ -59,9 +73,9 @@
- Segment fixup code completion.
- Trap and handle DOS and DPMI calls.
- - global memory allocation completion
- - GlobalAlloc should support ZEROINIT.
- GlobalAlloc of code segments.
+ - Rewrite global memory support including kernel mods to allow
+ application to mess with page map.
- complete and improve local heap allocation.
- Handle self-loading applications.
- Resource loading
@@ -85,6 +99,11 @@
- This is a patch that must be applied to the kernel.
It updates two header files, and the kernel Makefile.
+Or follow the same procedure with "ldt512.tar". This file contains
+Eric Youngdales patches for ALPHA-pl11. These patches give the
+emulator 512 ldt entries instead of the 32 available with the older
+patch kit.
+
BUILD:
The documentation for the build program is in the file build-spec.txt
diff --git a/Windows.tcl b/Windows.tcl
deleted file mode 100755
index 0257f1e..0000000
--- a/Windows.tcl
+++ /dev/null
@@ -1,91 +0,0 @@
-# Windows Tcl/Tk emulation scripts
-# Initial implementation by Peter MacDonald pmacdona@sanjuan.uvic.ca
-
-proc CreateWindow { f t x y h w } {
- global baseframe
- set baseframe $f
- wm title . "$t"
- frame .$f
- pack append . .$f {top}
- canvas .$f.canvas1 -scrollregion " $x $y $h $w " -width 15c -height 10c
- pack append .$f .$f.canvas1 {top}
-}
-
-proc CreateMenuEntry { fn t x } {
- global baseframe
- menubutton .$fn -text "$t" -underline $x -menu .$fn.m
- pack append .$baseframe .$fn left
- menu .$fn.m
-}
-
-proc CreateMenuBar { f } {
- global allmenus
- global baseframe
- set allmenus ""
- frame .$f -relief raised -borderwidth 1
- pack before .$baseframe .$f {top fillx}
-}
-
-proc AppendMenu { a b c d x } {
- global allmenus
- global baseframe
- if { ($b == 0x10) } {
- .$c configure -text "$d" -underline "$x"
- pack append .$a .$c left
- set allmenus "$allmenus $c"
- tk_menuBar .$a $allmenus
- tk_bindForTraversal .$baseframe.canvas1
- } else { if { ($b == 0x0800) } {
- .$a.m add separator
- } else {
- .$a.m add command -label "$d" -command "wincallback menu $a $b $c $d" -underline $x
- }}
-}
-
-####################################################################
-# Misc unimplemented stuff
-####################################################################
-
-proc LoadIcon { wind name } {
- echo "LoadIcon"
-}
-
-proc LoadBitmap { wind name } {
- echo "LoadBitmap"
-}
-
-proc LoadCursor { wind name } {
- echo "LoadCursor"
-}
-
-proc GetObject { obj count ptr } {
- echo "GetObject $obj $count $ptr"
-}
-
-proc GetStockObject { wind } {
- echo "GetStockObject $wind"
-}
-
-proc DefWindowProc { a b c d } {
- echo "DefWindowProc $a $b $c $d"
-}
-
-proc GetMenu { a } {
- echo "GetMenu $a"
-}
-
-proc SetMenu { a b } {
- echo "SetMenu $a $b"
-}
-
-proc MessageBeep {a } {
- echo "MessageBeep $a"
-}
-
-proc MessageBox { wind msg title type } {
- echo "MessageBox '$msg'"
-}
-
-proc DrawText { f t top left right bottom } {
- .$f.canvas1 create text $top $left -text "$t" -anchor n
-}
diff --git a/callback.c b/callback.c
index 0cfb00f..c0d82bd 100644
--- a/callback.c
+++ b/callback.c
@@ -1,6 +1,7 @@
static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
+#include "windows.h"
#include "callback.h"
#include "wine.h"
#include "segmem.h"
@@ -106,3 +107,22 @@
return tp->thunk;
}
+
+/**********************************************************************
+ * CallWindowProc (USER.122)
+ */
+LONG CallWindowProc( FARPROC func, HWND hwnd, WORD message,
+ WORD wParam, LONG lParam )
+{
+ if ((unsigned int)func & 0xffff0000)
+ {
+ PushOn16( CALLBACK_SIZE_WORD, hwnd );
+ PushOn16( CALLBACK_SIZE_WORD, message );
+ PushOn16( CALLBACK_SIZE_WORD, wParam );
+ PushOn16( CALLBACK_SIZE_LONG, lParam );
+ return CallTo16((unsigned int) func,
+ FindDataSegmentForCode((unsigned long) func));
+ }
+ else
+ return WIDGETS_Call32WndProc( func, hwnd, message, wParam, lParam );
+}
diff --git a/callback.h b/callback.h
index b867e43..ba84573 100644
--- a/callback.h
+++ b/callback.h
@@ -17,13 +17,4 @@
extern int CallBack16(void *func, int n_args, ...);
-/*
- * Windows procedure calling:
- * f(a, b, c, d)
- * wndprocfunc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
- */
-#define CALLWNDPROC(f, a, b, c, d) \
- CallBack16((f), 4, CALLBACK_SIZE_WORD, (a), CALLBACK_SIZE_WORD, (b), \
- CALLBACK_SIZE_WORD, (c), CALLBACK_SIZE_LONG, (d))
-
#endif /* CALLBACK_H */
diff --git a/class.c b/class.c
new file mode 100644
index 0000000..3a7cf2b
--- /dev/null
+++ b/class.c
@@ -0,0 +1,141 @@
+/*
+ * Window classes functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "class.h"
+
+
+static HCLASS firstClass = 0;
+
+
+/***********************************************************************
+ * CLASS_FindClassByName
+ *
+ * Return a handle and a pointer to the class.
+ * The caller must GlobalUnlock the pointer.
+ */
+HCLASS CLASS_FindClassByName( char * name, CLASS **ptr )
+{
+ HCLASS class, next;
+
+ class = firstClass;
+ while(class)
+ {
+ *ptr = (CLASS *) GlobalLock(class);
+ if (!strcmp( (*ptr)->wc.lpszClassName, name )) return class;
+ next = (*ptr)->hNext;
+ GlobalUnlock(class);
+ class = next;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * CLASS_FindClassPtr
+ *
+ * Return a pointer to the CLASS structure corresponding to a HCLASS.
+ * The caller must GlobalUnlock the pointer.
+ */
+CLASS * CLASS_FindClassPtr( HCLASS hclass )
+{
+ CLASS * ptr;
+
+ if (!hclass) return NULL;
+ ptr = (CLASS *) GlobalLock( hclass );
+ if (ptr->wMagic != CLASS_MAGIC)
+ {
+ GlobalUnlock( hclass );
+ return NULL;
+ }
+ return ptr;
+}
+
+
+/***********************************************************************
+ * RegisterClass (USER.57)
+ */
+ATOM RegisterClass( LPWNDCLASS class )
+{
+ CLASS * newClass;
+ HCLASS handle;
+ int i;
+
+#ifdef DEBUG_CLASS
+ printf( "RegisterClass: wndproc=%08x hinst=%d name='%s'\n",
+ class->lpfnWndProc, class->hInstance, class->lpszClassName );
+#endif
+
+ handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(CLASS)+class->cbClsExtra );
+ if (!handle) return 0;
+ newClass = (CLASS *) GlobalLock( handle );
+ newClass->hNext = firstClass;
+ newClass->wMagic = CLASS_MAGIC;
+ newClass->atomName = handle; /* Should be an atom */
+ newClass->hDCE = 0; /* Should allocate a DCE if needed */
+ newClass->cWindows = 0;
+ newClass->wc = *class;
+
+ newClass->wc.lpszMenuName = 0;
+
+ /* Class name should also be set to zero. For now we need the
+ * name because we don't have atoms.
+ */
+ newClass->wc.lpszClassName = (char *)malloc(strlen(class->lpszClassName)+1);
+ strcpy( newClass->wc.lpszClassName, class->lpszClassName );
+
+ if (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra );
+
+ GlobalUnlock( handle );
+
+ firstClass = handle;
+ return handle; /* Should be an atom */
+}
+
+
+/***********************************************************************
+ * UnregisterClass (USER.403)
+ */
+BOOL UnregisterClass( LPSTR className, HANDLE instance )
+{
+ HANDLE class, next, prevClass;
+ CLASS * classPtr, * prevClassPtr;
+
+ /* Check if we can remove this class */
+ class = CLASS_FindClassByName( className, &classPtr );
+ if (!class) return FALSE;
+ if ((classPtr->wc.hInstance != instance) || (classPtr->cWindows > 0))
+ {
+ GlobalUnlock( class );
+ return FALSE;
+ }
+
+ /* Remove the class from the linked list */
+ if (firstClass == class) firstClass = classPtr->hNext;
+ else
+ {
+ prevClass = firstClass;
+ while (prevClass)
+ {
+ prevClassPtr = (CLASS *) GlobalLock(prevClass);
+ next == prevClassPtr->hNext;
+ if (next == class) break;
+ GlobalUnlock(prevClass);
+ prevClass = next;
+ }
+ if (!prevClass)
+ {
+ printf( "ERROR: Class list corrupted\n" );
+ return FALSE;
+ }
+ prevClassPtr->hNext = classPtr->hNext;
+ GlobalUnlock( prevClass );
+ }
+
+ GlobalUnlock( class );
+ GlobalFree( class );
+ return TRUE;
+}
diff --git a/class.h b/class.h
new file mode 100644
index 0000000..1e7fa2b
--- /dev/null
+++ b/class.h
@@ -0,0 +1,33 @@
+/*
+ * Window classes definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef CLASS_H
+#define CLASS_H
+
+#include "windows.h"
+
+#define CLASS_MAGIC 0x4b4e /* 'NK' */
+
+typedef struct tagCLASS
+{
+ HCLASS hNext; /* Next class */
+ WORD wMagic; /* Magic number (must be CLASS_MAGIC) */
+ ATOM atomName; /* Name of the class */
+ HANDLE hDCE; /* Class DC Entry (if CS_CLASSDC) */
+ WORD cWindows; /* Count of existing windows of this class */
+ WNDCLASS wc __attribute__ ((packed)); /* Class information */
+ WORD wExtra[1]; /* Class extra bytes */
+} CLASS;
+
+
+ /* The caller must GlobalUnlock the pointer returned
+ * by these functions (except when NULL).
+ */
+HCLASS CLASS_FindClassByName( char * name, CLASS **ptr );
+CLASS * CLASS_FindClassPtr( HCLASS hclass );
+
+
+#endif /* CLASS_H */
diff --git a/event.c b/event.c
new file mode 100644
index 0000000..6e65f29
--- /dev/null
+++ b/event.c
@@ -0,0 +1,188 @@
+/*
+ * X events handling functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+
+#include "windows.h"
+
+
+#define NB_BUTTONS 3 /* Windows can handle 3 buttons */
+#define DBLCLICK_TIME 300 /* Max. time for a double click (milliseconds) */
+
+
+ /* Event handlers */
+static void EVENT_expose();
+static void EVENT_key();
+static void EVENT_mouse_motion();
+static void EVENT_mouse_button();
+
+
+/***********************************************************************
+ * EVENT_AddHandlers
+ *
+ * Add the event handlers to the given window
+ */
+void EVENT_AddHandlers( Widget w, int hwnd )
+{
+ XtAddEventHandler(w, ExposureMask, FALSE,
+ EVENT_expose, (XtPointer)hwnd );
+ XtAddEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE,
+ EVENT_key, (XtPointer)hwnd );
+ XtAddEventHandler(w, PointerMotionMask, FALSE,
+ EVENT_mouse_motion, (XtPointer)hwnd );
+ XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
+ EVENT_mouse_button, (XtPointer)hwnd );
+}
+
+
+/***********************************************************************
+ * EVENT_RemoveHandlers
+ *
+ * Remove the event handlers of the given window
+ */
+void EVENT_RemoveHandlers( Widget w, int hwnd )
+{
+ XtRemoveEventHandler(w, ExposureMask, FALSE,
+ EVENT_expose, (XtPointer)hwnd );
+ XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE,
+ EVENT_key, (XtPointer)hwnd );
+ XtRemoveEventHandler(w, PointerMotionMask, FALSE,
+ EVENT_mouse_motion, (XtPointer)hwnd );
+ XtRemoveEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
+ EVENT_mouse_button, (XtPointer)hwnd );
+}
+
+
+/***********************************************************************
+ * EVENT_XStateToKeyState
+ *
+ * Translate a X event state (Button1Mask, ShiftMask, etc...) to
+ * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
+ */
+static WORD EVENT_XStateToKeyState( int state )
+{
+ int kstate = 0;
+
+ if (state & Button1Mask) kstate |= MK_LBUTTON;
+ if (state & Button2Mask) kstate |= MK_MBUTTON;
+ if (state & Button3Mask) kstate |= MK_RBUTTON;
+ if (state & ShiftMask) kstate |= MK_SHIFT;
+ if (state & ControlMask) kstate |= MK_CONTROL;
+ return kstate;
+}
+
+
+/***********************************************************************
+ * EVENT_expose
+ *
+ * Handle a X expose event
+ */
+static void EVENT_expose( Widget w, int hwnd, XEvent *event,
+ Boolean *cont_dispatch )
+{
+ MSG msg;
+ XExposeEvent * expEvt = (XExposeEvent *)expEvt;
+
+ msg.hwnd = hwnd;
+ msg.message = WM_PAINT;
+ msg.wParam = 0;
+ msg.lParam = 0;
+ msg.time = 0;
+ msg.pt.x = 0;
+ msg.pt.y = 0;
+
+ MSG_AddMsg( &msg, 0 );
+}
+
+
+/***********************************************************************
+ * EVENT_key
+ *
+ * Handle a X key event
+ */
+static void EVENT_key( Widget w, int hwnd, XKeyEvent *event,
+ Boolean *cont_dispatch )
+{
+ MSG msg;
+
+ msg.hwnd = hwnd;
+ msg.message = (event->type == KeyRelease) ? WM_KEYUP : WM_KEYDOWN;
+ msg.wParam = 0;
+ msg.lParam = (event->x & 0xffff) | (event->y << 16);
+ msg.time = event->time;
+ msg.pt.x = event->x & 0xffff;
+ msg.pt.y = event->y & 0xffff;
+
+ MSG_AddMsg( &msg );
+}
+
+
+/***********************************************************************
+ * EVENT_mouse_motion
+ *
+ * Handle a X mouse motion event
+ */
+static void EVENT_mouse_motion( Widget w, int hwnd, XMotionEvent *event,
+ Boolean *cont_dispatch )
+{
+ MSG msg;
+
+ msg.hwnd = hwnd;
+ msg.message = WM_MOUSEMOVE;
+ msg.wParam = EVENT_XStateToKeyState( event->state );
+ msg.lParam = (event->x & 0xffff) | (event->y << 16);
+ msg.time = event->time;
+ msg.pt.x = event->x & 0xffff;
+ msg.pt.y = event->y & 0xffff;
+
+ MSG_AddMsg( &msg );
+}
+
+
+/***********************************************************************
+ * EVENT_mouse_button
+ *
+ * Handle a X mouse button event
+ */
+static void EVENT_mouse_button( Widget w, int hwnd, XButtonEvent *event,
+ Boolean *cont_dispatch )
+{
+ static WORD messages[3][NB_BUTTONS] =
+ {
+ { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN },
+ { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP },
+ { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK }
+ };
+ static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
+
+ MSG msg;
+ int buttonNum, prevTime, type;
+
+ buttonNum = event->button-1;
+ if (buttonNum >= NB_BUTTONS) return;
+ if (event->type == ButtonRelease) type = 1;
+ else
+ { /* Check if double-click */
+ prevTime = lastClickTime[buttonNum];
+ lastClickTime[buttonNum] = event->time;
+ type = (event->time - prevTime < DBLCLICK_TIME) ? 2 : 0;
+ }
+
+ msg.hwnd = hwnd;
+ msg.message = messages[type][buttonNum];
+ msg.wParam = EVENT_XStateToKeyState( event->state );
+ msg.lParam = (event->x & 0xffff) | (event->y << 16);
+ msg.time = event->time;
+ msg.pt.x = event->x & 0xffff;
+ msg.pt.y = event->y & 0xffff;
+
+ MSG_AddMsg( &msg );
+}
+
diff --git a/global.c b/global.c
index 3ef21ee..0bef480 100644
--- a/global.c
+++ b/global.c
@@ -8,7 +8,9 @@
#include "segmem.h"
/*
- * Global memory pool descriptor.
+ * Global memory pool descriptor. Segments MUST be maintained in segment
+ * ascending order. If not the reallocation routine will die a horrible
+ * death.
*
* handle = 0, this descriptor contains the address of a free pool.
* != 0, this describes an allocated block.
@@ -30,15 +32,18 @@
short sequence;
void *addr;
int length;
+ int lock_count;
} GDESC;
GDESC *GlobalList = NULL;
+static unsigned short next_unused_handle = 1;
+
/**********************************************************************
- * GLOBAL_GetFreeSegments
+ * GlobalGetFreeSegments
*/
GDESC *
-GLOBAL_GetFreeSegments(unsigned int flags, int n_segments)
+GlobalGetFreeSegments(unsigned int flags, int n_segments)
{
struct segment_descriptor_s *s;
GDESC *g;
@@ -100,7 +105,11 @@
g->sequence = -1;
g->addr = s->base_addr;
g->length = s->length;
-
+ if (!(flags & GLOBAL_FLAGS_MOVEABLE))
+ g->lock_count = 1;
+ else
+ g->lock_count = 0;
+
free(s);
if (count == 0)
@@ -130,15 +139,14 @@
}
/**********************************************************************
- * GLOBAL_Alloc
+ * GlobalAlloc
*/
unsigned int
-GLOBAL_Alloc(unsigned int flags, unsigned long size)
+GlobalAlloc(unsigned int flags, unsigned long size)
{
GDESC *g;
GDESC *g_prev;
void *m;
- int i;
/*
* If this block is fixed or very big we need to allocate entire
@@ -148,7 +156,7 @@
{
int segments = (size >> 16) + 1;
- g = GLOBAL_GetFreeSegments(flags, segments);
+ g = GlobalGetFreeSegments(flags, segments);
if (g == NULL)
return 0;
else
@@ -176,9 +184,9 @@
* If we couldn't get the memory there, then we need to create
* a new free list.
*/
- if (m == NULL)
+ if (g == NULL)
{
- g = GLOBAL_GetFreeSegments(0, 1);
+ g = GlobalGetFreeSegments(0, 1);
if (g == NULL)
return 0;
@@ -186,52 +194,56 @@
g->sequence = 0;
HEAP_Init((MDESC **) g->addr, (MDESC **) g->addr + 1,
0x10000 - sizeof(MDESC **));
- m = HEAP_Alloc((MDESC **) g->addr, 0, size);
+ m = HEAP_Alloc((MDESC **) g->addr, flags & GLOBAL_FLAGS_ZEROINIT,
+ size);
if (m == NULL)
return 0;
}
/*
+ * Save position of heap descriptor.
+ */
+ g_prev = g;
+
+ /*
* We have a new block. Let's create a GDESC entry for it.
*/
- g_prev = NULL;
- i = 0;
- for (g = GlobalList; g != NULL; g = g->next, i++)
- g_prev = g;
-
g = malloc(sizeof(*g));
+#ifdef DEBUG_HEAP
+ printf("New GDESC %08x\n", g);
+#endif
if (g == NULL)
return 0;
- g->handle = i << 3;
+ g->handle = next_unused_handle;
g->sequence = 0;
g->addr = m;
g->length = size;
- g->next = NULL;
+ g->next = g_prev->next;
+ g->lock_count = 0;
- if (g_prev != NULL)
- {
- g_prev->next = g;
- g->prev = g_prev;
- }
- else
- {
- GlobalList = g;
- g->prev = NULL;
- }
+ g_prev->next = g;
+ g->prev = g_prev;
+
+ next_unused_handle++;
+ if ((next_unused_handle & 7) == 7)
+ next_unused_handle++;
+#ifdef DEBUG_HEAP
+ printf("GlobalAlloc: returning %04x\n", g->handle);
+#endif
return g->handle;
}
}
/**********************************************************************
- * GLOBAL_Free
+ * GlobalFree
*
* Windows programs will pass a handle in the "block" parameter, but
* this function will also accept a 32-bit address.
*/
unsigned int
-GLOBAL_Free(unsigned int block)
+GlobalFree(unsigned int block)
{
GDESC *g;
@@ -264,10 +276,7 @@
{
HEAP_Free((MDESC **) (block & 0xffff0000), (void *) block);
- if (g->prev != NULL)
- g->prev->next = g->next;
- else
- GlobalList = g->next;
+ g->prev->next = g->next;
if (g->next != NULL)
g->next->prev = g->prev;
@@ -282,8 +291,8 @@
{
int i, limit;
- g->length;
- for (i = 0; i < limit; i++)
+ limit = g->length;
+ for (i = g->sequence - 1; i < limit && g != NULL; i++, g = g->next)
{
g->sequence = -1;
g->length = 0x10000;
@@ -294,11 +303,11 @@
}
/**********************************************************************
- * GLOBAL_Lock
+ * GlobalLock
*
*/
void *
-GLOBAL_Lock(unsigned int block)
+GlobalLock(unsigned int block)
{
GDESC *g;
@@ -309,8 +318,362 @@
* Find GDESC for this block.
*/
for (g = GlobalList; g != NULL; g = g->next)
+ {
if (g->handle == block)
+ {
+ g->lock_count++;
+#ifdef DEBUG_HEAP
+ printf("GlobalLock: returning %08x\n", g->addr);
+#endif
return g->addr;
+ }
+ }
+#ifdef DEBUG_HEAP
+ printf("GlobalLock: returning %08x\n", 0);
+#endif
return NULL;
}
+
+/**********************************************************************
+ * GlobalUnlock
+ *
+ */
+int
+GlobalUnlock(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block && g->lock_count > 0)
+ {
+ g->lock_count--;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**********************************************************************
+ * GlobalFlags
+ *
+ */
+unsigned int
+GlobalFlags(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ return g->lock_count;
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalSize
+ *
+ */
+unsigned int
+GlobalSize(unsigned int block)
+{
+ GDESC *g;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ return g->length;
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalHandle
+ *
+ * This routine is not strictly correct. MS Windows creates a selector
+ * for every locked global block. We do not. If the allocation is small
+ * enough, we only give out a little piece of a selector. Thus this
+ * function cannot be implemented.
+ */
+unsigned int
+GlobalHandle(unsigned int selector)
+{
+ GDESC *g;
+
+ if (selector == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == selector)
+ {
+ if (g->sequence > 0)
+ return g->handle;
+ else
+ {
+ fprintf(stderr, "Attempt to get a handle "
+ "from a selector to a far heap.\n");
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ * GlobalCompact
+ *
+ */
+unsigned int
+GlobalCompact(unsigned int desired)
+{
+ GDESC *g;
+ unsigned char free_map[512];
+ unsigned int max_selector_used = 0;
+ unsigned int i;
+ unsigned int selector;
+ int current_free;
+ int max_free;
+
+ /*
+ * Initialize free list to all items not controlled by GlobalAlloc()
+ */
+ for (i = 0; i < 512; i++)
+ free_map[i] = -1;
+
+ /*
+ * Traverse table looking for used and free selectors.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ /*
+ * Check for free segments.
+ */
+ if (g->sequence == -1)
+ {
+ free_map[g->handle >> 3] = 1;
+ if (g->handle > max_selector_used)
+ max_selector_used = g->handle;
+ }
+
+ /*
+ * Check for heap allocated segments.
+ */
+ else if (g->handle == 0)
+ {
+ selector = (unsigned int) g->addr >> 16;
+ free_map[selector >> 3] = 0;
+ if (selector > max_selector_used)
+ max_selector_used = selector;
+ }
+ }
+
+ /*
+ * All segments past the biggest selector used are free.
+ */
+ for (i = (max_selector_used >> 3) + 1; i < 512; i++)
+ free_map[i] = 1;
+
+ /*
+ * Find the largest free block of segments
+ */
+ current_free = 0;
+ max_free = 0;
+ for (i = 0; i < 512; i++)
+ {
+ if (free_map[i] == 1)
+ {
+ current_free++;
+ }
+ else
+ {
+ if (current_free > max_free)
+ max_free = current_free;
+ current_free = 0;
+ }
+ }
+
+ return max_free << 16;
+}
+
+/**********************************************************************
+ * GlobalReAlloc
+ *
+ */
+unsigned int
+GlobalReAlloc(unsigned int block, unsigned int new_size, unsigned int flags)
+{
+ GDESC *g;
+ unsigned int n_segments;
+ int i;
+
+ if (block == 0)
+ return 0;
+
+ /*
+ * Find GDESC for this block.
+ */
+ for (g = GlobalList; g != NULL; g = g->next)
+ {
+ if (g->handle == block)
+ break;
+ }
+
+ if (g == NULL)
+ return 0;
+
+ /*
+ * If this is a heap allocated block, then use HEAP_ReAlloc() to
+ * reallocate the block. If this fails, call GlobalAlloc() to get
+ * a new block.
+ */
+ if (g->sequence = 0)
+ {
+ MDESC **free_list;
+ void *p;
+
+ free_list = (MDESC **) ((unsigned int) g->addr & 0xffff0000);
+ p = HEAP_ReAlloc(free_list, g->addr, new_size, flags) ;
+ if (p == NULL)
+ {
+ unsigned int handle = GlobalAlloc(flags, new_size);
+ if (handle == 0)
+ return 0;
+ p = GlobalLock(handle);
+ memcpy(p, g->addr, g->length);
+ GlobalUnlock(handle);
+ GlobalFree(g->handle);
+
+ return handle;
+ }
+ else
+ {
+ g->addr = p;
+ g->length = new_size;
+ return g->handle;
+ }
+ }
+
+ /*
+ * Otherwise, we need to do the work ourselves. First verify the
+ * handle.
+ */
+ else
+ {
+ if (g->sequence != 1)
+ return 0;
+
+ /*
+ * Do we need more memory? Segments are in ascending order in
+ * the GDESC list.
+ */
+ n_segments = (new_size >> 16) + 1;
+ if (n_segments > g->length)
+ {
+ GDESC *g_new;
+ GDESC *g_start = g;
+ int old_segments = g_start->length;
+ unsigned short next_handle = g_start->handle;
+
+ for (i = 1; i <= n_segments; i++, g = g->next)
+ {
+ /*
+ * If we run into a block allocated to something else,
+ * try GlobalGetFreeSegments() and memcpy(). (Yuk!)
+ */
+ if (g->sequence != i || g->handle != next_handle)
+ {
+ g = GlobalGetFreeSegments(flags, n_segments);
+ if (g == NULL)
+ return 0;
+
+ memcpy(g->addr, g_start->addr,
+ g_start->length << 16);
+
+ GlobalFree(block);
+ return g->handle;
+ }
+
+ /*
+ * Otherwise this block is used by us or free. So,
+ * snatch it. If this block is new and we are supposed to
+ * zero init, then do some erasing.
+ */
+ if (g->sequence == -1 && (flags & GLOBAL_FLAGS_ZEROINIT))
+ memset(g->addr, 0, 0x10000);
+
+ g->sequence = i;
+ g->length = n_segments;
+ next_handle += 8;
+
+ /*
+ * If the next descriptor is non-existant, then use
+ * GlobalGetFreeSegments to create them.
+ */
+ if (i != n_segments && g->next == NULL)
+ {
+ g_new = GlobalGetFreeSegments(flags, n_segments - i);
+ if (g_new == NULL)
+ return 0;
+ GlobalFree(g_new->handle);
+ }
+ }
+
+ return g_start->handle;
+ }
+
+ /*
+ * Do we need less memory?
+ */
+ else if (n_segments < g->length)
+ {
+ GDESC *g_free;
+
+ g_free = g;
+ for (i = 0; i < n_segments; i++)
+ {
+ if (g_free->sequence != i + 1)
+ return 0;
+ g_free = g_free->next;
+ }
+ }
+
+ /*
+ * We already have exactly the right amount of memory.
+ */
+ else
+ return block;
+ }
+
+ /*
+ * If we fall through it must be an error.
+ */
+ return 0;
+}
diff --git a/heap.c b/heap.c
index fa06124..e2aed78 100644
--- a/heap.c
+++ b/heap.c
@@ -61,6 +61,11 @@
m->prev = m;
m->next = m;
+ if (flags & GLOBAL_FLAGS_ZEROINIT)
+ memset(m + 1, 0, bytes);
+#ifdef DEBUG_HEAP
+ printf("HeapAlloc: returning %08x\n", (m + 1));
+#endif
return (void *) (m + 1);
}
}
@@ -77,12 +82,31 @@
m->prev = m;
m->next = m;
+ if (flags & GLOBAL_FLAGS_ZEROINIT)
+ memset(m + 1, 0, bytes);
+#ifdef DEBUG_HEAP
+ printf("HeapAlloc: returning %08x\n", (m + 1));
+#endif
return (void *) (m + 1);
}
+#ifdef DEBUG_HEAP
+ printf("HeapAlloc: returning %08x\n", 0);
+#endif
+ return 0;
+}
+
+/**********************************************************************
+ * HEAP_ReAlloc
+ */
+void *
+HEAP_ReAlloc(MDESC **free_list, void *old_block,
+ int new_size, unsigned int flags)
+{
return 0;
}
+
/**********************************************************************
* HEAP_Free
*/
@@ -209,3 +233,20 @@
#endif
return m;
}
+
+/**********************************************************************
+ * HEAP_LocalCompact
+ */
+int
+HEAP_LocalCompact(int min_free)
+{
+ MDESC *m;
+ int max_block;
+
+ max_block = 0;
+ for (m = LOCAL_FreeList; m != NULL; m = m->next)
+ if (m->length > max_block)
+ max_block = m->length;
+
+ return max_block;
+}
diff --git a/heap.h b/heap.h
index 2d8bfa8..d602d84 100644
--- a/heap.h
+++ b/heap.h
@@ -15,5 +15,7 @@
extern void HEAP_Init(MDESC **free_list, void *start, int length);
extern void *HEAP_Alloc(MDESC **free_list, int flags, int bytes);
extern void HEAP_Free(MDESC **free_list, void *block);
+extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block,
+ int new_size, unsigned int flags);
#endif /* HEAP_H */
diff --git a/kernel.c b/kernel.c
index 24b0e90..13f30c7 100644
--- a/kernel.c
+++ b/kernel.c
@@ -8,17 +8,6 @@
extern unsigned short *Stack16Frame;
/**********************************************************************
- * KERNEL_GetVersion
- *
- * Return the version of Windows that we emulate.
- */
-int
-KERNEL_GetVersion(void)
-{
- return 0x0301;
-}
-
-/**********************************************************************
* KERNEL_LockSegment
*/
int
diff --git a/kernel.spec b/kernel.spec
index 1942b75..382630c 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -6,11 +6,17 @@
3 return GetVersion 0 0x301
5 pascal LocalAlloc(word word) HEAP_LocalAlloc(1 2)
-15 pascal GlobalAlloc(word long) GLOBAL_Alloc(1 2)
-17 pascal GlobalFree(word) GLOBAL_Free(1)
-18 pascal GLobalLock(word) GLOBAL_Lock(1)
+15 pascal GlobalAlloc(word long) GlobalAlloc(1 2)
+16 pascal GlobalReAlloc(word long word) GlobalReAlloc(1 2 3)
+17 pascal GlobalFree(word) GlobalFree(1)
+18 pascal GlobalLock(word) GlobalLock(1)
+19 pascal GlobalUnlock(word) GlobalUnlock(1)
+20 pascal GlobalSize(word) GlobalSize(1)
+21 pascal GlobalHandle(word) GlobalHandle(1)
+22 pascal GlobalFlags(word) GlobalFlags(1)
23 pascal LockSegment(s_word) KERNEL_LockSegment(1)
24 pascal UnlockSegment(s_word) KERNEL_UnlockSegment(1)
+25 pascal GlobalCompact(long) GlobalCompact(1)
30 pascal WaitEvent(word) KERNEL_WaitEvent(1)
49 pascal GetModuleFileName(word ptr s_word) KERNEL_GetModuleFileName(1 2 3)
51 pascal MakeProcInstance(ptr word) CALLBACK_MakeProcInstance(1 2)
@@ -18,6 +24,17 @@
102 register DOS3Call(word word word word word
word word word word word)
KERNEL_DOS3Call(1 2 3 4 5 6 7 8 9 10)
+111 pascal GlobalWire(word) GlobalLock(1)
+112 pascal GlobalUnWire(word) GlobalUnlock(1)
131 pascal GetDOSEnvironment() GetDOSEnvironment()
132 return GetWinFlags 0 0x413
+154 return GlobalNotify 4 0
+163 pascal GlobalLRUOldest(word) ReturnArg(1)
+164 pascal GlobalLRUNewest(word) ReturnArg(1)
178 equate __WINFLAGS 0x413
+184 return GlobalDOSAlloc 4 0
+185 return GlobalDOSFree 2 0
+191 pascal GlobalPageLock(word) GlobalLock(1)
+192 pascal GlobalPageUnlock(word) GlobalUnlock(1)
+197 pascal GlobalFix(word) GlobalLock(1)
+198 pascal GlobalUnfix(word) GlobalUnlock(1)
diff --git a/ldt512.tar b/ldt512.tar
new file mode 100644
index 0000000..978751c
--- /dev/null
+++ b/ldt512.tar
Binary files differ
diff --git a/message.c b/message.c
new file mode 100644
index 0000000..d013d1d
--- /dev/null
+++ b/message.c
@@ -0,0 +1,428 @@
+/*
+ * Message queues related functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+/*
+ * This code assumes that there is only one Windows task (hence
+ * one message queue).
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <sys/param.h>
+#include <sys/times.h>
+
+#include "message.h"
+#include "win.h"
+
+
+#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
+
+
+static MESSAGEQUEUE * msgQueue = NULL;
+
+
+/***********************************************************************
+ * MSG_GetMessageType
+ *
+ */
+int MSG_GetMessageType( int msg )
+{
+ if ((msg >= WM_KEYFIRST) && (msg <= WM_KEYLAST)) return QS_KEY;
+ else if ((msg >= WM_MOUSEFIRST) && (msg <= WM_MOUSELAST))
+ {
+ if (msg == WM_MOUSEMOVE) return QS_MOUSEMOVE;
+ else return QS_MOUSEBUTTON;
+ }
+ else if (msg == WM_PAINT) return QS_PAINT;
+ else if (msg == WM_TIMER) return QS_TIMER;
+ return QS_POSTMESSAGE;
+}
+
+
+/***********************************************************************
+ * MSG_AddMsg
+ *
+ * Add a message to the queue. Return FALSE if queue is full.
+ */
+int MSG_AddMsg( MSG * msg, DWORD extraInfo )
+{
+ int pos, type;
+ QMSG * qmsg;
+
+ if (!msgQueue) return FALSE;
+ pos = msgQueue->nextFreeMessage;
+
+ /* No need to store WM_PAINT messages */
+ if (msg->message == WM_PAINT)
+ {
+ msgQueue->status |= QS_PAINT;
+ msgQueue->tempStatus |= QS_PAINT;
+ /* For now we need to store them to keep the hwnd somewhere */
+ /* return TRUE; */
+ }
+
+ /* Check if queue is full */
+ if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
+ return FALSE;
+
+ /* Store message */
+ msgQueue->messages[pos].msg = *msg;
+ msgQueue->messages[pos].extraInfo = extraInfo;
+
+ /* Store message type */
+ type = MSG_GetMessageType( msg->message );
+ msgQueue->status |= type;
+ msgQueue->tempStatus |= type;
+
+ if (pos < msgQueue->queueSize-1) pos++;
+ else pos = 0;
+ msgQueue->nextFreeMessage = pos;
+ msgQueue->msgCount++;
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * MSG_FindMsg
+ *
+ * Find a message matching the given parameters. Return -1 if none available.
+ */
+int MSG_FindMsg( HWND hwnd, int first, int last )
+{
+ int i, pos = msgQueue->nextMessage;
+
+ if (!msgQueue->msgCount) return -1;
+ if (!hwnd && !first && !last) return pos;
+
+ for (i = 0; i < msgQueue->msgCount; i++)
+ {
+ MSG * msg = &msgQueue->messages[pos].msg;
+
+ if (!hwnd || (msg->hwnd == hwnd))
+ {
+ if (!first && !last) return pos;
+ if ((msg->message >= first) && (msg->message <= last)) return pos;
+ }
+ if (pos < msgQueue->queueSize-1) pos++;
+ else pos = 0;
+ }
+ return -1;
+}
+
+
+/***********************************************************************
+ * MSG_RemoveMsg
+ *
+ * Remove a message from the queue (pos must be a valid position).
+ */
+void MSG_RemoveMsg( int pos )
+{
+ int oldpos, i, type;
+ QMSG * qmsg;
+
+ if (!msgQueue) return;
+ qmsg = &msgQueue->messages[pos];
+
+ if (pos >= msgQueue->nextMessage)
+ {
+ int count = pos - msgQueue->nextMessage;
+ if (count) memmove( &msgQueue->messages[msgQueue->nextMessage+1],
+ &msgQueue->messages[msgQueue->nextMessage],
+ count * sizeof(QMSG) );
+ msgQueue->nextMessage++;
+ if (msgQueue->nextMessage >= msgQueue->queueSize)
+ msgQueue->nextMessage = 0;
+ }
+ else
+ {
+ int count = msgQueue->nextFreeMessage - pos;
+ if (count) memmove( &msgQueue->messages[pos],
+ &msgQueue->messages[pos+1], count * sizeof(QMSG) );
+ if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
+ else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
+ }
+ msgQueue->msgCount--;
+
+ /* Recalc status */
+ type = 0;
+ pos = msgQueue->nextMessage;
+ for (i = 0; i < msgQueue->msgCount; i++)
+ {
+ type |= MSG_GetMessageType( msgQueue->messages[pos].msg.message );
+ if (++pos >= msgQueue->queueSize-1) pos = 0;
+ }
+ msgQueue->status = msgQueue->status & (QS_PAINT | QS_SENDMESSAGE) | type;
+ msgQueue->tempStatus = 0;
+}
+
+
+/***********************************************************************
+ * MSG_EndPaint
+ *
+ * Remove the WM_PAINT message from the queue
+ */
+void MSG_EndPaint()
+{
+ msgQueue->status &= ~QS_PAINT;
+}
+
+
+/***********************************************************************
+ * MSG_GetTime
+ *
+ * Return the time elapsed from the starting of the system, in milliseconds.
+ * Used to timestamp messages.
+ */
+
+LONG MSG_GetTime()
+{
+ struct tms dummy;
+ return times(&dummy) / (1000 / HZ);
+}
+
+
+/***********************************************************************
+ * SetMessageQueue (USER.266)
+ */
+BOOL SetMessageQueue( int size )
+{
+ int queueSize;
+
+ /* Free the old message queue */
+ if (msgQueue) free(msgQueue);
+
+ if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
+
+ queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
+ msgQueue = (MESSAGEQUEUE *) malloc(queueSize);
+ if (!msgQueue) return FALSE;
+
+ msgQueue->next = 0;
+ msgQueue->hTask = 0;
+ msgQueue->msgSize = sizeof(QMSG);
+ msgQueue->msgCount = 0;
+ msgQueue->nextMessage = 0;
+ msgQueue->nextFreeMessage = 0;
+ msgQueue->queueSize = size;
+ msgQueue->GetMessageTimeVal = 0;
+ msgQueue->GetMessagePosVal = 0;
+ msgQueue->GetMessageExtraInfoVal = 0;
+ msgQueue->lParam = 0;
+ msgQueue->wParam = 0;
+ msgQueue->msg = 0;
+ msgQueue->hWnd = 0;
+ msgQueue->wPostQMsg = 0;
+ msgQueue->wExitCode = 0;
+ msgQueue->InSendMessageHandle = 0;
+ msgQueue->tempStatus = 0;
+ msgQueue->status = 0;
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * PostQuitMessage (USER.6)
+ */
+void PostQuitMessage( int exitCode )
+{
+ if (!msgQueue) return;
+ msgQueue->wPostQMsg = TRUE;
+ msgQueue->wExitCode = exitCode;
+}
+
+
+/***********************************************************************
+ * GetQueueStatus (USER.334)
+ */
+DWORD GetQueueStatus( int flags )
+{
+ unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
+ msgQueue->tempStatus = 0;
+ return ret & ((flags << 16) | flags);
+}
+
+
+/***********************************************************************
+ * GetInputState (USER.335)
+ */
+BOOL GetInputState()
+{
+ return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
+}
+
+
+/***********************************************************************
+ * PeekMessage (USER.109)
+ */
+BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
+{
+ int pos;
+
+ /* First handle a WM_QUIT message */
+ if (msgQueue->wPostQMsg)
+ {
+ msg->hwnd = hwnd;
+ msg->message = WM_QUIT;
+ msg->wParam = msgQueue->wExitCode;
+ msg->lParam = 0;
+ return TRUE;
+ }
+
+ /* Then handle a message put by SendMessage() */
+ if (msgQueue->status & QS_SENDMESSAGE)
+ {
+ if (!hwnd || (msgQueue->hWnd == hwnd))
+ {
+ if ((!first && !last) ||
+ ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
+ {
+ msg->hwnd = msgQueue->hWnd;
+ msg->message = msgQueue->msg;
+ msg->wParam = msgQueue->wParam;
+ msg->lParam = msgQueue->lParam;
+ if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
+ return TRUE;
+ }
+ }
+
+ }
+
+ /* Now find a normal message */
+ pos = MSG_FindMsg( hwnd, first, last );
+ if (pos != -1)
+ {
+ QMSG *qmsg = &msgQueue->messages[pos];
+ *msg = qmsg->msg;
+ msgQueue->GetMessageTimeVal = msg->time;
+ msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
+ msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+
+ if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
+ return TRUE;
+ }
+
+ /* If nothing else, return a WM_PAINT message */
+ if (msgQueue->status & QS_PAINT)
+ {
+ if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
+ {
+ msg->hwnd = hwnd;
+ msg->message = WM_PAINT;
+ msg->wParam = 0;
+ msg->lParam = 0;
+ return TRUE;
+ }
+
+ }
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * PostMessage (USER.110)
+ */
+BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+{
+ MSG msg;
+
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.time = MSG_GetTime();
+ msg.pt.x = 0;
+ msg.pt.y = 0;
+
+ return MSG_AddMsg( &msg, 0 );
+}
+
+
+/***********************************************************************
+ * SendMessage (USER.111)
+ */
+LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+ LONG retval = 0;
+ WND * wndPtr = WIN_FindWndPtr( hwnd );
+ if (wndPtr)
+ {
+ retval = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg,
+ wParam, lParam );
+ GlobalUnlock( hwnd );
+ }
+ return retval;
+}
+
+
+/***********************************************************************
+ * TranslateMessage (USER.113)
+ */
+BOOL TranslateMessage( LPMSG msg )
+{
+ int message = msg->message;
+
+ if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
+ (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
+ {
+#ifdef DEBUG_MSG
+ printf( "Translating key message\n" );
+#endif
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * DispatchMessage (USER.114)
+ */
+LONG DispatchMessage( LPMSG msg )
+{
+ LONG retval = 0;
+ WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
+
+#ifdef DEBUG_MSG
+ printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
+ msg->hwnd, msg->message, msg->wParam, msg->lParam,
+ msg->time, msg->pt.x, msg->pt.y );
+#endif
+ if (wndPtr)
+ {
+ retval = CallWindowProc(wndPtr->lpfnWndProc, msg->hwnd, msg->message,
+ msg->wParam, msg->lParam );
+ GlobalUnlock( msg->hwnd );
+ }
+ return retval;
+}
+
+
+/***********************************************************************
+ * GetMessagePos (USER.119)
+ */
+DWORD GetMessagePos(void)
+{
+ return msgQueue->GetMessagePosVal;
+}
+
+
+/***********************************************************************
+ * GetMessageTime (USER.120)
+ */
+LONG GetMessageTime(void)
+{
+ return msgQueue->GetMessageTimeVal;
+}
+
+/***********************************************************************
+ * GetMessageExtraInfo (USER.288)
+ */
+LONG GetMessageExtraInfo(void)
+{
+ return msgQueue->GetMessageExtraInfoVal;
+}
+
diff --git a/message.h b/message.h
new file mode 100644
index 0000000..0bbfc9a
--- /dev/null
+++ b/message.h
@@ -0,0 +1,44 @@
+/*
+ * Message queues definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+#include "windows.h"
+
+ /* Message as stored in the queue (contains the extraInfo field) */
+typedef struct tagQMSG
+{
+ MSG msg;
+ DWORD extraInfo __attribute__ ((packed)); /* Only in 3.1 */
+} QMSG;
+
+
+typedef struct tagMESSAGEQUEUE
+{
+ WORD next;
+ WORD hTask; /* hTask owning the queue */
+ WORD msgSize; /* Size of messages in the queue */
+ WORD msgCount; /* Number of waiting messages */
+ WORD nextMessage; /* Next message to be retrieved */
+ WORD nextFreeMessage; /* Next available slot in the queue */
+ WORD queueSize; /* Size of the queue */
+ DWORD GetMessageTimeVal; /* Value returned by GetMessageTime */
+ DWORD GetMessagePosVal; /* Value returned by GetMessagePos */
+ WORD GetMessageExtraInfoVal; /* Value returned by GetMessageExtraInfo */
+ DWORD lParam; /* Next four values set by SetMessage */
+ WORD wParam;
+ WORD msg;
+ WORD hWnd;
+ WORD wPostQMsg; /* PostQuitMessage flag */
+ WORD wExitCode; /* PostQuitMessage exit code */
+ WORD InSendMessageHandle; /* Handle of task that sent a message */
+ WORD tempStatus; /* State reset by GetQueueStatus */
+ WORD status; /* Queue state */
+ QMSG messages[1]; /* Queue messages */
+} MESSAGEQUEUE;
+
+#endif /* MESSAGE_H */
diff --git a/prototypes.h b/prototypes.h
index c030971..39560dd 100644
--- a/prototypes.h
+++ b/prototypes.h
@@ -27,10 +27,6 @@
extern struct segment_descriptor_s *GetNextSegment(unsigned int flags,
unsigned int limit);
-extern unsigned int GLOBAL_Alloc(unsigned int flags, unsigned long size);
-extern unsigned int GLOBAL_Free(unsigned int block);
-extern void *GLOBAL_Lock(unsigned int block);
-
extern struct mz_header_s *CurrentMZHeader;
extern struct ne_header_s *CurrentNEHeader;
extern int CurrentNEFile;
diff --git a/relay.c b/relay.c
index a86b92c..2331947 100644
--- a/relay.c
+++ b/relay.c
@@ -200,3 +200,11 @@
return 0;
}
+/**********************************************************************
+ * ReturnArg
+ */
+int
+ReturnArg(int arg)
+{
+ return arg;
+}
diff --git a/resource.c b/resource.c
index 93895e1..531f9c0 100644
--- a/resource.c
+++ b/resource.c
@@ -40,9 +40,13 @@
int n_colors;
n_colors = 1 << image->bcBitCount;
- handle = GLOBAL_Alloc(GMEM_MOVEABLE,
+ handle = GlobalAlloc(GMEM_MOVEABLE,
image_size + sizeof(*new_image) + n_colors);
- new_image = GLOBAL_Lock(handle);
+ new_image = GlobalLock(handle);
+#ifdef DEBUG_RESOURCE
+ printf("ConvertCoreBitmap: handle = %04x, new image = %08x\n",
+ handle, new_image);
+#endif
if (new_image == NULL)
return NULL;
@@ -96,6 +100,11 @@
void *
ConvertInfoBitmap(BITMAPINFOHEADER *image, int image_size)
{
+#ifdef DEBUG_RESOURCE
+ printf("ConvertInfoBitmap: \n");
+#endif
+
+ return NULL;
}
/**********************************************************************
@@ -142,6 +151,9 @@
r->resource_type = type;
r->resource_data = data;
+#ifdef DEBUG_RESOURCE
+ printf("AddResource: return handle %d\n", i + 1);
+#endif
/*
* Return a unique handle.
*/
@@ -325,6 +337,9 @@
free(image);
+#ifdef DEBUG_RESOURCE
+ printf("LoadResource: rsc_image = %08x\n", rsc_image);
+#endif
/*
* Add to resource list.
*/
diff --git a/tclIndex b/tclIndex
deleted file mode 100644
index 045f146..0000000
--- a/tclIndex
+++ /dev/null
@@ -1,12 +0,0 @@
-# Tcl autoload index file: each line identifies a Tcl
-# procedure and the file where that procedure is
-# defined. Generated by the "auto_mkindex" command.
-
-CreateWindow Windows.tcl
-CreateMenuBar Windows.tcl
-AppendMenu Windows.tcl
-# Unimplemented stuff
-LoadIcon Windows.tcl
-LoadCursor Windows.tcl
-GetStockObject Windows.tcl
-DefWindowProc Windows.tcl
diff --git a/tkInt.h b/tkInt.h
deleted file mode 100644
index 728847c..0000000
--- a/tkInt.h
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * tkInt.h --
- *
- * Declarations for things used internally by the Tk
- * procedures but not exported outside the module.
- *
- * Copyright 1990-1992 Regents of the University of California.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- * $Header: /user6/ouster/wish/RCS/tkInt.h,v 1.84 93/01/23 16:59:14 ouster Exp $ SPRITE (Berkeley)
- */
-
-#ifndef _TKINT
-#define _TKINT
-
-#ifndef _XLIB_H_
-#include <X11/Xlib.h>
-#endif
-#ifndef _XUTIL_H
-#include <X11/Xutil.h>
-#endif
-#ifndef _TK
-#include "tk.h"
-#endif
-#ifndef _TCL
-#include "tcl.h"
-#endif
-#ifndef _TCLHASH
-#include "tclHash.h"
-#endif
-
-/*
- * Opaque type declarations:
- */
-
-typedef struct Tk_PostscriptInfo Tk_PostscriptInfo;
-typedef struct TkGrabEvent TkGrabEvent;
-
-/*
- * One of the following structures is maintained for each display
- * containing a window managed by Tk:
- */
-
-typedef struct TkDisplay {
- Display *display; /* Xlib's info about display. */
- struct TkDisplay *nextPtr; /* Next in list of all displays. */
- char *name; /* Name of display (with any screen
- * identifier removed). Malloc-ed. */
- Time lastEventTime; /* Time of last event received for this
- * display. */
-
- /*
- * Information used by tkFocus.c and tkEvent.c:
- */
-
- struct TkWindow *focusTopLevelPtr;
- /* Pointer to the top-level window that
- * currently contains the focus for this
- * display. NULL means none of the
- * top-levels managed by this application
- * contains the focus. */
- int focussedOnEnter; /* Non-zero means the focus was set
- * implicitly from an Enter event rather
- * than from a FocusIn event. */
-
- /*
- * Information used primarily by tkBind.c:
- */
-
- int bindInfoStale; /* Non-zero means the variables in this
- * part of the structure are potentially
- * incorrect and should be recomputed. */
- unsigned int modeModMask; /* Has one bit set to indicate the modifier
- * corresponding to "mode shift". If no
- * such modifier, than this is zero. */
- enum {IGNORE, CAPS, SHIFT} lockUsage;
- /* Indicates how to interpret lock modifier. */
-
- /*
- * Information used by tkError.c only:
- */
-
- struct TkErrorHandler *errorPtr;
- /* First in list of error handlers
- * for this display. NULL means
- * no handlers exist at present. */
- int deleteCount; /* Counts # of handlers deleted since
- * last time inactive handlers were
- * garbage-collected. When this number
- * gets big, handlers get cleaned up. */
-
- /*
- * Information used by tkSend.c only:
- */
-
- Tk_Window commWindow; /* Window used for communication
- * between interpreters during "send"
- * commands. NULL means send info hasn't
- * been initialized yet. */
- Atom commProperty; /* X's name for comm property. */
- Atom registryProperty; /* X's name for property containing
- * registry of interpreter names. */
-
- /*
- * Information used by tkSelect.c only:
- */
-
- Tk_Window selectionOwner; /* Current owner of selection, or
- * NULL if selection isn't owned by
- * a window in this process. */
- int selectionSerial; /* Serial number of last XSelectionSetOwner
- * request we made to server (used to
- * filter out redundant SelectionClear
- * events. */
- Time selectionTime; /* Timestamp used to acquire selection. */
- Atom multipleAtom; /* Atom for MULTIPLE. None means
- * selection stuff isn't initialized. */
- Atom incrAtom; /* Atom for INCR. */
- Atom targetsAtom; /* Atom for TARGETS. */
- Atom timestampAtom; /* Atom for TIMESTAMP. */
- Atom textAtom; /* Atom for TEXT. */
- Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */
- Atom applicationAtom; /* Atom for APPLICATION. */
- Atom windowNameAtom; /* Atom for WINDOW_NAME. */
-
- /*
- * Information used by tkAtom.c only:
- */
-
- int atomInit; /* 0 means stuff below hasn't been
- * initialized yet. */
- Tcl_HashTable nameTable; /* Maps from names to Atom's. */
- Tcl_HashTable atomTable; /* Maps from Atom's back to names. */
-
- /*
- * Information used by tkCursor.c only:
- */
-
- Font cursorFont; /* Font to use for standard cursors.
- * None means font not loaded yet. */
-
- /*
- * Information used by tkGrab.c only:
- */
-
- struct TkWindow *grabWinPtr;
- /* Window in which the pointer is currently
- * grabbed, or NULL if none. */
- struct TkWindow *eventualGrabWinPtr;
- /* Value that grabWinPtr will have once the
- * grab event queue (below) has been
- * completely emptied. */
- struct TkWindow *buttonWinPtr;
- /* Window in which first mouse button was
- * pressed while grab was in effect, or NULL
- * if no such press in effect. */
- struct TkWindow *serverWinPtr;
- /* If no application contains the pointer then
- * this is NULL. Otherwise it contains the
- * last window for which we've gotten an
- * Enter or Leave event from the server (i.e.
- * the last window known to have contained
- * the pointer). Doesn't reflect events
- * that were synthesized in tkGrab.c. */
- TkGrabEvent *firstGrabEventPtr;
- /* First in list of enter/leave events
- * synthesized by grab code. These events
- * must be processed in order before any other
- * events are processed. NULL means no such
- * events. */
- TkGrabEvent *lastGrabEventPtr;
- /* Last in list of synthesized events, or NULL
- * if list is empty. */
- int grabFlags; /* Miscellaneous flag values. See definitions
- * in tkGrab.c. */
-
- /*
- * Miscellaneous information:
- */
-
- Tk_ColorModel *colorModels; /* Array of color models, one per screen;
- * indicates whether windows should attempt
- * to use full color for display, just mono,
- * etc. Malloc'ed. */
-} TkDisplay;
-
-/*
- * One of the following structures exists for each error handler
- * created by a call to Tk_CreateErrorHandler. The structure
- * is managed by tkError.c.
- */
-
-typedef struct TkErrorHandler {
- TkDisplay *dispPtr; /* Display to which handler applies. */
- unsigned long firstRequest; /* Only errors with serial numbers
- * >= to this are considered. */
- unsigned long lastRequest; /* Only errors with serial numbers
- * <= to this are considered. This
- * field is filled in when XUnhandle
- * is called. -1 means XUnhandle
- * hasn't been called yet. */
- int error; /* Consider only errors with this
- * error_code (-1 means consider
- * all errors). */
- int request; /* Consider only errors with this
- * major request code (-1 means
- * consider all major codes). */
- int minorCode; /* Consider only errors with this
- * minor request code (-1 means
- * consider all minor codes). */
- Tk_ErrorProc *errorProc; /* Procedure to invoke when a matching
- * error occurs. NULL means just ignore
- * errors. */
- ClientData clientData; /* Arbitrary value to pass to
- * errorProc. */
- struct TkErrorHandler *nextPtr;
- /* Pointer to next older handler for
- * this display, or NULL for end of
- * list. */
-} TkErrorHandler;
-
-/*
- * One of the following structures exists for each event handler
- * created by calling Tk_CreateEventHandler. This information
- * is used by tkEvent.c only.
- */
-
-typedef struct TkEventHandler {
- unsigned long mask; /* Events for which to invoke
- * proc. */
- Tk_EventProc *proc; /* Procedure to invoke when an event
- * in mask occurs. */
- ClientData clientData; /* Argument to pass to proc. */
- struct TkEventHandler *nextPtr;
- /* Next in list of handlers
- * associated with window (NULL means
- * end of list). */
-} TkEventHandler;
-
-/*
- * One of the following structures exists for each selection
- * handler created by calling Tk_CreateSelHandler. This
- * information is used by tkSelect.c only.
- */
-
-typedef struct TkSelHandler {
- Atom target; /* Target type for selection
- * conversion, such as TARGETS or
- * STRING. */
- Atom format; /* Format in which selection
- * info will be returned, such
- * as STRING or ATOM. */
- Tk_SelectionProc *proc; /* Procedure to generate selection
- * in this format. */
- ClientData clientData; /* Argument to pass to proc. */
- int size; /* Size of units returned by proc
- * (8 for STRING, 32 for almost
- * anything else). */
- struct TkSelHandler *nextPtr;
- /* Next selection handler associated
- * with same window (NULL for end of
- * list). */
-} TkSelHandler;
-
-/*
- * Tk keeps one of the following data structures for each main
- * window (created by a call to Tk_CreateMainWindow). It stores
- * information that is shared by all of the windows associated
- * with a particular main window.
- */
-
-typedef struct TkMainInfo {
- struct TkWindow *winPtr; /* Pointer to main window. */
- Tcl_Interp *interp; /* Interpreter associated with application. */
- Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow
- * structs for all windows related to this
- * main window. Managed by tkWindow.c. */
- Tk_BindingTable bindingTable;
- /* Used in conjunction with "bind" command
- * to bind events to Tcl commands. */
- struct TkWindow *focusPtr; /* Identifies window that currently has the
- * focus (or that will get the focus the next
- * time the pointer enters any of the top-level
- * windows associated with this main window).
- * NULL means nobody has the focus.
- * Managed by tkFocus.c. */
- struct TkWindow *focusDefaultPtr;
- /* Window that is to receive the focus by
- * default when the focusPtr window is
- * deleted. */
- struct ElArray *optionRootPtr;
- /* Top level of option hierarchy for this
- * main window. NULL means uninitialized.
- * Managed by tkOption.c. */
-} TkMainInfo;
-
-/*
- * Tk keeps one of the following structures for each window.
- * Some of the information (like size and location) is a shadow
- * of information managed by the X server, and some is special
- * information used here, such as event and geometry management
- * information. This information is (mostly) managed by tkWindow.c.
- * WARNING: the declaration below must be kept consistent with the
- * Tk_ClientWindow structure in tk.h. If you change one, be sure to
- * change the other!!
- */
-
-typedef struct TkWindow {
-
- /*
- * Structural information:
- */
-
- Display *display; /* Display containing window. */
- TkDisplay *dispPtr; /* Tk's information about display
- * for window. */
- int screenNum; /* Index of screen for window, among all
- * those for dispPtr. */
- Visual *visual; /* Visual to use for window. If not default,
- * MUST be set before X window is created. */
- int depth; /* Number of bits/pixel. */
- Window window; /* X's id for window. NULL means window
- * hasn't actually been created yet, or it's
- * been deleted. */
- struct TkWindow *childList; /* First in list of child windows,
- * or NULL if no children. */
- struct TkWindow *parentPtr; /* Pointer to parent window (logical
- * parent, not necessarily X parent), or
- * NULL if this is a main window. */
- struct TkWindow *nextPtr; /* Next in list of children with
- * same parent (NULL if end of
- * list). */
- TkMainInfo *mainPtr; /* Information shared by all windows
- * associated with a particular main
- * window. NULL means this window is
- * a rogue that isn't associated with
- * any application (at present, there
- * should never be any rogues). */
-
- /*
- * Name and type information for the window:
- */
-
- char *pathName; /* Path name of window (concatenation
- * of all names between this window and
- * its top-level ancestor). This is a
- * pointer into an entry in
- * mainPtr->nameTable or NULL if mainPtr
- * is NULL. */
- Tk_Uid nameUid; /* Name of the window within its parent
- * (unique within the parent). */
- Tk_Uid classUid; /* Class of the window. NULL means window
- * hasn't been given a class yet. */
-
- /*
- * Geometry and other attributes of window. This information
- * may not be updated on the server immediately; stuff that
- * hasn't been reflected in the server yet is called "dirty".
- * At present, information can be dirty only if the window
- * hasn't yet been created.
- */
-
- XWindowChanges changes; /* Geometry and other info about
- * window. */
- unsigned int dirtyChanges; /* Bits indicate fields of "changes"
- * that are dirty. */
- XSetWindowAttributes atts; /* Current attributes of window. */
- unsigned long dirtyAtts; /* Bits indicate fields of "atts"
- * that are dirty. */
-
- unsigned int flags; /* Various flag values: these are all
- * defined in tk.h (confusing, but they're
- * needed there for some query macros). */
-
- /*
- * Information kept by the event manager (tkEvent.c):
- */
-
- TkEventHandler *handlerList;/* First in list of event handlers
- * declared for this window, or
- * NULL if none. */
- /*
- * Information related to input focussing (tkFocus.c):
- */
-
- Tk_FocusProc *focusProc; /* Procedure to invoke when this window
- * gets or loses the input focus. NULL
- * means this window is not prepared to
- * receive the focus. */
- ClientData focusData; /* Arbitrary value to pass to focusProc. */
-
- /*
- * Information used by tkOption.c to manage options for the
- * window.
- */
-
- int optionLevel; /* -1 means no option information is
- * currently cached for this window.
- * Otherwise this gives the level in
- * the option stack at which info is
- * cached. */
- /*
- * Information used by tkSelect.c to manage the selection.
- */
-
- TkSelHandler *selHandlerList;
- /* First in list of handlers for
- * returning the selection in various
- * forms. */
- Tk_LostSelProc *selClearProc;
- ClientData selClearData; /* Info to pass to selClearProc. */
-
- /*
- * Information used by tkGeometry.c for geometry management.
- */
-
- Tk_GeometryProc *geomProc; /* Procedure to handle geometry
- * requests (NULL means no window is
- * unmanaged). */
- ClientData geomData; /* Argument for geomProc. */
- int reqWidth, reqHeight; /* Arguments from last call to
- * Tk_GeometryRequest, or 0's if
- * Tk_GeometryRequest hasn't been
- * called. */
- int internalBorderWidth; /* Width of internal border of window
- * (0 means no internal border). Geom.
- * mgr. should not place children on top
- * of the border. */
-
- /*
- * Information maintained by tkWm.c for window manager communication.
- */
-
- struct TkWmInfo *wmInfoPtr; /* For top-level windows, points to
- * structure with wm-related info (see
- * tkWm.c). For other windows, this
- * is NULL. */
-} TkWindow;
-
-/*
- * The context below is used to map from an X window id to
- * the TkWindow structure associated with the window.
- */
-
-extern XContext tkWindowContext;
-
-/*
- * Pointer to first entry in list of all displays currently known.
- */
-
-extern TkDisplay *tkDisplayList;
-
-/*
- * Flags passed to TkMeasureChars:
- */
-
-#define TK_WHOLE_WORDS 1
-#define TK_AT_LEAST_ONE 2
-#define TK_PARTIAL_OK 4
-#define TK_NEWLINES_NOT_SPECIAL 8
-
-/*
- * Location of library directory containing Tk scripts. This value
- * is put in the $tkLibrary variable for each application.
- */
-
-#ifndef TK_LIBRARY
-#define TK_LIBRARY "/usr/local/lib/tk"
-#endif
-
-/*
- * Miscellaneous variables shared among Tk modules but not exported
- * to the outside world:
- */
-
-extern Tk_Uid tkActiveUid;
-extern Tk_Uid tkDisabledUid;
-extern Tk_Uid tkNormalUid;
-
-/*
- * Internal procedures shared among Tk modules but not exported
- * to the outside world:
- */
-
-extern int TkAreaToPolygon _ANSI_ARGS_((double *polyPtr,
- int numPoints, double *rectPtr));
-extern void TkBezierPoints _ANSI_ARGS_((double control[],
- int numSteps, double *coordPtr));
-extern void TkBindEventProc _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-extern Time TkCurrentTime _ANSI_ARGS_((TkDisplay *dispPtr));
-extern int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-extern void TkDisplayChars _ANSI_ARGS_((Display *display,
- Drawable drawable, GC gc,
- XFontStruct *fontStructPtr, char *string,
- int numChars, int x, int y, int flags));
-extern void TkEventDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkFocusDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern int TkFocusFilterEvent _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-extern void TkGetButtPoints _ANSI_ARGS_((double p1[], double p2[],
- double width, int project, double m1[],
- double m2[]));
-extern int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin));
-extern int TkGetMiterPoints _ANSI_ARGS_((double p1[], double p2[],
- double p3[], double width, double m1[],
- double m2[]));
-extern void TkGrabDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkGrabTriggerProc _ANSI_ARGS_((XEvent *eventPtr));
-extern int TkLineToArea _ANSI_ARGS_((double end1Ptr[2],
- double end2Ptr[2], double rectPtr[4]));
-extern double TkLineToPoint _ANSI_ARGS_((double end1Ptr[2],
- double end2Ptr[2], double pointPtr[2]));
-extern void TkMakeBezierPostscript _ANSI_ARGS_((Tcl_Interp *interp,
- double *pointPtr, int numPoints,
- Tk_PostscriptInfo *psInfoPtr));
-extern int TkMeasureChars _ANSI_ARGS_((XFontStruct *fontStructPtr,
- char *source, int maxChars, int startX, int maxX,
- int flags, int *nextXPtr));
-extern void TkOptionDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern int TkOvalToArea _ANSI_ARGS_((double *ovalPtr,
- double *rectPtr));
-extern double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[4],
- double width, int filled, double pointPtr[2]));
-extern int TkPointerEvent _ANSI_ARGS_((XEvent *eventPtr,
- TkWindow *winPtr));
-extern int TkPolygonToArea _ANSI_ARGS_((double *polyPtr,
- int numPoints, double *rectPtr));
-extern double TkPolygonToPoint _ANSI_ARGS_((double *polyPtr,
- int numPoints, double *pointPtr));
-extern void TkSelDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin,
- XEvent *eventPtr));
-extern void TkSelPropProc _ANSI_ARGS_((XEvent *eventPtr));
-extern void TkUnderlineChars _ANSI_ARGS_((Display *display,
- Drawable drawable, GC gc,
- XFontStruct *fontStructPtr, char *string,
- int x, int y, int flags, int firstChar,
- int lastChar));
-extern void TkWmDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkWmMapWindow _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *evenvPtr));
-extern void TkWmSetClass _ANSI_ARGS_((TkWindow *winPtr));
-extern void TkWmNewWindow _ANSI_ARGS_((TkWindow *winPtr));
-
-#endif /* _TKINT */
diff --git a/user.c b/user.c
index dcc5db6..280ba3f 100644
--- a/user.c
+++ b/user.c
@@ -5,6 +5,9 @@
#include <stdlib.h>
#include "prototypes.h"
+#define DEFAULT_MSG_QUEUE_SIZE 8
+
+
/**********************************************************************
* USER_InitApp
*
@@ -13,5 +16,11 @@
int
USER_InitApp(int hInstance)
{
+ /* Initialize built-in window classes */
+ WIDGETS_Init();
+
+ /* Create task message queue */
+ if (!SetMessageQueue( DEFAULT_MSG_QUEUE_SIZE )) return 0;
+
return 1;
}
diff --git a/user.spec b/user.spec
index fa9953e..bf14b80 100644
--- a/user.spec
+++ b/user.spec
@@ -13,14 +13,20 @@
41 pascal CreateWindow(ptr ptr long word word word word word word word ptr)
CreateWindow(1 2 3 4 5 6 7 8 9 10 11)
42 pascal ShowWindow(word word) ShowWindow(1 2)
+53 pascal DestroyWindow(word) DestroyWindow(1)
57 pascal RegisterClass(ptr) RegisterClass(1)
66 pascal GetDC(word) GetDC(1)
-85 pascal DrawText(word ptr word ptr word) DrawText(1 2 3 4 5)
+85 pascal DrawText(word ptr s_word ptr word) DrawText(1 2 3 4 5)
104 pascal MessageBeep(word) MessageBeep(1)
107 pascal DefWindowProc(word word word long) DefWindowProc(1 2 3 4)
108 pascal GetMessage(ptr word word word) GetMessage(1 2 3 4)
+109 pascal PeekMessage(ptr word word word word) PeekMessage(1 2 3 4 5)
+110 pascal PostMessage(word word word word) PostMessage(1 2 3 4)
+111 pascal SendMessage(word word word word) SendMessage(1 2 3 4)
113 pascal TranslateMessage(ptr) TranslateMessage(1)
114 pascal DispatchMessage(ptr) DispatchMessage(1)
+119 pascal GetMessagePos() GetMessagePos()
+120 pascal GetMessageTime() GetMessageTime()
124 pascal UpdateWindow(word) UpdateWindow(1)
151 pascal CreateMenu() CreateMenu()
157 pascal GetMenu(word) GetMenu(1)
@@ -29,4 +35,9 @@
174 pascal LoadIcon(word ptr) RSC_LoadIcon(1 2)
175 pascal LoadBitmap(word ptr) RSC_LoadBitmap(1 2)
176 pascal LoadString(word word ptr s_word) RSC_LoadString(1 2 3 4)
+266 pascal SetMessageQueue(word) SetMessageQueue(1)
+288 pascal GetMessageExtraInfo() GetMessageExtraInfo()
+334 pascal GetQueueStatus(word) GetQueueStatus(1)
+335 pascal GetInputState() GetInputState()
+403 pascal UnregisterClass(ptr word) UnregisterClass(1 2)
411 pascal AppendMenu(word word word ptr) AppendMenu(1 2 3 4)
diff --git a/widgets.c b/widgets.c
new file mode 100644
index 0000000..f80a23e
--- /dev/null
+++ b/widgets.c
@@ -0,0 +1,121 @@
+/*
+ * Windows widgets (built-in window classes)
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "windows.h"
+
+
+static LONG WIDGETS_ButtonWndProc( HWND hwnd, WORD message,
+ WORD wParam, LONG lParam );
+static LONG WIDGETS_StaticWndProc( HWND hwnd, WORD message,
+ WORD wParam, LONG lParam );
+
+#define NB_BUILTIN_CLASSES 2
+
+static WNDCLASS WIDGETS_BuiltinClasses[NB_BUILTIN_CLASSES] =
+{
+ { 0, WIDGETS_ButtonWndProc, 0, 0, 0, 0, 0, 0, NULL, "BUTTON" },
+ { 0, WIDGETS_StaticWndProc, 0, 0, 0, 0, 0, 0, NULL, "STATIC" }
+};
+
+static FARPROC WndProc32[NB_BUILTIN_CLASSES];
+
+
+/***********************************************************************
+ * WIDGETS_Init
+ *
+ * Initialize the built-in window classes.
+ */
+BOOL WIDGETS_Init()
+{
+ int i;
+ WNDCLASS * pClass = WIDGETS_BuiltinClasses;
+
+ for (i = 0; i < NB_BUILTIN_CLASSES; i++, pClass++)
+ {
+ WndProc32[i] = pClass->lpfnWndProc;
+ pClass->lpfnWndProc = (FARPROC) i+1;
+ if (!RegisterClass(pClass)) return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**********************************************************************
+ * WIDGETS_Call32WndProc
+ *
+ * Call the window procedure of a built-in class.
+ */
+LONG WIDGETS_Call32WndProc( FARPROC func, HWND hwnd, WORD message,
+ WORD wParam, LONG lParam )
+{
+ unsigned int i = (unsigned int) func;
+ if (!i || (i > NB_BUILTIN_CLASSES)) return 0;
+ return (*WndProc32[i-1])( hwnd, message, wParam, lParam );
+}
+
+
+/***********************************************************************
+ * WIDGETS_ButtonWndProc
+ */
+static LONG WIDGETS_ButtonWndProc( HWND hwnd, WORD message,
+ WORD wParam, LONG lParam )
+{
+ switch(message)
+ {
+ case WM_CREATE:
+ return 0;
+
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+
+ hdc = BeginPaint( hwnd, &ps );
+ GetClientRect( hwnd, &rect );
+ DrawText(hdc, "Button", -1, &rect,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+ EndPaint( hwnd, &ps );
+ return 0;
+ }
+
+ default:
+ return DefWindowProc( hwnd, message, wParam, lParam );
+ }
+}
+
+
+/***********************************************************************
+ * WIDGETS_StaticWndProc
+ */
+static LONG WIDGETS_StaticWndProc( HWND hwnd, WORD message,
+ WORD wParam, LONG lParam )
+{
+ switch(message)
+ {
+ case WM_CREATE:
+ return 0;
+
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+
+ hdc = BeginPaint( hwnd, &ps );
+ GetClientRect( hwnd, &rect );
+ DrawText(hdc, "Static", -1, &rect,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+ EndPaint( hwnd, &ps );
+ return 0;
+ }
+
+ default:
+ return DefWindowProc( hwnd, message, wParam, lParam );
+ }
+}
diff --git a/win.c b/win.c
new file mode 100644
index 0000000..b0373ca
--- /dev/null
+++ b/win.c
@@ -0,0 +1,287 @@
+/*
+ * Window related functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+#include <X11/Shell.h>
+
+#include "class.h"
+#include "win.h"
+
+extern Widget XT_topLevelWidget;
+
+
+static HWND firstWindow = 0;
+
+
+/***********************************************************************
+ * WIN_FindWndPtr
+ *
+ * Return a pointer to the WND structure corresponding to a HWND.
+ * The caller must GlobalUnlock the pointer.
+ */
+WND * WIN_FindWndPtr( HWND hwnd )
+{
+ WND * ptr;
+
+ if (!hwnd) return NULL;
+ ptr = (WND *) GlobalLock( hwnd );
+ if (ptr->dwMagic != WND_MAGIC)
+ {
+ GlobalUnlock( hwnd );
+ return NULL;
+ }
+ return ptr;
+}
+
+
+/***********************************************************************
+ * CreateWindow (USER.41)
+ */
+HWND CreateWindow( LPSTR className, LPSTR windowName,
+ DWORD style, int x, int y, int width, int height,
+ HWND parent, HMENU menu, HANDLE instance, LPSTR data )
+{
+ HANDLE class, hwnd;
+ CLASS *classPtr;
+ WND *wndPtr, *parentPtr = NULL;
+ CREATESTRUCT createStruct;
+ Widget parentWidget = 0;
+
+ printf( "CreateWindow: %s\n", windowName );
+
+ if (x == CW_USEDEFAULT) x = 0;
+ if (y == CW_USEDEFAULT) y = 0;
+ if (width == CW_USEDEFAULT) width = 600;
+ if (height == CW_USEDEFAULT) height = 400;
+
+ /* Find the parent and class */
+
+ if (parent)
+ {
+ /* Check if parent is valid */
+ parentPtr = WIN_FindWndPtr( parent );
+ if (!parentPtr) return 0;
+ }
+ else if (style & WS_CHILD) return 0; /* WS_CHILD needs a parent */
+
+ if (!(class = CLASS_FindClassByName( className, &classPtr )))
+ {
+ GlobalUnlock( parent );
+ return 0;
+ }
+
+ /* Create the window structure */
+
+ hwnd = GlobalAlloc( GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra );
+ if (!hwnd)
+ {
+ GlobalUnlock( parent );
+ GlobalUnlock( class );
+ return 0;
+ }
+
+ /* Fill the structure */
+
+ wndPtr = (WND *) GlobalLock( hwnd );
+ wndPtr->hwndNext = 0;
+ wndPtr->hwndChild = 0;
+ wndPtr->dwMagic = WND_MAGIC;
+ wndPtr->hwndParent = parent;
+ wndPtr->hwndOwner = parent; /* What else? */
+ wndPtr->hClass = class;
+ wndPtr->hInstance = instance;
+ wndPtr->rectClient.left = x;
+ wndPtr->rectClient.top = y;
+ wndPtr->rectClient.right = x + width;
+ wndPtr->rectClient.bottom = y + height;
+ wndPtr->rectWindow = wndPtr->rectClient;
+ wndPtr->hrgnUpdate = 0;
+ wndPtr->hwndLastActive = 0;
+ wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
+ wndPtr->dwStyle = style;
+ wndPtr->hDCE = 0;
+ wndPtr->hmenuSystem = 0;
+ wndPtr->wIDmenu = menu;
+ if (classPtr->wc.cbWndExtra)
+ memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
+ classPtr->cWindows++;
+
+ /* Insert the window in the linked list */
+
+ if (parent)
+ {
+ wndPtr->hwndNext = parentPtr->hwndChild;
+ parentPtr->hwndChild = hwnd;
+ }
+ else /* Top-level window */
+ {
+ wndPtr->hwndNext = firstWindow;
+ firstWindow = hwnd;
+ }
+
+ /* Fill the CREATESTRUCT */
+
+ createStruct.lpCreateParams = data;
+ createStruct.hInstance = instance;
+ createStruct.hMenu = menu;
+ createStruct.hwndParent = parent;
+ createStruct.cx = width;
+ createStruct.cy = height;
+ createStruct.x = x;
+ createStruct.y = y;
+ createStruct.style = style;
+ createStruct.lpszName = windowName;
+ createStruct.lpszClass = className;
+ createStruct.dwExStyle = 0;
+
+ /* Create the widgets */
+
+ if (style & WS_CHILD)
+ {
+ wndPtr->shellWidget = 0;
+ wndPtr->winWidget = XtVaCreateManagedWidget(className,
+ coreWidgetClass,
+ parentPtr->winWidget,
+ XtNx, x,
+ XtNy, y,
+ XtNwidth, width,
+ XtNheight, height,
+ NULL );
+ }
+ else
+ {
+ wndPtr->shellWidget = XtVaAppCreateShell(className,
+ windowName,
+ topLevelShellWidgetClass,
+ XtDisplay(XT_topLevelWidget),
+ XtNx, x,
+ XtNy, y,
+ NULL );
+ wndPtr->winWidget = XtVaCreateManagedWidget(className,
+ compositeWidgetClass,
+ wndPtr->shellWidget,
+ XtNwidth, width,
+ XtNheight, height,
+ NULL );
+ }
+
+ /* Send the WM_CREATE message */
+
+ if (CallWindowProc( wndPtr->lpfnWndProc, hwnd,
+ WM_CREATE, 0, (LONG) &createStruct ) == -1)
+ {
+ /* Abort window creation */
+ if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
+ else XtDestroyWidget( wndPtr->winWidget );
+ GlobalUnlock( parent );
+ GlobalUnlock( class );
+ GlobalUnlock( hwnd );
+ GlobalFree( hwnd );
+ return 0;
+ }
+
+ EVENT_AddHandlers( wndPtr->winWidget, hwnd );
+
+ GlobalUnlock( parent );
+ GlobalUnlock( class );
+ GlobalUnlock( hwnd );
+ return hwnd;
+}
+
+/***********************************************************************
+ * DestroyWindow (USER.53)
+ */
+BOOL DestroyWindow( HWND hwnd )
+{
+ WND *wndPtr, *parentPtr;
+ CLASS * classPtr;
+
+ wndPtr = WIN_FindWndPtr( hwnd );
+ if (!wndPtr) return FALSE;
+
+ if (wndPtr->hwndParent)
+ {
+ parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+ printf( "INTERNAL ERROR: DestroyWindow: Invalid window parent\n" );
+ return FALSE;
+ }
+
+ classPtr = CLASS_FindClassPtr( wndPtr->hClass );
+ if (!classPtr)
+ {
+ printf( "INTERNAL ERROR: DestroyWindow: Invalid window class\n" );
+ return FALSE;
+ }
+
+ SendMessage( hwnd, WM_DESTROY, 0, 0 );
+
+ /* Destroy all children */
+
+ /* ........... */
+
+ /* Remove the window from the linked list */
+
+ /* ........... */
+
+ /* Destroy the window */
+
+ if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
+ else XtDestroyWidget( wndPtr->winWidget );
+ classPtr->cWindows--;
+ GlobalUnlock( wndPtr->hClass );
+ if (wndPtr->hwndParent) GlobalUnlock( wndPtr->hwndParent );
+ GlobalUnlock( hwnd );
+ GlobalFree( hwnd );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetClientRect (USER.33)
+ */
+void GetClientRect( HWND hwnd, LPRECT rect )
+{
+ WND * wndPtr = WIN_FindWndPtr( hwnd );
+ rect->left = rect->top = rect->right = rect->bottom = 0;
+ if (wndPtr)
+ {
+ XtVaGetValues(wndPtr->winWidget,
+ XtNwidth, &rect->right,
+ XtNheight, &rect->bottom,
+ NULL );
+ GlobalUnlock( hwnd );
+ }
+}
+
+
+/***********************************************************************
+ * ShowWindow (USER.42)
+ */
+BOOL ShowWindow( HWND hwnd, int cmd )
+{
+ WND * wndPtr = WIN_FindWndPtr( hwnd );
+ if (wndPtr)
+ {
+ if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
+ GlobalUnlock( hwnd );
+ }
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * UpdateWindow (USER.124)
+ */
+void UpdateWindow( HWND hwnd )
+{
+ SendMessage( hwnd, WM_PAINT, 0, 0 );
+}
+
+
diff --git a/win.h b/win.h
new file mode 100644
index 0000000..93162ab
--- /dev/null
+++ b/win.h
@@ -0,0 +1,50 @@
+/*
+ * Window definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef WIN_H
+#define WIN_H
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+
+#include "windows.h"
+
+
+#define WND_MAGIC 0x444e4957 /* 'WIND' */
+
+
+typedef struct tagWND
+{
+ HWND hwndNext; /* Next sibling */
+ HWND hwndChild; /* First child */
+ DWORD dwMagic; /* Magic number (must be WND_MAGIC) */
+ HWND hwndParent; /* Window parent (from CreateWindow) */
+ HWND hwndOwner; /* Window owner */
+ HCLASS hClass; /* Window class */
+ HANDLE hInstance; /* Window hInstance (from CreateWindow) */
+ RECT rectClient; /* Window client area screen coords */
+ RECT rectWindow; /* Window whole area screen coords */
+ HRGN hrgnUpdate; /* Update region */
+ HWND hwndLastActive; /* Last active popup hwnd */
+ FARPROC lpfnWndProc; /* Window procedure */
+ DWORD dwStyle; /* Window style (from CreateWindow) */
+ HANDLE hDCE; /* Window DC Entry (if CS_OWNDC) */
+ HMENU hmenuSystem; /* System menu */
+ WORD wIDmenu; /* ID or hmenu (from CreateWindow) */
+ Widget shellWidget; /* For top-level windows */
+ Widget winWidget; /* For all windows */
+ WORD wExtra[1]; /* Window extra bytes */
+} WND;
+
+
+ /* The caller must GlobalUnlock the pointer returned
+ * by this function (except when NULL).
+ */
+WND * WIN_FindWndPtr( HWND hwnd );
+
+
+#endif /* WIN_H */
diff --git a/windows.h b/windows.h
index c97f5fe..f8ae2be 100644
--- a/windows.h
+++ b/windows.h
@@ -1,5 +1,8 @@
/* Initial draft attempt of windows.h, by Peter MacDonald, pmacdona@sanjuan.uvic.ca */
+#ifndef WINDOWS_H
+#define WINDOWS_H
+
#ifndef _WINARGS
typedef unsigned short WORD;
@@ -12,19 +15,20 @@
typedef WORD HANDLE;
typedef HANDLE HWND;
typedef HANDLE HDC;
+typedef HANDLE HCLASS;
typedef HANDLE HCURSOR;
typedef HANDLE HFONT;
typedef HANDLE HPEN;
typedef HANDLE HRGN;
typedef HANDLE HPALETTE;
typedef HANDLE HICON;
+typedef HANDLE HINSTANCE;
typedef HANDLE HMENU;
typedef HANDLE HBITMAP;
typedef HANDLE HBRUSH;
typedef HANDLE LOCALHANDLE;
typedef char *LPSTR;
typedef char *NPSTR;
-typedef char *LPMSG;
typedef int *LPINT;
typedef void *LPVOID;
typedef long (*FARPROC)();
@@ -66,25 +70,44 @@
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
- LPSTR lpszMenuName, lpszClassName;
+ LPSTR lpszMenuName __attribute__ ((packed));
+ LPSTR lpszClassName __attribute__ ((packed));
} WNDCLASS;
typedef WNDCLASS * PWNDCLASS;
typedef WNDCLASS * NPWNDCLASS;
typedef WNDCLASS * LPWNDCLASS;
-typedef struct { int x, y; } POINT;
+typedef struct {
+ void * lpCreateParams;
+ HINSTANCE hInstance;
+ HMENU hMenu;
+ HWND hwndParent;
+ short cy;
+ short cx;
+ short y;
+ short x;
+ LONG style __attribute__ ((packed));
+ char * lpszName __attribute__ ((packed));
+ char * lpszClass __attribute__ ((packed));
+ DWORD dwExStyle __attribute__ ((packed));
+} CREATESTRUCT, *LPCREATESTRUCT;
+
+
+typedef struct { short x, y; } POINT;
typedef POINT *PPOINT;
typedef POINT *NPPOINT;
typedef POINT *LPPOINT;
-typedef struct {
- HWND hwnd;
- WORD message, wParam;
- long lParam;
- DWORD time;
- POINT pt;
-} MSG;
+typedef struct tagMSG
+{
+ HWND hwnd;
+ WORD message;
+ WORD wParam;
+ DWORD lParam __attribute__ ((packed));
+ DWORD time __attribute__ ((packed));
+ POINT pt __attribute__ ((packed));
+} MSG, *LPMSG;
typedef WORD ATOM;
@@ -270,7 +293,57 @@
WM_DELETEITEM, WM_VKEYTOITEM,
WM_CHARTOITEM, WM_SETFONT, WM_GETFONT };
-#define WM_COMMAND 0x0111
+ /* Keyboard messages */
+#define WM_KEYDOWN 0x0100
+#define WM_KEYUP 0x0101
+#define WM_CHAR 0x0102
+#define WM_DEADCHAR 0x0103
+#define WM_SYSKEYDOWN 0x0104
+#define WM_SYSKEYUP 0x0105
+#define WM_SYSCHAR 0x0106
+#define WM_SYSDEADCHAR 0x0107
+#define WM_KEYFIRST WM_KEYDOWN
+#define WM_KEYLAST 0x0108
+
+#define WM_COMMAND 0x0111
+#define WM_TIMER 0x0113
+
+ /* Mouse messages */
+#define WM_MOUSEMOVE 0x0200
+#define WM_LBUTTONDOWN 0x0201
+#define WM_LBUTTONUP 0x0202
+#define WM_LBUTTONDBLCLK 0x0203
+#define WM_RBUTTONDOWN 0x0204
+#define WM_RBUTTONUP 0x0205
+#define WM_RBUTTONDBLCLK 0x0206
+#define WM_MBUTTONDOWN 0x0207
+#define WM_MBUTTONUP 0x0208
+#define WM_MBUTTONDBLCLK 0x0209
+#define WM_MOUSEFIRST WM_MOUSEMOVE
+#define WM_MOUSELAST WM_MBUTTONDBLCLK
+
+ /* Key status flags for mouse events */
+#define MK_LBUTTON 0x0001
+#define MK_RBUTTON 0x0002
+#define MK_SHIFT 0x0004
+#define MK_CONTROL 0x0008
+#define MK_MBUTTON 0x0010
+
+ /* Queue status flags */
+#define QS_KEY 0x0001
+#define QS_MOUSEMOVE 0x0002
+#define QS_MOUSEBUTTON 0x0004
+#define QS_MOUSE (QS_MOUSEMOVE | QS_MOUSEBUTTON)
+#define QS_POSTMESSAGE 0x0008
+#define QS_TIMER 0x0010
+#define QS_PAINT 0x0020
+#define QS_SENDMESSAGE 0x0040
+#define QS_ALLINPUT 0x007f
+
+ /* PeekMessage() options */
+#define PM_NOREMOVE 0x0000
+#define PM_REMOVE 0x0001
+#define PM_NOYIELD 0x0002
enum { SW_HIDE, SW_SHOWNORMAL, SW_NORMAL, SW_SHOWMINIMIZED, SW_SHOWMAXIMIZED,
SW_MAXIMIZE, SW_SHOWNOACTIVATE, SW_SHOW, SW_MINIMIZE,
@@ -400,16 +473,23 @@
/* Implemented functions */
F(HMENU,CreateMenu)
+F(BOOL,GetInputState)
+F(LPSTR,GetDOSEnvironment)
+F(DWORD,GetMessagePos)
+F(LONG,GetMessageTime)
+F(LONG,GetMessageExtraInfo)
Fa(BOOL,IsCharAlpha,char,ch)
Fa(BOOL,IsCharAlphaNumeric,char,ch)
Fa(BOOL,IsCharLower,char,ch)
Fa(BOOL,IsCharUpper,char,ch)
-Fa(BOOL,RegisterClass,LPWNDCLASS,a)
+Fa(ATOM,RegisterClass,LPWNDCLASS,a)
Fa(BOOL,TranslateMessage,LPMSG,a)
+Fa(void,PostQuitMessage,int,a)
+Fa(BOOL,SetMessageQueue,int,a)
Fa(int,_lclose,int,a)
Fb(int,_lopen,LPSTR,a,int,b)
Fa(int,lstrlen,LPSTR,a)
-Fa(long,DispatchMessage,MSG *,msg)
+Fa(LONG,DispatchMessage,LPMSG,msg)
Fa(void,UpdateWindow,HWND,a)
Fb(BOOL,ExitWindows,DWORD,dwReserved,WORD,wReturnCode)
Fb(BOOL,ShowWindow,HWND,a,int,b)
@@ -421,6 +501,7 @@
Fb(int,lstrcmpi,LPSTR,a,LPSTR,b )
Fb(void,EndPaint,HWND,a,LPPAINTSTRUCT,b)
Fb(void,GetClientRect,HWND,a,LPRECT,b)
+Fb(BOOL,UnregisterClass,LPSTR,a,HANDLE,b)
Fc(BOOL,LineTo,HDC,a,int,b,int,c)
Fc(LONG,_llseek,int,a,long,b,int,c)
Fc(WORD,_lread,int,a,LPSTR,b,int,c)
@@ -428,9 +509,13 @@
Fc(int,FillRect,HDC,a,LPRECT,b,HBRUSH,c)
Fc(DWORD,MoveTo,HDC,a,int,b,int,c)
Fd(BOOL,AppendMenu,HMENU,a,WORD,b,WORD,c,LPSTR,d)
+Fd(BOOL,PostMessage,HWND,a,WORD,b,WORD,c,LONG,d)
+Fd(LONG,SendMessage,HWND,a,WORD,b,WORD,c,LONG,d)
Fd(BOOL,GetMessage,LPMSG,msg,HWND,b,WORD,c,WORD,d)
Fe(BOOL,Rectangle,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom)
Fe(int,DrawText,HDC,a,LPSTR,str,int,c,LPRECT,d,WORD,flag)
+Fe(BOOL,PeekMessage,LPMSG,a,HWND,b,WORD,c,WORD,d,WORD,e)
+Fe(LONG,CallWindowProc,FARPROC,a,HWND,b,WORD,c,WORD,d,LONG,e)
Fi(BOOL,Arc,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
Fi(BOOL,Chord,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
Fi(BOOL,Pie,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom,int,xStart,int,yStart,int,xEnd,int,yEnd)
@@ -440,10 +525,8 @@
F(BOOL,AnyPopup)
F(BOOL,CloseClipboard)
F(BOOL,EmptyClipboard)
-F(BOOL,GetInputState)
F(BOOL,InSendMessage)
F(DWORD,GetCurrentTime)
-F(DWORD,GetMessagePos)
F(DWORD,GetTickCount)
F(HANDLE,GetCurrentTask)
F(HMENU,CreatePopupMenu)
@@ -456,10 +539,8 @@
F(HWND,GetFocus)
F(HWND,GetSysModalWindow)
F(LONG,GetMenuCheckMarkDimensions)
-F(LONG,GetMessageTime)
F(LONG,GetWinFlags)
F(LPINT,GetThresholdEvent)
-/*F(LPSTR,GetDOSEnvironment)*/
F(LPSTR,ValidateFreeSpaces)
F(void,ValidateCodeSegments)
F(WORD,GetCaretBlinkTime)
@@ -521,7 +602,6 @@
Fa(BOOL,OpenIcon,HWND,a)
Fa(BOOL,RemoveFontResource,LPSTR,a)
Fa(BOOL,SetErrorMode,WORD,a)
-Fa(BOOL,SetMessageQueue,int,a)
Fa(BOOL,SwapMouseButton,BOOL,a)
Fa(BOOL,UnrealizeObject,HBRUSH,a)
Fa(BYTE,GetTempDrive,BYTE,a)
@@ -656,7 +736,6 @@
Fa(void,HideCaret,HWND,a)
Fa(void,MessageBeep,WORD,a)
Fa(void,OutputDebugString,LPSTR,a)
-Fa(void,PostQuitMessage,int,a)
Fa(void,ReplyMessage,LONG,a)
Fa(void,SetCaretBlinkTime,WORD,a)
Fa(void,SetDoubleClickTime,WORD,a)
@@ -688,7 +767,6 @@
Fb(BOOL,SetMenu,HWND,a,HMENU,b)
Fb(BOOL,TranslateMDISysAccel,HWND,a,LPMSG,b)
Fb(BOOL,UnhookWindowsHook,int,a,FARPROC,b)
-Fb(BOOL,UnregisterClass,LPSTR,a,HANDLE,b)
Fb(DWORD,GetNearestColor,HDC,a,DWORD,b)
Fb(DWORD,SetBkColor,HDC,a,DWORD,b)
Fb(DWORD,SetMapperFlags,HDC,a,DWORD,b)
@@ -885,7 +963,6 @@
Fd(BOOL,HiliteMenuItem,HWND,a,HMENU,b,WORD,c,WORD,d)
Fd(BOOL,PolyPolygon,HDC,a,LPPOINT,b,LPINT,c,int,d)
Fd(BOOL,PostAppMessage,HANDLE,a,WORD,b,WORD,c,LONG,d)
-Fd(BOOL,PostMessage,HWND,a,WORD,b,WORD,c,LONG,d)
Fd(BOOL,WinHelp,HWND,hwndMain,LPSTR,lpszHelp,WORD,usCommand,DWORD,ulData)
Fd(BOOL,WritePrivateProfileString,LPSTR,a,LPSTR,b,LPSTR,c,LPSTR,d)
Fd(DWORD,DefHookProc,int,a,WORD,b,DWORD,c,FARPROC FAR*,d)
@@ -900,7 +977,6 @@
Fd(LONG,DefDlgProc,HWND,a,WORD,b,WORD,c,LONG,d)
Fd(LONG,DefMDIChildProc,HWND,a,WORD,b,WORD,c,LONG,d)
Fd(LONG,DefWindowProc,HWND,a,WORD,b,WORD,c,LONG,d)
-Fd(LONG,SendMessage,HWND,a,WORD,b,WORD,c,LONG,d)
Fd(WORD,GetDlgItemInt,HWND,a,int,b,BOOL FAR*,c,BOOL,d)
Fd(WORD,GetPaletteEntries,HPALETTE,a,WORD,b,WORD,c,LPPALETTEENTRY,d)
Fd(WORD,GetPrivateProfileInt,LPSTR,a,LPSTR,b,int,c,LPSTR,d)
@@ -931,7 +1007,6 @@
Fe(BOOL,FrameRgn,HDC,a,HRGN,b,HBRUSH,e,int,c,int,d)
Fe(BOOL,InsertMenu,HMENU,a,WORD,b,WORD,c,WORD,d,LPSTR,e)
Fe(BOOL,ModifyMenu,HMENU,a,WORD,b,WORD,c,WORD,d,LPSTR,e)
-Fe(BOOL,PeekMessage,LPMSG,a,HWND,b,WORD,c,WORD,d,WORD,e)
Fe(BOOL,SetMenuItemBitmaps,HMENU,a,WORD,b,WORD,c,HBITMAP,d,HBITMAP,e)
Fe(BOOL,TextOut,HDC,a,int,b,int,c,LPSTR,d,int,e)
Fe(DWORD,GetTabbedTextExtent,HDC,a,LPSTR,b,int,c,int,d,LPINT,e)
@@ -940,7 +1015,6 @@
Fe(HBITMAP,CreateBitmap,int,a,int,b,BYTE,c,BYTE,d,LPSTR,e)
Fe(HWND,CreateDialogIndirectParam,HANDLE,a,LPSTR,b,HWND,c,FARPROC,d,LONG,e)
Fe(HWND,CreateDialogParam,HANDLE,a,LPSTR,b,HWND,c,FARPROC,d,LONG,e)
-Fe(LONG,CallWindowProc,FARPROC,a,HWND,b,WORD,c,WORD,d,LONG,e)
Fe(LONG,DefFrameProc,HWND,a,HWND,b,WORD,c,WORD,d,LONG,e)
Fe(LONG,SendDlgItemMessage,HWND,a,int,b,WORD,c,WORD,d,LONG,e)
Fe(int,DialogBoxIndirectParam,HANDLE,a,HANDLE,b,HWND,c,FARPROC,d,LONG,e)
@@ -982,3 +1056,5 @@
Fl(int,SetDIBitsToDevice,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l)
Fm(int,StretchDIBits,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l,DWORD,m)
Fn(HFONT,CreateFont,int,a,int,b,int,c,int,d,int,e,BYTE,f,BYTE,g,BYTE,h,BYTE,i,BYTE,j,BYTE,k,BYTE,l,BYTE,m,LPSTR,n)
+
+#endif /* WINDOWS_H */
diff --git a/wintcl.c b/wintcl.c
deleted file mode 100644
index a9bdbb9..0000000
--- a/wintcl.c
+++ /dev/null
@@ -1,858 +0,0 @@
-#define _WINMAIN
-/*
- * main.c --
- *
- * This file contains the main program for "wish", a windowing
- * shell based on Tk and Tcl. It also provides a template that
- * can be used as the basis for main programs for other Tk
- * applications.
- *
- * Copyright 1990-1992 Regents of the University of California.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- * Modifiyed by Peter MacDonald for windows API.
- */
-
-#ifndef lint
-static char rcsid[] = "$Header: /user6/ouster/wish/RCS/main.c,v 1.72 93/02/03 10:20:42 ouster Exp $ SPRITE (Berkeley)";
-#endif
-
-
-#include <stdio.h>
-#include <stdarg.h>
-#include "tkConfig.h"
-#include "tkInt.h"
-
-#include "callback.h"
-
-#define dprintf(n,s) dodprintf(s)
-
-void dodprintf(char *str, ... )
-{
- va_list va;
- char buf[2000];
- va_start(va, str);
- vsprintf(buf,str,va);
- puts(buf);
- va_end(str);
-}
-
-#define TK_EXTENDED
-#ifdef TK_EXTENDED
-# include "tclExtend.h"
- extern Tcl_Interp *tk_mainInterp; /* Need to process signals */
-#endif
-
-/*
- * Declarations for library procedures:
- */
-
-extern int isatty();
-
-/*
- * Command used to initialize wish:
- */
-
-#ifdef TK_EXTENDED
-static char initCmd[] = "load wishx.tcl";
-#else
-static char initCmd[] = "source $tk_library/wish.tcl";
-#endif
-
-/*
- * Global variables used by the main program:
- */
-
-static Tk_Window w; /* The main window for the application. If
- * NULL then the application no longer
- * exists. */
-static Tcl_Interp *interp; /* Interpreter for this application. */
-static int x, y; /* Coordinates of last location moved to;
- * used by "moveto" and "lineto" commands. */
-static Tcl_CmdBuf buffer; /* Used to assemble lines of terminal input
- * into Tcl commands. */
-static int tty; /* Non-zero means standard input is a
- * terminal-like device. Zero means it's
- * a file. */
-
-/*
- * Command-line options:
- */
-
-int synchronize = 0;
-char *fileName = NULL;
-char *name = NULL;
-char *display = NULL;
-char *geometry = NULL;
-
-Tk_ArgvInfo argTable[] = {
- {"-file", TK_ARGV_STRING, (char *) NULL, (char *) &fileName,
- "File from which to read commands"},
- {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry,
- "Initial geometry for window"},
- {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,
- "Display to use"},
- {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name,
- "Name to use for application"},
- {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize,
- "Use synchronous mode for display server"},
- {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
- (char *) NULL}
-};
-
-/*
- * Declaration for Tcl command procedure to create demo widget. This
- * procedure is only invoked if SQUARE_DEMO is defined.
- */
-
-extern int Tk_SquareCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-
-/*
- * Forward declarations for procedures defined later in this file:
- */
-
-static void DelayedMap _ANSI_ARGS_((ClientData clientData));
-static int LinetoCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-static int MovetoCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-static void StdinProc _ANSI_ARGS_((ClientData clientData,
- int mask));
-static void StructureProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
-static int _WinCallBack _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-static int _getStrHandle _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-
-
-/*
- *----------------------------------------------------------------------
- *
- * main --
- *
- * Main program for Wish.
- *
- * Results:
- * None. This procedure never returns (it exits the process when
- * it's done
- *
- * Side effects:
- * This procedure initializes the wish world and then starts
- * interpreting commands; almost anything could happen, depending
- * on the script being interpreted.
- *
- *----------------------------------------------------------------------
- */
-
-int
-main( int argc, /* Number of arguments. */
- char **argv) /* Array of argument strings. */
-{
- char *args, *p, *msg;
- char buf[20]; char bigBuf[300];
- int result;
- Tk_3DBorder border;
-
-#ifdef TK_EXTENDED
- tk_mainInterp = interp = Tcl_CreateExtendedInterp();
-#else
- interp = Tcl_CreateInterp();
-#endif
-#ifdef TCL_MEM_DEBUG
- Tcl_InitMemory(interp);
-#endif
-
- /*
- * Parse command-line arguments.
- */
-
-#if 0
- if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv, argTable, 0)
- != TCL_OK) {
- fprintf(stderr, "%s\n", interp->result);
- exit(1);
- }
-#endif
- if (name == NULL) {
- if (fileName != NULL) {
- p = fileName;
- } else {
- p = argv[0];
- }
- name = strrchr(p, '/');
- if (name != NULL) {
- name++;
- } else {
- name = p;
- }
- }
-
- /*
- * Initialize the Tk application and arrange to map the main window
- * after the startup script has been executed, if any. This way
- * the script can withdraw the window so it isn't ever mapped
- * at all.
- */
-
- w = Tk_CreateMainWindow(interp, display, name);
- if (w == NULL) {
- fprintf(stderr, "%s\n", interp->result);
- exit(1);
- }
- Tk_SetClass(w, "Tk");
- Tk_CreateEventHandler(w, StructureNotifyMask, StructureProc,
- (ClientData) NULL);
- Tk_DoWhenIdle(DelayedMap, (ClientData) NULL);
- if (synchronize) {
- XSynchronize(Tk_Display(w), True);
- }
- Tk_GeometryRequest(w, 200, 200);
- border = Tk_Get3DBorder(interp, w, None, "#ffe4c4");
- if (border == NULL) {
- Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
- Tk_SetWindowBackground(w, WhitePixelOfScreen(Tk_Screen(w)));
- } else {
- Tk_SetBackgroundFromBorder(w, border);
- }
- XSetForeground(Tk_Display(w), DefaultGCOfScreen(Tk_Screen(w)),
- BlackPixelOfScreen(Tk_Screen(w)));
-
- /*
- * Make command-line arguments available in the Tcl variables "argc"
- * and "argv". Also set the "geometry" variable from the geometry
- * specified on the command line.
- */
-
-#if 0
- args = Tcl_Merge(argc-1, argv+1);
- Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
- ckfree(args);
- sprintf(buf, "%d", argc-1);
- Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
-#endif
- if (geometry != NULL) {
- Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY);
- }
-
- /*
- * Add a few application-specific commands to the application's
- * interpreter.
- */
-
- Tcl_CreateCommand(interp, "lineto", LinetoCmd, (ClientData) w,
- (void (*)()) NULL);
- Tcl_CreateCommand(interp, "moveto", MovetoCmd, (ClientData) w,
- (void (*)()) NULL);
-#ifdef SQUARE_DEMO
- Tcl_CreateCommand(interp, "square", Tk_SquareCmd, (ClientData) w,
- (void (*)()) NULL);
-#endif
- Tcl_CreateCommand(interp, "wincallback", _WinCallBack, (ClientData) w,
- (void (*)()) NULL);
- Tcl_CreateCommand(interp, "getstrhandle", _getStrHandle, (ClientData) w,
- (void (*)()) NULL);
-
- /*
- * Execute Wish's initialization script, followed by the script specified
- * on the command line, if any.
- */
-
-#ifdef TK_EXTENDED
- tclAppName = "Wish";
- tclAppLongname = "Wish - Tk Shell";
- tclAppVersion = TK_VERSION;
- Tcl_ShellEnvInit (interp, TCLSH_ABORT_STARTUP_ERR,
- name,
- 0, NULL, /* argv var already set */
- fileName == NULL, /* interactive? */
- NULL); /* Standard default file */
-#endif
- result = Tcl_Eval(interp, initCmd, 0, (char **) NULL);
- if (result != TCL_OK) {
- goto error;
- }
- strcpy(bigBuf, Tcl_GetVar(interp, "auto_path", TCL_GLOBAL_ONLY));
- strcat(bigBuf," /usr/local/windows");
- Tcl_SetVar(interp, "auto_path", bigBuf, TCL_GLOBAL_ONLY);
- dprintf(4,("set auto_path \"$auto_path /usr/local/windows\""));
- if (result != TCL_OK) {
- goto error;
- }
-#if 0
- tty = isatty(0);
- if (fileName != NULL) {
- result = Tcl_VarEval(interp, "source ", fileName, (char *) NULL);
- if (result != TCL_OK) {
- goto error;
- }
- tty = 0;
- } else {
- /*
- * Commands will come from standard input. Set up a handler
- * to receive those characters and print a prompt if the input
- * device is a terminal.
- */
-
- Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0);
- if (tty) {
- printf("wish: ");
- }
- }
-#endif
- fflush(stdout);
- buffer = Tcl_CreateCmdBuf();
- (void) Tcl_Eval(interp, "update", 0, (char **) NULL);
-
- /*
- * Loop infinitely, waiting for commands to execute. When there
- * are no windows left, Tk_MainLoop returns and we clean up and
- * exit.
- */
-/* Tcl_Eval( interp, "button .hello -text \"Hello, world\" -command {\n puts stdout \"Hello, world\"; destroy .\n\
-}\n pack append . .hello {top}\n", 0, (char **)NULL); */
- _WinMain(argc,argv);
- Tcl_DeleteInterp(interp);
- Tcl_DeleteCmdBuf(buffer);
- exit(0);
-
-error:
- msg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if (msg == NULL) {
- msg = interp->result;
- }
- fprintf(stderr, "%s\n", msg);
- Tcl_Eval(interp, "destroy .", 0, (char **) NULL);
- exit(1);
- return 0; /* Needed only to prevent compiler warnings. */
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StdinProc --
- *
- * This procedure is invoked by the event dispatcher whenever
- * standard input becomes readable. It grabs the next line of
- * input characters, adds them to a command being assembled, and
- * executes the command if it's complete.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Could be almost arbitrary, depending on the command that's
- * typed.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static void
-StdinProc(clientData, mask)
- ClientData clientData; /* Not used. */
- int mask; /* Not used. */
-{
-#define BUFFER_SIZE 4000
- char input[BUFFER_SIZE+1];
- static int gotPartial = 0;
- char *cmd;
- int result, count;
-
-count=strlen(input);
- if (count <= 0) {
- if (!gotPartial) {
- if (tty) {
- Tcl_Eval(interp, "destroy .", 0, (char **) NULL);
- exit(0);
- } else {
- Tk_DeleteFileHandler(0);
- }
- return;
- } else {
- input[0] = 0;
- }
- } else {
- input[count] = 0;
- }
- cmd = Tcl_AssembleCmd(buffer, input);
- if (cmd == NULL) {
- gotPartial = 1;
- return;
- }
- gotPartial = 0;
- result = Tcl_RecordAndEval(interp, cmd, 0);
- if (*interp->result != 0) {
- if ((result != TCL_OK) || (tty)) {
- printf("%s\n", interp->result);
- }
- }
- if (tty) {
- printf("wish: ");
- fflush(stdout);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StructureProc --
- *
- * This procedure is invoked whenever a structure-related event
- * occurs on the main window. If the window is deleted, the
- * procedure modifies "w" to record that fact.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Variable "w" may get set to NULL.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static void
-StructureProc(clientData, eventPtr)
- ClientData clientData; /* Information about window. */
- XEvent *eventPtr; /* Information about event. */
-{
- if (eventPtr->type == DestroyNotify) {
- w = NULL;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DelayedMap --
- *
- * This procedure is invoked by the event dispatcher once the
- * startup script has been processed. It waits for all other
- * pending idle handlers to be processed (so that all the
- * geometry information will be correct), then maps the
- * application's main window.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The main window gets mapped.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static void
-DelayedMap(clientData)
- ClientData clientData; /* Not used. */
-{
-
- while (Tk_DoOneEvent(TK_IDLE_EVENTS) != 0) {
- /* Empty loop body. */
- }
- if (w == NULL) {
- return;
- }
- Tk_MapWindow(w);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MoveToCmd and LineToCmd --
- *
- * This procedures are registered as the command procedures for
- * "moveto" and "lineto" Tcl commands. They provide a trivial
- * drawing facility. They don't really work right, in that the
- * drawn information isn't persistent on the screen (it will go
- * away if the window is iconified and de-iconified again). The
- * commands are here partly for testing and partly to illustrate
- * how to add application-specific commands to Tk. You probably
- * shouldn't use these commands in any real scripts.
- *
- * Results:
- * The procedures return standard Tcl results.
- *
- * Side effects:
- * The screen gets modified.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static int
-MovetoCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
-{
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " x y\"", (char *) NULL);
- return TCL_ERROR;
- }
- x = strtol(argv[1], (char **) NULL, 0);
- y = strtol(argv[2], (char **) NULL, 0);
- return TCL_OK;
-}
- /* ARGSUSED */
-static int
-LinetoCmd(dummy, interp, argc, argv)
- ClientData dummy; /* Not used. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
-{
- int newX, newY;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " x y\"", (char *) NULL);
- return TCL_ERROR;
- }
- newX = strtol(argv[1], (char **) NULL, 0);
- newY = strtol(argv[2], (char **) NULL, 0);
- Tk_MakeWindowExist(w);
- XDrawLine(Tk_Display(w), Tk_WindowId(w),
- DefaultGCOfScreen(Tk_Screen(w)), x, y, newX, newY);
- x = newX;
- y = newY;
- return TCL_OK;
-}
-
-/*===============================================================*/
-
-#define _WIN_CODE_SECTION
-static int dte(char *str,...);
-#include <windows.h>
-#include <assert.h>
-
-
-LPWNDCLASS LpWndClass;
-
-static int tclexec(char *str, ... )
-{ int result;
- va_list va;
- char buf[2000];
- va_start(va, str);
- vsprintf(buf,str,va);
- dprintf(32,("tclexec'ing:%s",buf));
- result = Tcl_Eval( interp, buf, 0, (char **)NULL);
- va_end(str);
- if (result != TCL_OK)
- { printf("error evaluating %s\n", buf);
- fprintf(stderr, "%s\n", interp->result);
- exit(-1);
- }
- return(result);
-}
-
-static void str2lower(char *str)
-{
- while (*str)
- { *str = tolower(*str);
- str++;
- }
-}
-
-static char *_handles[300];
-static int _handInd=0;
-
-static char* getStrHandle(int hndl)
-{ static char buf[20];
- if((hndl<_handInd) && (hndl>=0))
- return(_handles[hndl]);
- sprintf(buf, "%d", hndl);
- return(buf);
-}
-
-static int findHandle(char* str)
-{ int i;
- for (i=0; i<_handInd; i++)
- if (!strcmp(str,_handles[i]))
- return(i);
- return(-1);
-}
-
-typedef enum {enum_win, enum_frame, enum_canvas, enum_button, enum_menu} class_enum;
-
-static int allocStrHandle(char *seed, class_enum class)
-{
- static char *classes[]= {"win", "frame", "canvas", "button", "menu"};
- static int classInds[10] = { 0, 0, 0, 0, 0, 0};
- char buf[200];
- assert((class>=0) && (class<=4));
- if (seed && *seed)
- sprintf(buf,"%s.%s%d", seed, classes[class], ++classInds[class]);
- else
- sprintf(buf,"%s%d", classes[class], ++classInds[class]);
- str2lower(buf);
- _handles[_handInd]=strdup(buf);
- return(_handInd++);
-}
-
-#if 0
-static _WinMain(int argc, char *argv[])
-{ int i; char buf[300];
-
- *buf = 0;
- for (i=1; i<argc; i++)
- { if (*buf) strcat(buf," ");
- strcat(buf,argv[i]);
- }
- WinMain(getpid(),NULL,buf,SW_SHOWNORMAL); /* or SW_SHOWMINNOACTIVE*/
- exit(0);
-}
-#endif
-
-static int _WinCallBack( ClientData clientData, Tcl_Interp *interp,
- int argc, char **argv)
-{
- int i;
- if (argc>2)
- { if (!strcmp(argv[1],"menu"))
- {
-#if 0
- LpWndClass->lpfnWndProc(findHandle(argv[2]),
- WM_COMMAND,atoi(argv[4]),0);
-#else
- CALLWNDPROC(LpWndClass->lpfnWndProc,
- findHandle(argv[2]),
- WM_COMMAND,
- atoi(argv[4]),
- 0);
-#endif
- }
- }
-/* for (i=0; i<argc; i++)
- printf("%s\n", argv[i]);
- printf("\n"); */
- return(TCL_OK);
-}
-
-static int _getStrHandle( ClientData clientData, Tcl_Interp *interp,
- int argc, char **argv)
-{
- int i;
- if (argc != 2)
- { sprintf(interp->result, "%s: invalid arg\n", argv[0]);
- return(TCL_ERROR);
- }
- i = atoi(argv[1]);
- strcpy(interp->result, getStrHandle(i));
- return(TCL_OK);
-}
-
-_MsMsg2XvMsg(HWND hwnd, char *event)
-{
- WORD message, wParam = 0; LONG lParam = 0;
- if (1) message=WM_PAINT;
-#if 0
- LpWndClass->lpfnWndProc(hwnd,message,wParam,lParam);
-#else
- CALLWNDPROC(LpWndClass->lpfnWndProc, hwnd, message, wParam, lParam);
-#endif
-}
-
-static short *closed_bits;
-
-HWND CreateWindow(LPSTR szAppName, LPSTR Label, DWORD ol, int x, int y, int w, int h, HWND d, HMENU e, HANDLE i, LPSTR g)
-{ int result, n;
- static int called=0;
- if (x == CW_USEDEFAULT) x=0;
- if (y == CW_USEDEFAULT) y=0;
- if (w == CW_USEDEFAULT) w=500;
- if (h == CW_USEDEFAULT) h=400;
- n=allocStrHandle("",enum_win);
- tclexec( "CreateWindow %s \"%s\" %d %d %d %d", getStrHandle(n), Label, x, y, w, h);
- called=1;
- return((HWND)n);
-}
-
-int DrawText(HDC a, LPSTR str, int c, LPRECT d, WORD flag)
-{ int x=d->left, y=d->top, w = d->right, h=d->bottom;
- if (flag&DT_SINGLELINE);
- if (flag&DT_CENTER);
- x=200;
- if (flag&DT_VCENTER);
- y=200;
- /*tclexec(".%s create text 200 200 -text \"%s\" -anchor n\n",getStrHandle(a), str); */
- tclexec("DrawText %s \"%s\" %d %d %d %d\n",getStrHandle(a), str,
- y,x,h,w);
-}
-
-BOOL GetMessage(LPMSG msg,HWND b,WORD c, WORD d)
-{ static int called=0;
- if (!called)
- _MsMsg2XvMsg(b, 0);
- called=1;
- return(1);
-}
-
-long DispatchMessage(MSG *msg)
-{
- if (tk_NumMainWindows > 0) {
- Tk_DoOneEvent(0);
- return(0);
- }
- exit(0);
-}
-
-BOOL TranslateMessage(LPMSG a){}
-
-void MyEventProc( ClientData clientData, XEvent *eventPtr)
-{
-}
-
-
-BOOL RegisterClass(LPWNDCLASS a)
-{
- /* Tk_CreateEventHandler(win,mask,proc,data); */
- LpWndClass = a; return(1);
-}
-
-BOOL ShowWindow(HWND a, int b)
-{
- if (b != SW_SHOWNORMAL)
- { assert(b==SW_SHOWMINNOACTIVE); /* iconize */
- }
- return(TRUE);
-}
-
-void UpdateWindow(HWND a)
-{
-}
-
-HDC BeginPaint(HWND a, LPPAINTSTRUCT b)
-{ return(a);
-}
-void EndPaint(HWND a, LPPAINTSTRUCT b) { }
-
-void GetClientRect(HWND a, LPRECT b)
-{ b->top = 0; b->left = 0;
- b->bottom = b->top+0;
- b->right = b->left+0;
-}
-
-HMENU CreateMenu(void)
-{ static int n, called=0;
- int result;
- if (!called)
- { n=allocStrHandle("",enum_frame);
- tclexec( "CreateMenuBar %s\n",getStrHandle(n));
- }
- else
- { n=allocStrHandle("",enum_menu);
- tclexec( "CreateMenuEntry %s any 0\n",getStrHandle(n));
- }
- called=1;
- return(n);
-}
-
-BOOL AppendMenu(HMENU a, WORD b, WORD c, LPSTR d)
-{ char *buf; int dist,n;
- char *cmd = getStrHandle(a);
- if (d)
- { char *t;
- buf = strdup(d);
- if (t=strchr(buf,'&'))
- strcpy(t,strchr(d,'&')+1);
- dist = t-buf;
- }
- tclexec("AppendMenu %s %d %s {%s} %d", cmd, b, getStrHandle(c),
- buf, dist);
- return(1);
-}
-
-/* Graphics Primitives */
-BOOL Rectangle(HDC a, int xLeft, int yTop, int xRight, int yBottom)
-{
- XDrawRectangle(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
- xLeft, yTop, xRight-xLeft+1, yBottom-yTop+1);
-}
-
-int FillRect(HDC a,LPRECT b,HBRUSH c)
-{
- XFillRectangle(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
- b->left, b->top, b->right-b->left+1, b->bottom-b->top+1);
-}
-
-static int _LineX=0, _LineY=0;
-
-int LineTo(HDC a, int b, int c)
-{
- XDrawLine(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)),
- _LineX,b, _LineY,c);
- _LineX=b; _LineY=c;
-}
-
-int MoveTo(HDC a, int b, int c) { _LineX=b; _LineY=c; }
-
-BOOL Arc(HDC a, int xLeft, int yTop, int xRight, int yBottom,
- int xStart, int yStart, int xEnd, int yEnd)
-{ int w, h, x, y;
-/* XDrawArc(Tk_Display(w), Tk_WindowId(w), DefaultGCOfScreen(Tk_Screen(w)), x,y,..);*/
-}
-
-BOOL Pie(HDC a, int xLeft, int yTop, int xRight, int yBottom,
- int xStart, int yStart, int xEnd, int yEnd)
-{ int w, h, x,y;
-}
-
-BOOL Chord(HDC a, int xLeft, int yTop, int xRight, int yBottom,
- int xStart, int yStart, int xEnd, int yEnd)
-{ int w, h, x,y;
-}
-
-static int dte(char *str,...)
-{ char cmd[300], *ptr, *ptr2;
- int n, i;
- va_list va;
- va_start(va, str);
- strcpy(cmd, str);
- n = va_arg(va,int);
- for (i=0; i<n; i++)
- { ptr = va_arg(va,char *);
- ptr2 = va_arg(va,char *);
- if (!strncmp("LPSTR",ptr,5))
- sprintf(cmd+strlen(cmd)," \"%s\"", (ptr2?ptr2:""));
- else if (!strncmp("char",ptr,4))
- sprintf(cmd+strlen(cmd)," %c\0", ptr2);
- else if (!strncmp("HANDLE",ptr,6))
- sprintf(cmd+strlen(cmd)," %s", getStrHandle((int)ptr2));
- else
- sprintf(cmd+strlen(cmd)," %d", ptr2);
- }
- strcat(cmd,"\n");
- va_end(va);
- tclexec(cmd);
-}
-
-int wsprintf(LPSTR a,LPSTR b,...) {}
-
-BOOL IsCharAlpha(char ch) { return(isalpha(ch)); }
-BOOL IsCharAlphaNumeric(char ch) { return(isalnum(ch)); }
-BOOL IsCharUpper(char ch) { return(isupper(ch)); }
-BOOL IsCharLower(char ch) { return(islower(ch)); }
-int lstrcmp( LPSTR a, LPSTR b ) { return(strcmp(a,b)); }
-int lstrcmpi( LPSTR a, LPSTR b ) { return(strcasecmp(a,b)); }
-LPSTR lstrcpy( LPSTR a, LPSTR b ) { return(strcpy(a,b)); }
-LPSTR lstrcat( LPSTR a, LPSTR b ) { return(strcat(a,b)); }
-int lstrlen( LPSTR a) { return(strlen(a)); }
-int _lopen( LPSTR a, int b) { return(open(a,b)); }
-int _lclose( int a) { return(close(a)); }
-int _lcreat( LPSTR a, int b) { return(creat(a,b)); }
-LONG _llseek( int a, long b, int c) { return(lseek(a,b,c)); }
-WORD _lread( int a, LPSTR b, int c) { return(read(a,b,c)); }
-WORD _lwrite( int a, LPSTR b, int c) { return(write(a,b,c)); }
-BOOL ExitWindows(DWORD dwReserved, WORD wReturnCode) {exit(0); }
-
diff --git a/xt.c b/xt.c
new file mode 100644
index 0000000..040560f
--- /dev/null
+++ b/xt.c
@@ -0,0 +1,143 @@
+/*
+ * X toolkit functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+#include <X11/Shell.h>
+
+#include "message.h"
+#include "callback.h"
+#include "win.h"
+
+
+Widget XT_topLevelWidget;
+
+static XtAppContext app_context;
+
+
+/***********************************************************************
+ * main
+ */
+void main(int argc, char **argv)
+{
+ XT_topLevelWidget = XtVaAppInitialize(&app_context,
+ "XWine", /* Application class */
+ NULL, 0, /* Option list */
+ &argc, argv, /* Command line args */
+ NULL, /* Fallback resources */
+ NULL );
+ _WinMain( argc, argv );
+}
+
+
+/***********************************************************************
+ * GetMessage (USER.108)
+ */
+BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last )
+{
+ XEvent event;
+
+ while(1)
+ {
+ if (PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
+ XtAppNextEvent( app_context, &event );
+ XtDispatchEvent( &event );
+ }
+
+ return (msg->message != WM_QUIT);
+}
+
+
+/***********************************************************************
+ * DefWindowProc (USER.107)
+ */
+LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
+{
+ PAINTSTRUCT paintstruct;
+
+ printf( "DefWindowProc: %d %d %d %d\n", hwnd, msg, wParam, lParam );
+
+ switch(msg)
+ {
+ case WM_PAINT:
+ BeginPaint( hwnd, &paintstruct );
+ EndPaint( hwnd, &paintstruct );
+ return 0;
+
+ case WM_CREATE:
+ return 0;
+
+ }
+ return 0;
+}
+
+
+/********************************************************************
+ *
+ * Miscellaneous partially implemented functions.
+ *
+ */
+
+
+HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
+{
+ return hwnd;
+}
+
+
+void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
+{
+ MSG_EndPaint();
+}
+
+int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
+{
+ WND * wndPtr = WIN_FindWndPtr( hdc );
+ int x = rect->left, y = rect->top;
+
+ if (flags & DT_CENTER) x = (rect->left + rect->right) / 2;
+ if (flags & DT_VCENTER) y = (rect->top + rect->bottom) / 2;
+ if (count == -1) count = strlen(str);
+
+ printf( "DrawText: %d,%d '%s'\n", x, y, str );
+ if (wndPtr)
+ {
+ XDrawString( XtDisplay(wndPtr->winWidget),
+ XtWindow(wndPtr->winWidget),
+ DefaultGCOfScreen(XtScreen(wndPtr->winWidget)),
+ x, y, str, count );
+ GlobalUnlock( hdc );
+ }
+}
+
+int MessageBox( HWND hwnd, LPSTR str, LPSTR title, WORD type )
+{
+ printf( "MessageBox: '%s'\n", str );
+}
+
+void MessageBeep( WORD i )
+{
+ printf( "MessageBeep: %d\n", i );
+}
+
+HDC GetDC( HWND hwnd ) { }
+
+HMENU CreateMenu() { }
+
+HMENU GetMenu( HWND hwnd ) { }
+
+BOOL SetMenu( HWND hwnd, HMENU hmenu ) { }
+
+BOOL AppendMenu( HMENU hmenu, WORD flags, WORD id, LPSTR text ) { }
+
+BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom ) { }
+
+HANDLE GetStockObject( int obj ) { }
+
+