Release 980118
Sun Jan 18 17:05:58 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/stackframe.h] [tools/build.c]
Some cleanups in stack frame building.
* [misc/port.c]
Implemented clone() wrapper for libc5 users.
* [scheduler/mutex.c] [scheduler/synchro.c]
Implemented abandoned mutexes.
* [scheduler/process.c] [scheduler/thread.c]
We now create a process and a thread structure as soon as possible
during initialization.
* [scheduler/thread.c] [scheduler/sysdeps.c]
Moved system-specific thread handling to sysdeps.c.
Fri Jan 16 10:45:15 1998 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [graphics/ddraw.c][include/ddraw.h]
Surface handling enhanced. Some stuff already works ;)
* [multimedia/dsound.c][include/dsound.h]
Implemented using the Open Sound System.
Slowly starts to work (sounds terrible for some programs).
* [configure.in][multimedia/audio.c][include/config.h.in]
Added check for OpenSoundSystem, fixed -lXxf86dga check.
Replaced OS #ifdefs by #ifdef HAVE_OSS in mm/audio.c.
* [if1632/relay.c][relay32/relay386.c]
Do not print control characters for 'str' or 'wstr' args.
* [misc/registry.c]
"" seems to equals NULL in keynames. Replace where needed. Seems
to help the win95 regedit.exe...
* [win32/newfns.c]
Implemented QueryPerformance* using gettimeofday(2)
(should be done using the pentium timers probably).
* [tools/ipcl]
Removed useless open_pipe construct.
Sun Jan 11 17:10:02 1998 Huw D M Davies <h.davies1@physics.oxford.ac.uk>
* [objects/region.c] [include/region.h] [graphics/x11drv/clipping.c]
Regions are now internal to Wine. The basis of this code is taken
from the X11 distribution. GetRegionData() is implemented as is
ExtCreateRegion() (without Xforms). CreatePolyPolygonRgn() should
behave correctly now.
* [objects/metafile.c] [graphics/metafiledrv/graphics.c]
[graphics/metafiledrv/init.c] [include/metafile.h]
[include/metafiledrv.h]
Playback of META_CREATEREGION should now work. Implemented recording
of META_CREATEREGION and META_PAINTREGION.
* [graphics/x11drv/graphics.c]
FillRgn() (and therefore its friends) respect logical co-ords.
Wed Jan 7 01:21:45 1998 Steinar Hamre <steinarh@stud.fim.ntnu.no>
* [configure.in] [include/acconfig.h] [tools/build.c]
Now checking whether to use .string or .ascii.
* [configure.in] [include/acconfig.h] [scheduler/critsection.c]
Defining union semun if this is not available from header files.
* [misc/lstr.c]
Moved wine's own header files below <wctype.h> to avoid
parse error on Solaris.
Sun Jan 4 15:38:07 1998 Andrew Taylor <ataylor@cadvision.com>
* [multimedia/mmsystem.c] [multimedia/mmio.c]
Implemented mmioSendMessage and rearranged the mmio
subsystem in terms of this function.
Wed Dec 24 00:51:29 1997 Charles Duffy <cduffy@bigfoot.com>
* [windows/clipboard.c] [relay32/user32.spec]
GetPriorityClipboardFormat32 now has something other than just
a stub. I have no idea if it works (can't test until
SetClipboardData is finished) but HEdit likes things a lot more
this way.
diff --git a/ANNOUNCE b/ANNOUNCE
index aba47d4..e7555fe 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,13 @@
-This is release 980104 of Wine, the MS Windows emulator. This is still a
+This is release 980118 of Wine, the MS Windows emulator. This is still a
developer's only release. There are many bugs and many unimplemented API
features. Most applications still do not work correctly.
Patches should be submitted to "julliard@lrc.epfl.ch". Please don't
forget to include a ChangeLog entry.
-WHAT'S NEW with Wine-980104: (see ChangeLog for details)
- - Beginnings of DirectDraw/DirectSound support.
- - Preliminary threading support based on clone().
+WHAT'S NEW with Wine-980118: (see ChangeLog for details)
+ - New region implementation based on X11 code.
+ - Improvements to DirectDraw and DirectSound.
- Lots of bug fixes.
See the README file in the distribution for installation instructions.
@@ -16,10 +16,10 @@
the release is available at the ftp sites. The sources will be available
from the following locations:
- ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-980104.tar.gz
- ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-980104.tar.gz
- ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-980104.tar.gz
- ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-980104.tar.gz
+ ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-980118.tar.gz
+ ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-980118.tar.gz
+ ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-980118.tar.gz
+ ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-980118.tar.gz
It should also be available from any site that mirrors tsx-11 or sunsite.
diff --git a/ChangeLog b/ChangeLog
index 57e6fb2..65a51a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,93 @@
----------------------------------------------------------------------
+Sun Jan 18 17:05:58 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
+
+ * [include/stackframe.h] [tools/build.c]
+ Some cleanups in stack frame building.
+
+ * [misc/port.c]
+ Implemented clone() wrapper for libc5 users.
+
+ * [scheduler/mutex.c] [scheduler/synchro.c]
+ Implemented abandoned mutexes.
+
+ * [scheduler/process.c] [scheduler/thread.c]
+ We now create a process and a thread structure as soon as possible
+ during initialization.
+
+ * [scheduler/thread.c] [scheduler/sysdeps.c]
+ Moved system-specific thread handling to sysdeps.c.
+
+Fri Jan 16 10:45:15 1998 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+ * [graphics/ddraw.c][include/ddraw.h]
+ Surface handling enhanced. Some stuff already works ;)
+
+ * [multimedia/dsound.c][include/dsound.h]
+ Implemented using the Open Sound System.
+ Slowly starts to work (sounds terrible for some programs).
+
+ * [configure.in][multimedia/audio.c][include/config.h.in]
+ Added check for OpenSoundSystem, fixed -lXxf86dga check.
+ Replaced OS #ifdefs by #ifdef HAVE_OSS in mm/audio.c.
+
+ * [if1632/relay.c][relay32/relay386.c]
+ Do not print control characters for 'str' or 'wstr' args.
+
+ * [misc/registry.c]
+ "" seems to equals NULL in keynames. Replace where needed. Seems
+ to help the win95 regedit.exe...
+
+ * [win32/newfns.c]
+ Implemented QueryPerformance* using gettimeofday(2)
+ (should be done using the pentium timers probably).
+
+ * [tools/ipcl]
+ Removed useless open_pipe construct.
+
+Sun Jan 11 17:10:02 1998 Huw D M Davies <h.davies1@physics.oxford.ac.uk>
+
+ * [objects/region.c] [include/region.h] [graphics/x11drv/clipping.c]
+ Regions are now internal to Wine. The basis of this code is taken
+ from the X11 distribution. GetRegionData() is implemented as is
+ ExtCreateRegion() (without Xforms). CreatePolyPolygonRgn() should
+ behave correctly now.
+
+ * [objects/metafile.c] [graphics/metafiledrv/graphics.c]
+ [graphics/metafiledrv/init.c] [include/metafile.h]
+ [include/metafiledrv.h]
+ Playback of META_CREATEREGION should now work. Implemented recording
+ of META_CREATEREGION and META_PAINTREGION.
+
+ * [graphics/x11drv/graphics.c]
+ FillRgn() (and therefore its friends) respect logical co-ords.
+
+Wed Jan 7 01:21:45 1998 Steinar Hamre <steinarh@stud.fim.ntnu.no>
+
+ * [configure.in] [include/acconfig.h] [tools/build.c]
+ Now checking whether to use .string or .ascii.
+
+ * [configure.in] [include/acconfig.h] [scheduler/critsection.c]
+ Defining union semun if this is not available from header files.
+
+ * [misc/lstr.c]
+ Moved wine's own header files below <wctype.h> to avoid
+ parse error on Solaris.
+
+Sun Jan 4 15:38:07 1998 Andrew Taylor <ataylor@cadvision.com>
+
+ * [multimedia/mmsystem.c] [multimedia/mmio.c]
+ Implemented mmioSendMessage and rearranged the mmio
+ subsystem in terms of this function.
+
+Wed Dec 24 00:51:29 1997 Charles Duffy <cduffy@bigfoot.com>
+
+ * [windows/clipboard.c] [relay32/user32.spec]
+ GetPriorityClipboardFormat32 now has something other than just
+ a stub. I have no idea if it works (can't test until
+ SetClipboardData is finished) but HEdit likes things a lot more
+ this way.
+
+----------------------------------------------------------------------
Sat Jan 3 17:15:56 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [debugger/db_disasm.c]
@@ -149,6 +238,13 @@
* [files/drive.c]
Return correct "CDFS" fsname so Diablo is a bit happier.
+Sun Dec 21 21:45:48 1997 Kevin Cozens <kcozens@interlog.com>
+
+ * [misc/registry.c]
+ Fixed bugs in the routines which read the Windows '95 registry
+ files. Added extra information regarding the format of the Windows
+ '95 registry files.
+
----------------------------------------------------------------------
Fri Dec 19 10:50:46 1997 Douglas Ridgway <ridgway@winehq.com>
@@ -1232,7 +1328,7 @@
Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init,
GetSysColor16, GetSysColor32. Add support for above colors.
-Sun Aug 24 16:22:57 1997 Andrew Taylor <andrew@riscan.com>
+Sun Aug 24 16:22:57 1997 Andrew Taylor <ataylor@cadvision.com>
* [multimedia/mmsystem.c]
Changed mmioDescend to use mmio functions for file I/O, neccessary
@@ -1731,7 +1827,7 @@
* [windows/mdi.c] [windows/win.c]
Replaced WCL lists with WIN_BuildWinArray().
-Mon Jun 9 23:51:16 1997 Andrew Taylor <andrew@riscan.com>
+Mon Jun 9 23:51:16 1997 Andrew Taylor <ataylor@cadvision.com>
* [misc/error.c] [include/windows.h] [if1632/kernel.spec]
Implemented LogParamError, LogError functions.
@@ -1973,7 +2069,7 @@
Another ximage!=bitmap memory layout bug.
All _XinitImageFuncPtrs except one removed.
-Sun Apr 20 17:12:30 1997 Andrew Taylor <andrew@riscan.com>
+Sun Apr 20 17:12:30 1997 Andrew Taylor <ataylor@cadvision.com>
* [multimedia/audio.c]
Fixed some regression bugs.
@@ -2309,7 +2405,7 @@
* [controls/edit.c]
Fix incorrect arg order in LOCAL_Alloc() call.
-Fri Feb 21 18:19:17 1997 Andrew Taylor <andrew@riscan.com>
+Fri Feb 21 18:19:17 1997 Andrew Taylor <ataylor@cadvision.com>
* [multimedia/mmsystem.c] [multimedia/mcistring.c]
Fixed bug related to device IDs returned by multimedia
@@ -2351,7 +2447,7 @@
* [msdos/dosmem.c] [memory/global.c]
Some changes in DOS memory allocation.
-Fri Feb 7 21:46:03 1997 Andrew Taylor <andrew@riscan.com>
+Fri Feb 7 21:46:03 1997 Andrew Taylor <ataylor@cadvision.com>
* [win32/security.c]
Added SID manipulation functions.
@@ -3020,7 +3116,7 @@
* [windows/win.c]
SetWindowWord(): call SetParent on GWW_HWNDPARENT.
-Wed Dec 4 22:03:05 1996 Andrew Taylor <andrew@riscan.com>
+Wed Dec 4 22:03:05 1996 Andrew Taylor <ataylor@cadvision.com>
* [files/dos_fs.c]
Check if buf is NULL before copying string in GetFullPathName32A().
@@ -6870,7 +6966,7 @@
* [controls/edit.c]
Almost rewrote EDIT_GetLineMsg.
-Sat Dec 16 13:51:48 MST 1995 Andrew Taylor <andrew@riscan.com>
+Sat Dec 16 13:51:48 MST 1995 Andrew Taylor <ataylor@cadvision.com>
* [windows/mdi.c]
Fixed MDITile() bug that occurs when 0 windows are present or all
@@ -7883,7 +7979,7 @@
* [loader/ne_image.c]
Preliminary support for iterated segments.
-Sat Aug 19 00:43:04 1995 Andrew Taylor (andrew@riscan.com)
+Sat Aug 19 00:43:04 1995 Andrew Taylor (ataylor@cadvision.com)
* [windows/mapping.c]
In function MAPPING_FixIsotropic(), VportExt[XY] is multiplied by
diff --git a/Make.rules.in b/Make.rules.in
index 5cc35b7..0006fce 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -18,7 +18,7 @@
CC = @CC@
CPP = @CPP@
CFLAGS = @CFLAGS@
-OPTIONS = @OPTIONS@
+OPTIONS = @OPTIONS@ -D_REENTRANT
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
XPM_LIB = -lXpm
diff --git a/configure b/configure
index 20417c6..84d8791 100755
--- a/configure
+++ b/configure
@@ -1990,7 +1990,7 @@
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lXxf86dga -lXext -lX11 $LIBS"
+LIBS="-lXxf86dga $X_LIBS -lXext -lX11 $LIBS"
cat > conftest.$ac_ext <<EOF
#line 1996 "configure"
#include "confdefs.h"
@@ -2018,19 +2018,91 @@
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo Xxf86dga | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
+ cat >> confdefs.h <<\EOF
+#define HAVE_LIBXXF86DGA 1
EOF
-
- LIBS="-lXxf86dga $LIBS"
-
+ X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga"
else
echo "$ac_t""no" 1>&6
fi
+
+echo $ac_n "checking "for Open Sound System"""... $ac_c" 1>&6
+echo "configure:2033: checking "for Open Sound System"" >&5
+if eval "test \"`echo '$''{'ac_cv_c_opensoundsystem'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2038 "configure"
+#include "confdefs.h"
+#include <sys/soundcard.h>
+int main() {
+
+/* check for open sound system and one of the SNDCTL_ defines to be sure */
+#if !defined(OPEN_SOUND_SYSTEM) || !defined(SNDCTL_DSP_STEREO)
+#error No open sound system
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2050: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_opensoundsystem="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_opensoundsystem="no"
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_opensoundsystem" 1>&6
+
+if test "$ac_cv_c_opensoundsystem" = "yes"
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_OSS 1
+EOF
+
+fi
+
+
+echo $ac_n "checking "for union semun"""... $ac_c" 1>&6
+echo "configure:2074: checking "for union semun"" >&5
+if eval "test \"`echo '$''{'ac_cv_c_union_semun'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2079 "configure"
+#include "confdefs.h"
+#include <sys/sem.h>
+int main() {
+union semun foo
+; return 0; }
+EOF
+if { (eval echo configure:2086: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_union_semun="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_union_semun="no"
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_union_semun" 1>&6
+if test "$ac_cv_c_union_semun" = "yes"
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_UNION_SEMUN 1
+EOF
+
+fi
+
if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
@@ -2038,7 +2110,7 @@
then
CFLAGS="$CFLAGS -Wall"
echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
-echo "configure:2042: checking "for gcc strength-reduce bug"" >&5
+echo "configure:2114: checking "for gcc strength-reduce bug"" >&5
if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2046,7 +2118,7 @@
ac_cv_c_gcc_strength_bug="yes"
else
cat > conftest.$ac_ext <<EOF
-#line 2050 "configure"
+#line 2122 "configure"
#include "confdefs.h"
int main(void) {
@@ -2057,7 +2129,7 @@
exit( Array[1] != -2 );
}
EOF
-if { (eval echo configure:2061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2133: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_c_gcc_strength_bug="no"
else
@@ -2080,7 +2152,7 @@
echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
-echo "configure:2084: checking "whether external symbols need an underscore prefix"" >&5
+echo "configure:2156: checking "whether external symbols need an underscore prefix"" >&5
if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2092,14 +2164,14 @@
.long 0
EOF
cat > conftest.$ac_ext <<EOF
-#line 2096 "configure"
+#line 2168 "configure"
#include "confdefs.h"
extern int ac_test;
int main() {
if (ac_test) return 1
; return 0; }
EOF
-if { (eval echo configure:2103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
ac_cv_c_extern_prefix="yes"
else
@@ -2122,25 +2194,66 @@
fi
+echo $ac_n "checking "whether assembler accepts .string"""... $ac_c" 1>&6
+echo "configure:2199: checking "whether assembler accepts .string"" >&5
+if eval "test \"`echo '$''{'ac_cv_c_asm_string'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ saved_libs=$LIBS
+LIBS="conftest_asm.s $LIBS"
+cat > conftest_asm.s <<EOF
+ .string "test"
+EOF
+cat > conftest.$ac_ext <<EOF
+#line 2209 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:2216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ ac_cv_c_asm_string="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_asm_string="no"
+fi
+rm -f conftest*
+LIBS=$saved_libs
+fi
+
+echo "$ac_t""$ac_cv_c_asm_string" 1>&6
+if test "$ac_cv_c_asm_string" = "yes"
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ASM_STRING 1
+EOF
+
+fi
+
+
DLLFLAGS=""
if test "$LIB_TARGET" = "libwine.so.1.0"
then
echo $ac_n "checking "whether we can build a dll"""... $ac_c" 1>&6
-echo "configure:2130: checking "whether we can build a dll"" >&5
+echo "configure:2243: checking "whether we can build a dll"" >&5
if eval "test \"`echo '$''{'ac_cv_c_dll'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0"
cat > conftest.$ac_ext <<EOF
-#line 2137 "configure"
+#line 2250 "configure"
#include "confdefs.h"
int main() {
return 1
; return 0; }
EOF
-if { (eval echo configure:2144: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
ac_cv_c_dll="yes"
else
@@ -2168,12 +2281,12 @@
for ac_func in clone memmove strerror tcgetattr usleep wait4 waitpid
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2172: checking for $ac_func" >&5
+echo "configure:2285: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2177 "configure"
+#line 2290 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2196,7 +2309,7 @@
; return 0; }
EOF
-if { (eval echo configure:2200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2224,17 +2337,17 @@
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2228: checking for $ac_hdr" >&5
+echo "configure:2341: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2233 "configure"
+#line 2346 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2238: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2261,12 +2374,12 @@
done
echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:2265: checking whether stat file-mode macros are broken" >&5
+echo "configure:2378: checking whether stat file-mode macros are broken" >&5
if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2270 "configure"
+#line 2383 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -2317,12 +2430,12 @@
fi
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2321: checking for working const" >&5
+echo "configure:2434: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2326 "configure"
+#line 2439 "configure"
#include "confdefs.h"
int main() {
@@ -2371,7 +2484,7 @@
; return 0; }
EOF
-if { (eval echo configure:2375: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2488: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@@ -2392,12 +2505,12 @@
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2396: checking for ANSI C header files" >&5
+echo "configure:2509: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2401 "configure"
+#line 2514 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -2405,7 +2518,7 @@
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2409: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2522: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2422,7 +2535,7 @@
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2426 "configure"
+#line 2539 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -2440,7 +2553,7 @@
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2444 "configure"
+#line 2557 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -2461,7 +2574,7 @@
:
else
cat > conftest.$ac_ext <<EOF
-#line 2465 "configure"
+#line 2578 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2472,7 +2585,7 @@
exit (0); }
EOF
-if { (eval echo configure:2476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
@@ -2496,12 +2609,12 @@
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2500: checking for size_t" >&5
+echo "configure:2613: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2505 "configure"
+#line 2618 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
diff --git a/configure.in b/configure.in
index abf9119..83da896 100644
--- a/configure.in
+++ b/configure.in
@@ -51,7 +51,33 @@
dnl Check for -lw for Solaris
AC_CHECK_LIB(w,iswalnum)
dnl Check for XFree86 DGA extension
-AC_CHECK_LIB(Xxf86dga,XF86DGAQueryExtension,,,-lXext -lX11)
+AC_CHECK_LIB(Xxf86dga,XF86DGAQueryExtension,AC_DEFINE(HAVE_LIBXXF86DGA) X_PRE_LIBS="$X_PRE_LIBS -lXxf86dga",,$X_LIBS -lXext -lX11)
+
+dnl **** Check for Open Sound System ****
+
+AC_CACHE_CHECK("for Open Sound System",
+ ac_cv_c_opensoundsystem,
+ AC_TRY_COMPILE([#include <sys/soundcard.h>],[
+/* check for open sound system and one of the SNDCTL_ defines to be sure */
+#if !defined(OPEN_SOUND_SYSTEM) || !defined(SNDCTL_DSP_STEREO)
+#error No open sound system
+#endif
+],ac_cv_c_opensoundsystem="yes",ac_cv_c_opensoundsystem="no"))
+
+if test "$ac_cv_c_opensoundsystem" = "yes"
+then
+ AC_DEFINE(HAVE_OSS)
+fi
+
+dnl **** Check for union semun ****
+
+AC_CACHE_CHECK("for union semun", ac_cv_c_union_semun,
+ AC_TRY_COMPILE([#include <sys/sem.h>],[union semun foo],
+ ac_cv_c_union_semun="yes", ac_cv_c_union_semun="no"))
+if test "$ac_cv_c_union_semun" = "yes"
+then
+ AC_DEFINE(HAVE_UNION_SEMUN)
+fi
dnl **** If ln -s doesn't work, use cp instead ****
if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi
@@ -98,6 +124,22 @@
AC_DEFINE(NEED_UNDERSCORE_PREFIX)
fi
+dnl **** Check for .string in assembler ****
+
+AC_CACHE_CHECK("whether assembler accepts .string",
+ ac_cv_c_asm_string,
+[saved_libs=$LIBS
+LIBS="conftest_asm.s $LIBS"
+cat > conftest_asm.s <<EOF
+ .string "test"
+EOF
+AC_TRY_LINK(,,ac_cv_c_asm_string="yes",ac_cv_c_asm_string="no")
+LIBS=$saved_libs])
+if test "$ac_cv_c_asm_string" = "yes"
+then
+ AC_DEFINE(HAVE_ASM_STRING)
+fi
+
dnl **** Check for working dll ****
DLLFLAGS=""
diff --git a/controls/menu.c b/controls/menu.c
index ee5a098..e70533d 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1837,7 +1837,7 @@
{
if( menu->wFlags & MF_SYSMENU )
{
- PostMessage16( pmt->hOwnerWnd, WM_SYSCOMMAND, item->hSubMenu,
+ PostMessage16( pmt->hOwnerWnd, WM_SYSCOMMAND, item->wID,
MAKELPARAM((INT16)pmt->pt.x, (INT16)pmt->pt.y) );
}
else
diff --git a/debugger/break.c b/debugger/break.c
index d842f50..b332ade 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -347,9 +347,7 @@
if (pModule->flags & NE_FFLAGS_WIN32) /* PE module */
{
- PE_MODREF *pem;
- if (!pCurrentProcess) continue;
- pem = pCurrentProcess->modref_list;
+ PE_MODREF *pem = PROCESS_Current()->modref_list;
while (pem)
{
if (pem->module == pModule->module32) break;
diff --git a/debugger/hash.c b/debugger/hash.c
index acf281f..ba87473 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -803,7 +803,7 @@
void **functions;
const char **names;
- PE_MODREF *pem = pCurrentProcess->modref_list;
+ PE_MODREF *pem = PROCESS_Current()->modref_list;
while (pem && (pem->module != hModule)) pem = pem->next;
if (!pem) return;
exports = pem->pe_export;
diff --git a/files/drive.c b/files/drive.c
index d5a8a86..7aca8b6 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -949,7 +949,7 @@
if (DRIVE_GetType(drive)==TYPE_CDROM)
lstrcpyn32A( fsname, "CDFS", fsname_len );
else
- lstrcpyn32A( fsname, "FAT16", fsname_len );
+ lstrcpyn32A( fsname, "FAT", fsname_len );
}
return TRUE;
}
diff --git a/graphics/ddraw.c b/graphics/ddraw.c
index 7248690..d2fd0bd 100644
--- a/graphics/ddraw.c
+++ b/graphics/ddraw.c
@@ -1,6 +1,38 @@
/* DirectDraw
*
- * Copyright 1997 Marcus Meissner
+ * Copyright 1997,1998 Marcus Meissner
+ */
+/* When DirectVideo mode is enabled you can no longer use 'normal' X
+ * applications nor can you switch to a virtual console. Also, enabling
+ * only works, if you have switched to the screen where the application
+ * is running.
+ * Some ways to debug this stuff are:
+ * - A terminal connected to the serial port. Can be bought used for cheap.
+ * (This is the method I am using.)
+ * - Another machine connected over some kind of network.
+ */
+/* Progress on following programs:
+ *
+ * - Diablo:
+ * The movies play. The game doesn't yet. No sound. (Needs clone())
+ *
+ * - WingCommander 4 (not 5!) / Win95 Patch:
+ * The intromovie plays, in 8 bit mode (to reconfigure wc4, run wine
+ * "wc4w.exe -I"). The 16bit mode looks broken, but I think this is due to
+ * my Matrox Mystique which uses 565 (rgb) colorweight instead of the usual
+ * 555. Specifying it in DDPIXELFORMAT didn't help.
+ * Requires to be run in 640x480xdepth mode (doesn't seem to heed
+ * DDSURFACEDESC.lPitch).
+ *
+ * - Monkey Island 3:
+ * Goes to the easy/hard selection screen, then hangs due to not MT safe
+ * XLibs.
+ *
+ * - Dark Angel Demo (Some shoot and run game):
+ * The graphics stuff works fine, you can play it.
+ *
+ * - XvT:
+ * Doesn't work, I am still unsure why not.
*/
#include "config.h"
@@ -8,6 +40,7 @@
#include <unistd.h>
#include <assert.h>
#include <X11/Xlib.h>
+#include <sys/signal.h>
#include "windows.h"
#include "winerror.h"
@@ -30,7 +63,7 @@
static HRESULT WINAPI IDirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE,REFIID,LPVOID*);
static HRESULT WINAPI IDirectDraw_QueryInterface(LPDIRECTDRAW this,REFIID refiid,LPVOID *obj);
static HRESULT WINAPI IDirectDraw2_CreateSurface( LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk);
-static HRESULT WINAPI IDirectDraw_CreateSurface( LPDIRECTDRAW this,LPDDSURFACEDESC *lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk);
+static HRESULT WINAPI IDirectDraw_CreateSurface( LPDIRECTDRAW this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk);
static struct IDirectDrawSurface2_VTable dds2vt;
static struct IDirectDrawSurface_VTable ddsvt;
@@ -39,8 +72,8 @@
DirectDrawEnumerate32A(LPDDENUMCALLBACK32A ddenumproc,LPVOID data) {
fprintf(stderr,"DirectDrawEnumerateA(%p,%p).\n",ddenumproc,data);
ddenumproc(0,"WINE Display","display",data);
- ddenumproc(&IID_IDirectDraw,"WINE DirectDraw","directdraw",data);
- ddenumproc(&IID_IDirectDrawPalette,"WINE DirectPalette","directpalette",data);
+ ddenumproc((void*)&IID_IDirectDraw,"WINE DirectDraw","directdraw",data);
+ ddenumproc((void*)&IID_IDirectDrawPalette,"WINE DirectPalette","directpalette",data);
return 0;
}
@@ -52,10 +85,125 @@
#ifdef HAVE_LIBXXF86DGA
+static void _dump_DDSCAPS(DWORD flagmask) {
+ int i;
+ const struct {
+ DWORD mask;
+ char *name;
+ } flags[] = {
+#define FE(x) { x, #x},
+ FE(DDSCAPS_3D)
+ FE(DDSCAPS_ALPHA)
+ FE(DDSCAPS_BACKBUFFER)
+ FE(DDSCAPS_COMPLEX)
+ FE(DDSCAPS_FLIP)
+ FE(DDSCAPS_FRONTBUFFER)
+ FE(DDSCAPS_OFFSCREENPLAIN)
+ FE(DDSCAPS_OVERLAY)
+ FE(DDSCAPS_PALETTE)
+ FE(DDSCAPS_PRIMARYSURFACE)
+ FE(DDSCAPS_PRIMARYSURFACELEFT)
+ FE(DDSCAPS_SYSTEMMEMORY)
+ FE(DDSCAPS_TEXTURE)
+ FE(DDSCAPS_3DDEVICE)
+ FE(DDSCAPS_VIDEOMEMORY)
+ FE(DDSCAPS_VISIBLE)
+ FE(DDSCAPS_WRITEONLY)
+ FE(DDSCAPS_ZBUFFER)
+ FE(DDSCAPS_OWNDC)
+ FE(DDSCAPS_LIVEVIDEO)
+ FE(DDSCAPS_HWCODEC)
+ FE(DDSCAPS_MODEX)
+ FE(DDSCAPS_MIPMAP)
+ FE(DDSCAPS_ALLOCONLOAD)
+ };
+ for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+ if (flags[i].mask & flagmask)
+ fprintf(stderr,"%s ",flags[i].name);
+}
+
+static void _dump_DDCAPS(DWORD flagmask) {
+ int i;
+ const struct {
+ DWORD mask;
+ char *name;
+} flags[] = {
+#define FE(x) { x, #x},
+ FE(DDCAPS_3D)
+ FE(DDCAPS_ALIGNBOUNDARYDEST)
+ FE(DDCAPS_ALIGNSIZEDEST)
+ FE(DDCAPS_ALIGNBOUNDARYSRC)
+ FE(DDCAPS_ALIGNSIZESRC)
+ FE(DDCAPS_ALIGNSTRIDE)
+ FE(DDCAPS_BLT)
+ FE(DDCAPS_BLTQUEUE)
+ FE(DDCAPS_BLTFOURCC)
+ FE(DDCAPS_BLTSTRETCH)
+ FE(DDCAPS_GDI)
+ FE(DDCAPS_OVERLAY)
+ FE(DDCAPS_OVERLAYCANTCLIP)
+ FE(DDCAPS_OVERLAYFOURCC)
+ FE(DDCAPS_OVERLAYSTRETCH)
+ FE(DDCAPS_PALETTE)
+ FE(DDCAPS_PALETTEVSYNC)
+ FE(DDCAPS_READSCANLINE)
+ FE(DDCAPS_STEREOVIEW)
+ FE(DDCAPS_VBI)
+ FE(DDCAPS_ZBLTS)
+ FE(DDCAPS_ZOVERLAYS)
+ FE(DDCAPS_COLORKEY)
+ FE(DDCAPS_ALPHA)
+ FE(DDCAPS_COLORKEYHWASSIST)
+ FE(DDCAPS_NOHARDWARE)
+ FE(DDCAPS_BLTCOLORFILL)
+ FE(DDCAPS_BANKSWITCHED)
+ FE(DDCAPS_BLTDEPTHFILL)
+ FE(DDCAPS_CANCLIP)
+ FE(DDCAPS_CANCLIPSTRETCHED)
+ FE(DDCAPS_CANBLTSYSMEM)
+ };
+ for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+ if (flags[i].mask & flagmask)
+ fprintf(stderr,"%s ",flags[i].name);
+}
+
+static void _dump_DDSD(DWORD flagmask) {
+ int i;
+ const struct {
+ DWORD mask;
+ char *name;
+ } flags[] = {
+ FE(DDSD_CAPS)
+ FE(DDSD_HEIGHT)
+ FE(DDSD_WIDTH)
+ FE(DDSD_PITCH)
+ FE(DDSD_BACKBUFFERCOUNT)
+ FE(DDSD_ZBUFFERBITDEPTH)
+ FE(DDSD_ALPHABITDEPTH)
+ FE(DDSD_PIXELFORMAT)
+ FE(DDSD_CKDESTOVERLAY)
+ FE(DDSD_CKDESTBLT)
+ FE(DDSD_CKSRCOVERLAY)
+ FE(DDSD_CKSRCBLT)
+ FE(DDSD_MIPMAPCOUNT)
+ FE(DDSD_REFRESHRATE)
+ };
+ for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+ if (flags[i].mask & flagmask)
+ fprintf(stderr,"%s ",flags[i].name);
+}
+
static int _getpixelformat(LPDIRECTDRAW ddraw,LPDDPIXELFORMAT pf) {
+ static XVisualInfo *vi;
+ XVisualInfo vt;
+ int nitems;
+
+ if (!vi)
+ vi = XGetVisualInfo(display,VisualNoMask,&vt,&nitems);
+
pf->dwFourCC = mmioFOURCC('R','G','B',' ');
if (ddraw->d.depth==8) {
- pf->dwFlags = DDPF_RGB|DDPF_PALETTEINDEXEDTO8;
+ pf->dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
pf->x.dwRGBBitCount = 8;
pf->y.dwRBitMask = 0;
pf->z.dwGBitMask = 0;
@@ -63,11 +211,11 @@
return 0;
}
if (ddraw->d.depth==16) {
- pf->dwFlags = DDPF_RGB;
- pf->x.dwRGBBitCount = 16;
- pf->y.dwRBitMask = 0x0000f800;
- pf->z.dwGBitMask = 0x000007e0;
- pf->xx.dwBBitMask = 0x0000001f;
+ pf->dwFlags = DDPF_RGB;
+ pf->x.dwRGBBitCount = 16;
+ pf->y.dwRBitMask = vi[0].red_mask;
+ pf->z.dwGBitMask = vi[0].green_mask;
+ pf->xx.dwBBitMask = vi[0].blue_mask;
return 0;
}
fprintf(stderr,"_getpixelformat:oops?\n");
@@ -78,10 +226,12 @@
static HRESULT WINAPI IDirectDrawSurface_Lock(
LPDIRECTDRAWSURFACE this,LPRECT32 lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE32 hnd
) {
- dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Lock(%p,%p,%08lx,%08lx)\n",
+ /*
+ fprintf(stderr,"IDirectDrawSurface(%p)->Lock(%p,%p,%08lx,%08lx)\n",
this,lprect,lpddsd,flags,(DWORD)hnd
);
fprintf(stderr,".");
+ */
if (lprect) {
/*
fprintf(stderr," lprect: %dx%d-%dx%d\n",
@@ -103,10 +253,10 @@
static HRESULT WINAPI IDirectDrawSurface2_Lock(
LPDIRECTDRAWSURFACE2 this,LPRECT32 lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE32 hnd
) {
- dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Lock(%p,%p,%08lx,%08lx)\n",
+ fprintf(stderr,"IDirectDrawSurface2(%p)->Lock(%p,%p,%08lx,%08lx)\n",
this,lprect,lpddsd,flags,(DWORD)hnd
);
- fprintf(stderr,".");
+ /*fprintf(stderr,".");*/
if (lprect) {
/*
fprintf(stderr," lprect: %dx%d-%dx%d\n",
@@ -128,30 +278,47 @@
static HRESULT WINAPI IDirectDrawSurface_Unlock(
LPDIRECTDRAWSURFACE this,LPVOID surface
) {
- dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Unlock(%p)\n",this,surface);
+ dprintf_relay(stderr,"IDirectDrawSurface(%p)->Unlock(%p)\n",this,surface);
return 0;
}
static HRESULT WINAPI IDirectDrawSurface_Flip(
LPDIRECTDRAWSURFACE this,LPDIRECTDRAWSURFACE flipto,DWORD dwFlags
) {
- fprintf(stderr,"IDirectDrawSurface(%p)->Flip(%p,%08lx),STUB\n",this,flipto,dwFlags);
- if (flipto) {
- XF86DGASetViewPort(display,DefaultScreen(display),0,flipto->fb_height);
- } else {
- /* FIXME: flip through attached surfaces */
- XF86DGASetViewPort(display,DefaultScreen(display),0,this->fb_height);
+/* fprintf(stderr,"IDirectDrawSurface(%p)->Flip(%p,%08lx),STUB\n",this,flipto,dwFlags);*/
+ if (!flipto) {
+ if (this->backbuffer)
+ flipto = this->backbuffer;
+ else
+ flipto = this;
}
- while (!XF86DGAViewPortChanged(display,DefaultScreen(display),1)) {
- }
- fprintf(stderr,"flipped to new height %ld\n",flipto->fb_height);
+/* fprintf(stderr,"f>%ld",flipto->fb_height);*/
+ XF86DGASetViewPort(display,DefaultScreen(display),0,flipto->fb_height);
+ if (flipto->palette && flipto->palette->cm)
+ XF86DGAInstallColormap(display,DefaultScreen(display),flipto->palette->cm);
+ while (!XF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
+ fprintf(stderr,"w");
+ }
+ /* is this a good idea ? */
+ if (flipto!=this) {
+ int tmp;
+ LPVOID ptmp;
+
+ tmp = this->fb_height;
+ this->fb_height = flipto->fb_height;
+ flipto->fb_height = tmp;
+
+ ptmp = this->surface;
+ this->surface = flipto->surface;
+ flipto->surface = ptmp;
+ }
return 0;
}
static HRESULT WINAPI IDirectDrawSurface2_Unlock(
LPDIRECTDRAWSURFACE2 this,LPVOID surface
) {
- dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Unlock(%p)\n",this,surface);
+ dprintf_relay(stderr,"IDirectDrawSurface2(%p)->Unlock(%p)\n",this,surface);
return 0;
}
@@ -213,38 +380,43 @@
static HRESULT WINAPI IDirectDrawSurface_GetCaps(
LPDIRECTDRAWSURFACE this,LPDDSCAPS caps
) {
- fprintf(stderr,"IDirectDrawSurface(%p)->GetCaps(%p),stub!\n",this,caps);
- caps->dwCaps = 0; /* we cannot do anything */
+ fprintf(stderr,"IDirectDrawSurface(%p)->GetCaps(%p)\n",this,caps);
+ caps->dwCaps = DDCAPS_PALETTE; /* probably more */
return 0;
}
static HRESULT WINAPI IDirectDrawSurface_GetSurfaceDesc(
LPDIRECTDRAWSURFACE this,LPDDSURFACEDESC ddsd
-) {
+) {
fprintf(stderr,"IDirectDrawSurface(%p)->GetSurfaceDesc(%p)\n",this,ddsd);
- if (ddsd->dwFlags & DDSD_CAPS)
- ddsd->ddsCaps.dwCaps = 0;
- if (ddsd->dwFlags & DDSD_BACKBUFFERCOUNT)
- ddsd->dwBackBufferCount = 1;
- if (ddsd->dwFlags & DDSD_HEIGHT)
- ddsd->dwHeight = this->height;
- if (ddsd->dwFlags & DDSD_WIDTH)
- ddsd->dwHeight = this->width;
- ddsd->dwFlags &= ~(DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_HEIGHT|DDSD_WIDTH);
- if (ddsd->dwFlags)
- fprintf(stderr," ddsd->flags is 0x%08lx\n",ddsd->dwFlags);
+ fprintf(stderr," flags: ");
+ _dump_DDSD(ddsd->dwFlags);
+ fprintf(stderr,"\n");
+
+ ddsd->dwFlags |= DDSD_PIXELFORMAT|DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_HEIGHT|DDSD_WIDTH;
+ ddsd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
+ ddsd->dwBackBufferCount = 1;
+ ddsd->dwHeight = this->height;
+ ddsd->dwWidth = this->width;
+ ddsd->lPitch = this->lpitch;
+ if (this->backbuffer)
+ ddsd->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP;
+ _getpixelformat(this->ddraw,&(ddsd->ddpfPixelFormat));
+
return 0;
}
static ULONG WINAPI IDirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE this) {
- dprintf_relay(stddeb,"IDirectDrawSurface(%p)->AddRef()\n",this);
+ dprintf_relay(stderr,"IDirectDrawSurface(%p)->AddRef()\n",this);
return ++(this->ref);
}
static ULONG WINAPI IDirectDrawSurface_Release(LPDIRECTDRAWSURFACE this) {
- dprintf_relay(stddeb,"IDirectDrawSurface(%p)->Release()\n",this);
+ dprintf_relay(stderr,"IDirectDrawSurface(%p)->Release()\n",this);
if (!--(this->ref)) {
this->ddraw->lpvtbl->fnRelease(this->ddraw);
+ /* clear out of surface list */
+ this->ddraw->d.vpmask &= ~(1<<(this->fb_height/this->ddraw->d.fb_height));
HeapFree(GetProcessHeap(),0,this);
return 0;
}
@@ -252,14 +424,15 @@
}
static ULONG WINAPI IDirectDrawSurface2_AddRef(LPDIRECTDRAWSURFACE2 this) {
- dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->AddRef()\n",this);
+ dprintf_relay(stderr,"IDirectDrawSurface2(%p)->AddRef()\n",this);
return ++(this->ref);
}
static ULONG WINAPI IDirectDrawSurface2_Release(LPDIRECTDRAWSURFACE2 this) {
- dprintf_relay(stddeb,"IDirectDrawSurface2(%p)->Release()\n",this);
+ dprintf_relay(stderr,"IDirectDrawSurface2(%p)->Release()\n",this);
if (!--(this->ref)) {
this->ddraw->lpvtbl->fnRelease(this->ddraw);
+ this->ddraw->d.vpmask &= ~(1<<(this->fb_height/this->ddraw->d.fb_height));
HeapFree(GetProcessHeap(),0,this);
return 0;
}
@@ -269,30 +442,28 @@
static HRESULT WINAPI IDirectDrawSurface2_GetAttachedSurface(
LPDIRECTDRAWSURFACE2 this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE2 *lpdsf
) {
- DDSURFACEDESC ddsfd;
- IUnknown unk;
-
- /* DOES NOT CREATE THEM, but uses the ones already attached to this
- * surface
- */
fprintf(stderr,"IDirectDrawSurface2(%p)->GetAttachedSurface(%p,%p)\n",this,lpddsd,lpdsf);
- /* FIXME: not correct */
- IDirectDraw2_CreateSurface((LPDIRECTDRAW2)this->ddraw,&ddsfd,(LPDIRECTDRAWSURFACE*)lpdsf,&unk);
-
- lpddsd->dwCaps = 0;
+ fprintf(stderr," caps ");_dump_DDSCAPS(lpddsd->dwCaps);fprintf(stderr,"\n");
+ if (!(lpddsd->dwCaps & DDSCAPS_BACKBUFFER)) {
+ fprintf(stderr,"whoops, can only handle backbuffers for now\n");
+ return E_FAIL;
+ }
+ /* FIXME: should handle more than one backbuffer */
+ *lpdsf = this->backbuffer;
return 0;
}
static HRESULT WINAPI IDirectDrawSurface_GetAttachedSurface(
LPDIRECTDRAWSURFACE this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE *lpdsf
) {
- LPDDSURFACEDESC lpddsfd;
- IUnknown unk;
-
fprintf(stderr,"IDirectDrawSurface(%p)->GetAttachedSurface(%p,%p)\n",this,lpddsd,lpdsf);
- /* FIXME: not correct */
- IDirectDraw_CreateSurface(this->ddraw,&lpddsfd,lpdsf,&unk);
- lpddsd->dwCaps = 0;
+ fprintf(stderr," caps ");_dump_DDSCAPS(lpddsd->dwCaps);fprintf(stderr,"\n");
+ if (!(lpddsd->dwCaps & DDSCAPS_BACKBUFFER)) {
+ fprintf(stderr,"whoops, can only handle backbuffers for now\n");
+ return E_FAIL;
+ }
+ /* FIXME: should handle more than one backbuffer */
+ *lpdsf = this->backbuffer;
return 0;
}
@@ -302,8 +473,7 @@
fprintf(stderr,"IDirectDrawSurface(%p)->Initialize(%p,%p)\n",
this,ddraw,lpdsfd
);
- fprintf(stderr," dwFlags is %08lx\n",lpdsfd->dwFlags);
- return 0;
+ return DDERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectDrawSurface_GetPixelFormat(
@@ -340,45 +510,45 @@
}
static struct IDirectDrawSurface2_VTable dds2vt = {
- 1/*IDirectDrawSurface2_QueryInterface*/,
+ (void*)1/*IDirectDrawSurface2_QueryInterface*/,
IDirectDrawSurface2_AddRef,
IDirectDrawSurface2_Release,
- 4,
- 5,
- 6/*IDirectDrawSurface_Blt*/,
- 7/*IDirectDrawSurface_BltBatch*/,
- 8,
- 9,
+ (void*)4,
+ (void*)5,
+ (void*)6/*IDirectDrawSurface_Blt*/,
+ (void*)7/*IDirectDrawSurface_BltBatch*/,
+ (void*)8,
+ (void*)9,
IDirectDrawSurface2_EnumAttachedSurfaces,
- 11,
- 12,
+ (void*)11,
+ (void*)12,
IDirectDrawSurface2_GetAttachedSurface,
- 14,
- 15/*IDirectDrawSurface_GetCaps*/,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23/*IDirectDrawSurface_GetSurfaceDesc*/,
- 24,
- 25,
+ (void*)14,
+ (void*)15/*IDirectDrawSurface_GetCaps*/,
+ (void*)16,
+ (void*)17,
+ (void*)18,
+ (void*)19,
+ (void*)20,
+ (void*)21,
+ (void*)22,
+ (void*)23/*IDirectDrawSurface_GetSurfaceDesc*/,
+ (void*)24,
+ (void*)25,
IDirectDrawSurface2_Lock,
- 27,
- 28,
- 29,
- 30,
- 31,
+ (void*)27,
+ (void*)28,
+ (void*)29,
+ (void*)30,
+ (void*)31,
IDirectDrawSurface2_SetPalette,
IDirectDrawSurface2_Unlock,
- 34,
- 35,
- 36,
- 37,
- 38,
- 39,
+ (void*)34,
+ (void*)35,
+ (void*)36,
+ (void*)37,
+ (void*)38,
+ (void*)39,
};
@@ -408,61 +578,96 @@
IDirectDrawSurface_QueryInterface,
IDirectDrawSurface_AddRef,
IDirectDrawSurface_Release,
- 4,
- 5,
+ (void*)4,
+ (void*)5,
IDirectDrawSurface_Blt,
IDirectDrawSurface_BltBatch,
IDirectDrawSurface_BltFast,
- 9,
- 10,
- 11,
+ (void*)9,
+ (void*)10,
+ (void*)11,
IDirectDrawSurface_Flip,
IDirectDrawSurface_GetAttachedSurface,
IDirectDrawSurface_GetBltStatus,
IDirectDrawSurface_GetCaps,
- 16,
- 17,
+ (void*)16,
+ (void*)17,
IDirectDrawSurface_GetDC,
- 19,
+ (void*)19,
IDirectDrawSurface_GetOverlayPosition,
- 21,
+ (void*)21,
IDirectDrawSurface_GetPixelFormat,
IDirectDrawSurface_GetSurfaceDesc,
IDirectDrawSurface_Initialize,
- 25,
+ (void*)25,
IDirectDrawSurface_Lock,
- 27,
- 28,
- 29,
- 30,
- 31,
+ (void*)27,
+ (void*)28,
+ (void*)29,
+ (void*)30,
+ (void*)31,
IDirectDrawSurface_SetPalette,
IDirectDrawSurface_Unlock,
- 34,
- 35,
- 36,
+ (void*)34,
+ (void*)35,
+ (void*)36,
};
static HRESULT WINAPI IDirectDraw_CreateSurface(
- LPDIRECTDRAW this,LPDDSURFACEDESC *lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
+ LPDIRECTDRAW this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
) {
+ int i;
+
fprintf(stderr,"IDirectDraw(%p)->CreateSurface(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
- *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawSurface));
+ fprintf(stderr," [w=%ld,h=%ld,flags ",lpddsd->dwWidth,lpddsd->dwHeight);
+ _dump_DDSD(lpddsd->dwFlags);
+ fprintf(stderr,"caps ");_dump_DDSCAPS(lpddsd->ddsCaps.dwCaps);
+ fprintf(stderr,"]\n");
+
+ *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
this->lpvtbl->fnAddRef(this);
(*lpdsf)->ref = 1;
(*lpdsf)->lpvtbl = &ddsvt;
- (*lpdsf)->surface = this->d.fb_addr+(this->d.current_height*this->d.fb_width*this->d.depth/8);
- (*lpdsf)->fb_height = this->d.current_height; /* for setviewport */
- this->d.current_height += this->d.fb_height;
+ for (i=0;i<32;i++)
+ if (!(this->d.vpmask & (1<<i)))
+ break;
+ fprintf(stderr,"using viewport %d for a primary surface\n",i);
+ /* if i == 32 or maximum ... return error */
+ this->d.vpmask|=(1<<i);
+ (*lpdsf)->surface = this->d.fb_addr+((i*this->d.vp_height)*this->d.fb_width*this->d.depth/8);
+ (*lpdsf)->fb_height = i*this->d.fb_height;
+
(*lpdsf)->width = this->d.width;
(*lpdsf)->height = this->d.height;
(*lpdsf)->ddraw = this;
(*lpdsf)->lpitch = this->d.fb_width*this->d.depth/8;
- *lpddsd = (LPDDSURFACEDESC)HeapAlloc(GetProcessHeap(),0,sizeof(DDSURFACEDESC));
- (*lpddsd)->dwWidth = this->d.width;
- (*lpddsd)->dwHeight = this->d.height;
- (*lpddsd)->lPitch = this->d.fb_width*this->d.depth/8;
- (*lpddsd)->ddsCaps.dwCaps = 0;
+ (*lpdsf)->backbuffer = NULL;
+ if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
+ LPDIRECTDRAWSURFACE back;
+
+ if (lpddsd->dwBackBufferCount>1)
+ fprintf(stderr,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
+
+ (*lpdsf)->backbuffer = back = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
+ this->lpvtbl->fnAddRef(this);
+ back->ref = 1;
+ back->lpvtbl = &ddsvt;
+ for (i=0;i<32;i++)
+ if (!(this->d.vpmask & (1<<i)))
+ break;
+ fprintf(stderr,"using viewport %d for backbuffer\n",i);
+ /* if i == 32 or maximum ... return error */
+ this->d.vpmask|=(1<<i);
+ back->surface = this->d.fb_addr+((i*this->d.vp_height)*this->d.fb_width*this->d.depth/8);
+ back->fb_height = i*this->d.fb_height;
+
+ back->width = this->d.width;
+ back->height = this->d.height;
+ back->ddraw = this;
+ back->lpitch = this->d.fb_width*this->d.depth/8;
+ back->backbuffer = NULL; /* does not have a backbuffer, it is
+ * one! */
+ }
return 0;
}
@@ -477,35 +682,85 @@
static HRESULT WINAPI IDirectDraw2_CreateSurface(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
) {
+ int i;
+
fprintf(stderr,"IDirectDraw2(%p)->CreateSurface(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
- *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawSurface));
+ *lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
this->lpvtbl->fnAddRef(this);
(*lpdsf)->ref = 1;
(*lpdsf)->lpvtbl = &ddsvt;
- (*lpdsf)->surface = this->d.fb_addr+(this->d.current_height*this->d.fb_width*this->d.depth/8);
+
+ for (i=0;i<32;i++)
+ if (!(this->d.vpmask & (1<<i)))
+ break;
+ fprintf(stderr,"using viewport %d for primary\n",i);
+ /* if i == 32 or maximum ... return error */
+ this->d.vpmask|=(1<<i);
+ (*lpdsf)->surface = this->d.fb_addr+((i*this->d.fb_height)*this->d.fb_width*this->d.depth/8);
(*lpdsf)->width = this->d.width;
(*lpdsf)->height = this->d.height;
(*lpdsf)->ddraw = (LPDIRECTDRAW)this;
- (*lpdsf)->fb_height = this->d.current_height;
+ (*lpdsf)->fb_height = i*this->d.fb_height;
(*lpdsf)->lpitch = this->d.fb_width*this->d.depth/8;
- this->d.current_height += this->d.fb_height;
- lpddsd->dwWidth = this->d.width;
- lpddsd->dwHeight = this->d.height;
- lpddsd->lPitch = this->d.fb_width*this->d.depth/8;
- lpddsd->ddsCaps.dwCaps = 0;
+ (*lpdsf)->backbuffer = NULL;
+ if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
+ LPDIRECTDRAWSURFACE back;
+
+ if (lpddsd->dwBackBufferCount>1)
+ fprintf(stderr,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
+
+ (*lpdsf)->backbuffer = back = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface2));
+ this->lpvtbl->fnAddRef(this);
+ back->ref = 1;
+ back->lpvtbl = &ddsvt;
+ for (i=0;i<32;i++)
+ if (!(this->d.vpmask & (1<<i)))
+ break;
+ fprintf(stderr,"using viewport %d for backbuffer\n",i);
+ /* if i == 32 or maximum ... return error */
+ this->d.vpmask|=(1<<i);
+ back->surface = this->d.fb_addr+((i*this->d.vp_height)*this->d.fb_width*this->d.depth/8);
+ back->fb_height = i*this->d.fb_height;
+
+ back->width = this->d.width;
+ back->height = this->d.height;
+ back->ddraw = (LPDIRECTDRAW)this;
+ back->lpitch = this->d.fb_width*this->d.depth/8;
+ back->backbuffer = NULL; /* does not have a backbuffer, it is
+ * one! */
+ }
return 0;
}
static HRESULT WINAPI IDirectDraw_SetCooperativeLevel(
- LPDIRECTDRAW this,HWND32 hwnd,DWORD x
+ LPDIRECTDRAW this,HWND32 hwnd,DWORD cooplevel
) {
+ int i;
+ const struct {
+ int mask;
+ char *name;
+ } flagmap[] = {
+ FE(DDSCL_FULLSCREEN)
+ FE(DDSCL_ALLOWREBOOT)
+ FE(DDSCL_NOWINDOWCHANGES)
+ FE(DDSCL_NORMAL)
+ FE(DDSCL_ALLOWMODEX)
+ FE(DDSCL_EXCLUSIVE)
+ };
fprintf(stderr,"IDirectDraw(%p)->SetCooperativeLevel(%08lx,%08lx),stub!\n",
- this,(DWORD)hwnd,x
+ this,(DWORD)hwnd,cooplevel
);
+ fprintf(stderr," cooperative level ");
+ for (i=0;i<sizeof(flagmap)/sizeof(flagmap[0]);i++)
+ if (flagmap[i].mask & cooplevel)
+ fprintf(stderr,"%s ",flagmap[i].name);
+ fprintf(stderr,"\n");
this->d.mainwindow = hwnd;
return 0;
}
+extern BOOL32 SIGNAL_InitEmulator(void);
+
static HRESULT WINAPI IDirectDraw_SetDisplayMode(
LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
) {
@@ -535,9 +790,18 @@
if (this->d.fb_height < height)
this->d.fb_height = height;
this->d.depth = depth;
+
+ /* FIXME: this function OVERWRITES several signal handlers.
+ * can we save them? and restore them later? In a way that
+ * it works for the library too?
+ */
XF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
+/* FIXME: can't call this in winelib... so comment only in for debugging.
+ SIGNAL_InitEmulator();
+ */
return 0;
}
+
static HRESULT WINAPI IDirectDraw_GetCaps(
LPDIRECTDRAW this,LPDDCAPS caps1,LPDDCAPS caps2
) {
@@ -560,7 +824,10 @@
static struct IDirectDrawClipper_VTable ddclipvt = {
- 1,2,3,4,5,6,0x10007,8,9
+ (void*)1,
+ (void*)2,(void*)3,(void*)4,(void*)5,
+ (void*)6,
+ (void*)7,(void*)8,(void*)9
};
static HRESULT WINAPI IDirectDraw_CreateClipper(
@@ -569,7 +836,7 @@
fprintf(stderr,"IDirectDraw(%p)->CreateClipper(%08lx,%p,%p),stub!\n",
this,x,lpddclip,lpunk
);
- *lpddclip = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawClipper));
+ *lpddclip = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
(*lpddclip)->ref = 1;
(*lpddclip)->lpvtbl = &ddclipvt;
return 0;
@@ -590,17 +857,24 @@
XColor xc;
int i;
+/*
fprintf(stderr,"IDirectDrawPalette(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
this,x,start,end,palent
);
+ */
if (!this->cm) /* should not happen */ {
fprintf(stderr,"no colormap in SetEntries???\n");
return DDERR_GENERIC;
}
+/* FIXME: free colorcells instead of freeing whole map */
XFreeColormap(display,this->cm);
this->cm = XCreateColormap(display,DefaultRootWindow(display),DefaultVisual(display,DefaultScreen(display)),AllocAll);
- xc.red = xc.blue = xc.green = 0; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 0; XStoreColor(display,this->cm,&xc);
- xc.red = xc.blue = xc.green = 0xffff; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 255; XStoreColor(display,this->cm,&xc);
+ if (start>0) {
+ xc.red = xc.blue = xc.green = 0; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 0; XStoreColor(display,this->cm,&xc);
+ }
+ if (end<256) {
+ xc.red = xc.blue = xc.green = 0xffff; xc.flags = DoRed|DoGreen|DoBlue; xc.pixel = 255; XStoreColor(display,this->cm,&xc);
+ }
for (i=start;i<end;i++) {
xc.red = palent[i-start].peRed<<8;
xc.blue = palent[i-start].peBlue<<8;
@@ -632,13 +906,20 @@
return ++(this->ref);
}
+static HRESULT WINAPI IDirectDrawPalette_Initialize(
+ LPDIRECTDRAWPALETTE this,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
+) {
+ fprintf(stderr,"IDirectDrawPalette(%p)->Initialize(%p,0x%08lx,%p)\n",this,ddraw,x,palent);
+ return DDERR_ALREADYINITIALIZED;
+}
+
static struct IDirectDrawPalette_VTable ddpalvt = {
- 1,
+ (void*)1,
IDirectDrawPalette_AddRef,
IDirectDrawPalette_Release,
- 4,
+ (void*)4,
IDirectDrawPalette_GetEntries,
- 6,
+ IDirectDrawPalette_Initialize,
IDirectDrawPalette_SetEntries
};
@@ -648,7 +929,7 @@
fprintf(stderr,"IDirectDraw(%p)->CreatePalette(%08lx,%p,%p,%p),stub!\n",
this,x,palent,lpddpal,lpunk
);
- *lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDrawPalette));
+ *lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPalette));
(*lpddpal)->ref = 1;
(*lpddpal)->lpvtbl = &ddpalvt;
(*lpddpal)->ddraw = this;
@@ -675,14 +956,15 @@
}
static ULONG WINAPI IDirectDraw_AddRef(LPDIRECTDRAW this) {
- dprintf_relay(stddeb,"IDirectDraw(%p)->AddRef()\n",this);
+ dprintf_relay(stderr,"IDirectDraw(%p)->AddRef()\n",this);
return ++(this->ref);
}
static ULONG WINAPI IDirectDraw_Release(LPDIRECTDRAW this) {
- dprintf_relay(stddeb,"IDirectDraw(%p)->Release()\n",this);
+ dprintf_relay(stderr,"IDirectDraw(%p)->Release()\n",this);
if (!--(this->ref)) {
fprintf(stderr,"IDirectDraw::Release:freeing IDirectDraw(%p)\n",this);
+ XF86DGADirectVideo(display,DefaultScreen(display),0);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
@@ -744,27 +1026,27 @@
IDirectDraw2_QueryInterface,
IDirectDraw2_AddRef,
IDirectDraw2_Release,
- 4,
- 5/*IDirectDraw_CreateClipper*/,
+ (void*)4,
+ (void*)5/*IDirectDraw_CreateClipper*/,
IDirectDraw2_CreatePalette,
IDirectDraw2_CreateSurface,
- 8,
- 9,
+ (void*)8,
+ (void*)9,
IDirectDraw2_EnumSurfaces,
- 11,
+ (void*)11,
IDirectDraw2_GetCaps,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
+ (void*)13,
+ (void*)14,
+ (void*)15,
+ (void*)16,
+ (void*)17,
+ (void*)18,
+ (void*)19,
IDirectDraw2_RestoreDisplayMode,
IDirectDraw2_SetCooperativeLevel,
IDirectDraw2_SetDisplayMode,
- 23/*IDirectDraw_WaitForVerticalBlank*/,
- 24
+ (void*)23/*IDirectDraw_WaitForVerticalBlank*/,
+ (void*)24
};
static HRESULT WINAPI IDirectDraw_QueryInterface(
@@ -804,16 +1086,33 @@
fprintf(stderr,"IDirectDraw(%p)->EnumDisplayModes(0x%08lx,%p,%p,%p),stub!\n",this,dwFlags,lpddsfd,context,modescb);
ddsfd.dwSize = sizeof(ddsfd);
- ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_CAPS|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE;
+ fprintf(stderr,"size is %d\n",sizeof(ddsfd));
+ ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
ddsfd.dwHeight = 480;
ddsfd.dwWidth = 640;
ddsfd.lPitch = 640;
- ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE|DDSCAPS_FRONTBUFFER|DDSCAPS_BACKBUFFER|DDSCAPS_FLIP|DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY|DDSCAPS_ZBUFFER;
ddsfd.dwBackBufferCount = 1;
ddsfd.x.dwRefreshRate = 60;
+ ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
+ this->d.depth = 8;
_getpixelformat(this,&(ddsfd.ddpfPixelFormat));
fprintf(stderr,"modescb returned: 0x%lx\n",(DWORD)modescb(&ddsfd,context));
- return 0;
+ return DD_OK;
+}
+
+static HRESULT WINAPI IDirectDraw_GetDisplayMode(
+ LPDIRECTDRAW this,LPDDSURFACEDESC lpddsfd
+) {
+ fprintf(stderr,"IDirectDraw(%p)->GetDisplayMode(%p),stub!\n",this,lpddsfd);
+ lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
+ lpddsfd->dwHeight = this->d.vp_height;
+ lpddsfd->dwWidth = this->d.vp_width;
+ lpddsfd->lPitch = this->d.fb_width*this->d.depth/8;
+ lpddsfd->dwBackBufferCount = 1;
+ lpddsfd->x.dwRefreshRate = 60;
+ lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
+ _getpixelformat(this,&(lpddsfd->ddpfPixelFormat));
+ return DD_OK;
}
@@ -821,22 +1120,22 @@
IDirectDraw_QueryInterface,
IDirectDraw_AddRef,
IDirectDraw_Release,
- 4,
+ (void*)4,
IDirectDraw_CreateClipper,
IDirectDraw_CreatePalette,
IDirectDraw_CreateSurface,
IDirectDraw_DuplicateSurface,
IDirectDraw_EnumDisplayModes,
- 10,
- 11,
+ (void*)10,
+ (void*)11,
IDirectDraw_GetCaps,
- 13,
- 14,
- 15,
- 16,
- 17,
+ IDirectDraw_GetDisplayMode,
+ (void*)14,
+ (void*)15,
+ (void*)16,
+ (void*)17,
IDirectDraw_GetVerticalBlankStatus,
- 19,
+ (void*)19,
IDirectDraw_RestoreDisplayMode,
IDirectDraw_SetCooperativeLevel,
IDirectDraw_SetDisplayMode,
@@ -861,7 +1160,7 @@
MessageBox32A(0,"Using the XF86DGA extensions requires the program to be run using UID 0.","WINE DirectDraw",MB_OK|MB_ICONSTOP);
return E_UNEXPECTED;
}
- *lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectDraw));
+ *lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
(*lplpDD)->lpvtbl = &ddvt;
(*lplpDD)->ref = 1;
if (!XF86DGAQueryExtension(display,&evbase,&evret)) {
@@ -883,16 +1182,11 @@
(*lplpDD)->d.fb_banksize = banksize;
XF86DGASetViewPort(display,DefaultScreen(display),0,0);
- while (!XF86DGAViewPortChanged(display,DefaultScreen(display),1)) {
- fprintf(stderr,".");
- }
XF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
(*lplpDD)->d.vp_width = width;
(*lplpDD)->d.vp_height = height;
- (*lplpDD)->d.fb_height = height; /* FIXME: can we find out the virtual
- * size somehow else ?
- */
- (*lplpDD)->d.current_height = 0;
+ (*lplpDD)->d.fb_height = height;
+ (*lplpDD)->d.vpmask = 0;
return 0;
}
#else
diff --git a/graphics/metafiledrv/graphics.c b/graphics/metafiledrv/graphics.c
index f0fbc02..1647a66 100644
--- a/graphics/metafiledrv/graphics.c
+++ b/graphics/metafiledrv/graphics.c
@@ -188,3 +188,18 @@
{
return MF_MetaParam4(dc,META_FLOODFILL,x,y,HIWORD(color),LOWORD(color));
}
+
+
+/**********************************************************************
+ * MFDRV_PaintRgn
+ */
+BOOL32
+MFDRV_PaintRgn( DC *dc, HRGN32 hrgn )
+{
+ INT16 index;
+ index = MF_CreateRegion( dc, hrgn );
+ if(index == -1)
+ return FALSE;
+ return MF_MetaParam1( dc, META_PAINTREGION, index );
+}
+
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index f60fe08..c55832a 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -38,7 +38,7 @@
NULL, /* pOffsetClipRgn */
MFDRV_OffsetViewportOrg, /* pOffsetViewportOrg */
MFDRV_OffsetWindowOrg, /* pOffsetWindowOrg */
- NULL, /* pPaintRgn */
+ MFDRV_PaintRgn, /* pPaintRgn */
MFDRV_PatBlt, /* pPatBlt */
MFDRV_Pie, /* pPie */
MFDRV_PolyPolygon, /* pPolyPolygon */
diff --git a/graphics/x11drv/clipping.c b/graphics/x11drv/clipping.c
index 7645e68..d6cbc08 100644
--- a/graphics/x11drv/clipping.c
+++ b/graphics/x11drv/clipping.c
@@ -1,7 +1,7 @@
/*
- * DC clipping functions
+ * X11DRV clipping functions
*
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1998 Huw Davies
*/
#include <stdio.h>
@@ -10,26 +10,55 @@
#include "region.h"
#include "stddebug.h"
#include "debug.h"
+#include "heap.h"
/***********************************************************************
* X11DRV_SetDeviceClipping
+ * Copy RECT32s to a temporary buffer of XRectangles and call
+ * XSetClipRectangles().
+ *
+ * Could write using GetRegionData but this would be slower.
*/
void X11DRV_SetDeviceClipping( DC * dc )
{
+ XRectangle *pXrect;
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
if (!obj)
{
fprintf( stderr, "X11DRV_SetDeviceClipping: Rgn is 0. Please report this.\n");
exit(1);
}
- if (obj->xrgn)
+
+ if (obj->rgn->numRects > 0)
{
- XSetRegion( display, dc->u.x.gc, obj->xrgn );
- XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
+ XRectangle *pXr;
+ RECT32 *pRect = obj->rgn->rects;
+ RECT32 *pEndRect = obj->rgn->rects + obj->rgn->numRects;
+
+ pXrect = HeapAlloc( GetProcessHeap(), 0,
+ sizeof(*pXrect) * obj->rgn->numRects );
+ if(!pXrect)
+ {
+ fprintf(stderr, "X11DRV_SetDeviceClipping() can't alloc buffer\n");
+ return;
+ }
+
+ for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++)
+ {
+ pXr->x = pRect->left;
+ pXr->y = pRect->top;
+ pXr->width = pRect->right - pRect->left;
+ pXr->height = pRect->bottom - pRect->top;
+ }
}
- else /* Clip everything */
- {
- XSetClipRectangles( display, dc->u.x.gc, 0, 0, NULL, 0, 0 );
- }
+ else
+ pXrect = NULL;
+
+ XSetClipRectangles( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY,
+ pXrect, obj->rgn->numRects, YXBanded );
+
+ if(pXrect)
+ HeapFree( GetProcessHeap(), 0, pXrect );
+
GDI_HEAP_UNLOCK( dc->w.hGCClipRgn );
}
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
index d6e42e4..af3fd94 100644
--- a/graphics/x11drv/graphics.c
+++ b/graphics/x11drv/graphics.c
@@ -440,15 +440,20 @@
HRGN32 tmpVisRgn, prevVisRgn;
HDC32 hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
- /* Modify visible region */
+ if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return FALSE;
- if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
- if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 )))
- {
- RestoreVisRgn( hdc );
- return FALSE;
+ /* Transform region into device co-ords */
+ if (!REGION_LPTODP( hdc, tmpVisRgn, hrgn )) {
+ DeleteObject32( tmpVisRgn );
+ return FALSE;
}
- CombineRgn32( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
+
+ /* Modify visible region */
+ if (!(prevVisRgn = SaveVisRgn( hdc ))) {
+ DeleteObject32( tmpVisRgn );
+ return FALSE;
+ }
+ CombineRgn32( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
SelectVisRgn( hdc, tmpVisRgn );
DeleteObject32( tmpVisRgn );
diff --git a/if1632/relay.c b/if1632/relay.c
index 8e247ff..6e188bb 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -112,8 +112,25 @@
case 't':
args16 -= 4;
printf( "0x%08x", *(int *)args16 );
- if (HIWORD(*(int *)args16))
- printf( " \"%s\"", (char *)PTR_SEG_TO_LIN(*(int *)args16) );
+ if (HIWORD(*(int *)args16)) {
+ LPBYTE s = (LPBYTE)PTR_SEG_TO_LIN(*(int*)args16);
+
+ /* filter out non printable chars, which would destroy output */
+ fputs(" \"",stdout);
+ while (*s) {
+ if (*s < ' ') {
+ printf( "\\0x%02x",*s++);
+ continue;
+ }
+ if (*s=='\\') {
+ fputs( "\\\\",stdout);
+ s++;
+ continue;
+ }
+ fputc(*s++,stdout);
+ }
+ fputs("\"",stdout);
+ }
break;
case 'p':
args16 -= 4;
@@ -122,8 +139,25 @@
case 'T':
args16 -= 4;
printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
- if (HIWORD(*(int *)args16))
- printf( " \"%s\"", (char *)PTR_SEG_TO_LIN(*(int *)args16) );
+ if (HIWORD(*(int *)args16)) {
+ LPBYTE s = (LPBYTE)PTR_SEG_TO_LIN(*(int*)args16);
+
+ /* filter out non printable chars, which would destroy output */
+ fputs(" \"",stdout);
+ while (*s) {
+ if (*s < ' ') {
+ printf( "\\0x%02x",*s++);
+ continue;
+ }
+ if (*s=='\\') {
+ fputs( "\\\\",stdout);
+ s++;
+ continue;
+ }
+ fputc(*s++,stdout);
+ }
+ fputs("\"",stdout);
+ }
break;
}
args++;
@@ -209,10 +243,10 @@
if (nb_args == -1) /* Register function */
{
CONTEXT *context = (CONTEXT *)stack[0];
- WORD *stack16 = (WORD *)CURRENT_STACK16 - 2 /* for saved %%esp */;
+ WORD *stack16 = (WORD *)CURRENT_STACK16;
printf( "CallTo16(func=%04lx:%04x,ds=%04lx",
CS_reg(context), IP_reg(context), DS_reg(context) );
- nb_args = -stack[1] / sizeof(WORD);
+ nb_args = stack[1] / sizeof(WORD);
while (nb_args--) printf( ",0x%04x", *(--stack16) );
printf( ")\n" );
printf( " AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x BP=%04x ES=%04x\n",
@@ -268,13 +302,13 @@
lpbuf[0] = IP_reg(context);
lpbuf[1] = CS_reg(context);
- lpbuf[2] = LOWORD(pFrame->saved_ss_sp);
+ lpbuf[2] = LOWORD(pFrame->frame32);
lpbuf[3] = BP_reg(context);
lpbuf[4] = SI_reg(context);
lpbuf[5] = DI_reg(context);
lpbuf[6] = DS_reg(context);
lpbuf[7] = OFFSETOF(IF1632_Saved16_ss_sp);
- lpbuf[8] = HIWORD(pFrame->saved_ss_sp);
+ lpbuf[8] = HIWORD(pFrame->frame32);
AX_reg(context) = 0; /* Return 0 */
}
@@ -301,7 +335,7 @@
IF1632_Saved16_ss_sp = MAKELONG( lpbuf[7] - sizeof(WORD),
HIWORD(IF1632_Saved16_ss_sp) );
pFrame = CURRENT_STACK16;
- pFrame->saved_ss_sp = MAKELONG( lpbuf[2], lpbuf[8] );
+ pFrame->frame32 = MAKELONG( lpbuf[2], lpbuf[8] );
IP_reg(context) = lpbuf[0];
CS_reg(context) = lpbuf[1];
BP_reg(context) = lpbuf[3];
@@ -375,6 +409,14 @@
break;
case 7: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
break;
+ case 8: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+ break;
+ case 9: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
+ break;
+ case 10: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
+ break;
+ case 11: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
+ break;
default:
/* FIXME: should go up to 32 arguments */
fprintf(stderr,"CallProc32W: unsupported number of arguments %ld, please report.\n",nrofargs);
diff --git a/if1632/thunk.c b/if1632/thunk.c
index 5bb6eba..88b0281 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -240,15 +240,14 @@
}
}
- args = (WORD *)CURRENT_STACK16 - 7;
+ args = (WORD *)CURRENT_STACK16 - 5;
args[0] = LOWORD(lParam);
args[1] = HIWORD(lParam);
args[2] = wParam;
args[3] = msg;
args[4] = hwnd;
- /* args[5] and args[6] are used by relay code to store the stack pointer */
- ret = CallTo16_sreg_( &context, -(5 * sizeof(WORD)) );
+ ret = CallTo16_sreg_( &context, 5 * sizeof(WORD) );
if (offset) STACK16_POP(offset);
return ret;
}
diff --git a/include/acconfig.h b/include/acconfig.h
index 00d85cd..e7ec75b 100644
--- a/include/acconfig.h
+++ b/include/acconfig.h
@@ -5,3 +5,15 @@
/* Define if symbols declared in assembly code need an underscore prefix */
#undef NEED_UNDERSCORE_PREFIX
+
+/* Define to use .string instead of .ascii */
+#undef HAVE_ASM_STRING
+
+/* Define if union semun is defined in sys/sem.h */
+#undef HAVE_UNION_SEMUN
+
+/* Define if you have the Xxf86dga library (-lXxf86dga). */
+#undef HAVE_LIBXXF86DGA
+
+/* Define if you have the Open Sound system. */
+#undef HAVE_OSS
diff --git a/include/config.h.in b/include/config.h.in
index 40d489b..0f335ec 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -18,6 +18,18 @@
/* Define if symbols declared in assembly code need an underscore prefix */
#undef NEED_UNDERSCORE_PREFIX
+/* Define to use .string instead of .ascii */
+#undef HAVE_ASM_STRING
+
+/* Define if union semun is defined in sys/sem.h */
+#undef HAVE_UNION_SEMUN
+
+/* Define if you have the Xxf86dga library (-lXxf86dga). */
+#undef HAVE_LIBXXF86DGA
+
+/* Define if you have the Open Sound system. */
+#undef HAVE_OSS
+
/* Define if you have the clone function. */
#undef HAVE_CLONE
@@ -42,9 +54,6 @@
/* Define if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H
-/* Define if you have the Xxf86dga library (-lXxf86dga). */
-#undef HAVE_LIBXXF86DGA
-
/* Define if you have the i386 library (-li386). */
#undef HAVE_LIBI386
diff --git a/include/ddraw.h b/include/ddraw.h
index 3197b85..26f72ac 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -20,6 +20,12 @@
typedef struct IDirectDrawSurface IDirectDrawSurface,*LPDIRECTDRAWSURFACE;
typedef struct IDirectDrawSurface2 IDirectDrawSurface2,*LPDIRECTDRAWSURFACE2;
+#define DDENUMRET_CANCEL 0
+#define DDENUMRET_OK 1
+
+#define DD_OK 0
+
+
#define _FACDD 0x876
#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code )
@@ -681,7 +687,7 @@
STDMETHOD(Compact)(THIS) PURE;
STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE;
STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE;
- STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE FAR *,
+ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *,
IUnknown FAR *) PURE;
STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE
FAR * ) PURE;
@@ -706,9 +712,10 @@
DWORD depth;
DWORD vp_width,vp_height; /* viewport dimension */
DWORD height,width; /* SetDisplayMode */
- DWORD current_height,fb_width,fb_height,fb_banksize,fb_memsize;
+ DWORD fb_width,fb_height,fb_banksize,fb_memsize;
HWND32 mainwindow;
void *fb_addr;
+ unsigned int vpmask;
};
@@ -830,6 +837,7 @@
LPDIRECTDRAWPALETTE palette;
DWORD fb_height,lpitch,width,height;
LPDIRECTDRAW ddraw;
+ LPDIRECTDRAWSURFACE backbuffer;
};
#undef THIS
#define THIS LPDIRECTDRAWSURFACE2 this
@@ -885,6 +893,7 @@
LPDIRECTDRAWPALETTE palette;
DWORD fb_height,lpitch,width,height;
LPDIRECTDRAW ddraw;
+ LPDIRECTDRAWSURFACE backbuffer;
};
#undef THIS
diff --git a/include/dsound.h b/include/dsound.h
index 61d042b..f4d6801 100644
--- a/include/dsound.h
+++ b/include/dsound.h
@@ -14,6 +14,25 @@
typedef struct IDirectSound IDirectSound,*LPDIRECTSOUND;
typedef struct IDirectSoundBuffer IDirectSoundBuffer,*LPDIRECTSOUNDBUFFER,**LPLPDIRECTSOUNDBUFFER;
+#define _FACDS 0x878
+#define MAKE_DSHRESULT(code) MAKE_HRESULT(1,_FACDS,code)
+
+#define DSERR_ALLOCATED MAKE_DSHRESULT(10)
+#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30)
+#define DSERR_INVALIDPARAM E_INVALIDARG
+#define DSERR_INVALIDCALL MAKE_DSHRESULT(50)
+#define DSERR_GENERIC E_FAIL
+#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70)
+#define DSERR_OUTOFMEMORY E_OUTOFMEMORY
+#define DSERR_BADFORMAT MAKE_DSHRESULT(100)
+#define DSERR_UNSUPPORTED E_NOTIMPL
+#define DSERR_NODRIVER MAKE_DSHRESULT(120)
+#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT(130)
+#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION
+#define DSERR_BUFFERLOST MAKE_DSHRESULT(150)
+#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT(160)
+#define DSERR_UNINITIALIZED MAKE_DSHRESULT(170)
+
#define DSCAPS_PRIMARYMONO 0x00000001
#define DSCAPS_PRIMARYSTEREO 0x00000002
#define DSCAPS_PRIMARY8BIT 0x00000004
@@ -26,6 +45,11 @@
#define DSCAPS_SECONDARY8BIT 0x00000400
#define DSCAPS_SECONDARY16BIT 0x00000800
+#define DSSCL_NORMAL 1
+#define DSSCL_PRIORITY 2
+#define DSSCL_EXCLUSIVE 3
+#define DSSCL_WRITEPRIMARY 4
+
typedef struct _DSCAPS
{
DWORD dwSize;
@@ -145,6 +169,8 @@
struct IDirectSound {
LPDIRECTSOUND_VTABLE lpvtbl;
DWORD ref;
+ int nrofbuffers;
+ LPDIRECTSOUNDBUFFER *buffers;
};
#undef THIS
@@ -181,7 +207,11 @@
struct IDirectSoundBuffer {
LPDIRECTSOUNDBUFFER_VTABLE lpvtbl;
+ WAVEFORMATEX wfx;
DWORD ref;
+ LPBYTE buffer;
+ DWORD playing,playpos,writepos,buflen;
+ LPDIRECTSOUND dsound;
};
#endif
diff --git a/include/k32obj.h b/include/k32obj.h
index afe3c94..5ac2a5e 100644
--- a/include/k32obj.h
+++ b/include/k32obj.h
@@ -44,7 +44,7 @@
typedef struct
{
BOOL32 (*signaled)(K32OBJ*,DWORD); /* Is object signaled? */
- void (*satisfied)(K32OBJ*,DWORD); /* Wait on object is satisfied */
+ BOOL32 (*satisfied)(K32OBJ*,DWORD); /* Wait on object is satisfied */
void (*add_wait)(K32OBJ*,DWORD); /* Add thread to wait queue */
void (*remove_wait)(K32OBJ*,DWORD); /* Remove thread from wait queue */
void (*destroy)(K32OBJ *); /* Destroy object on refcount==0 */
diff --git a/include/metafile.h b/include/metafile.h
index b511fce..c674718 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -36,6 +36,6 @@
BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
short heightDest, DC *dcSrc, short xSrc, short ySrc,
short widthSrc, short heightSrc, DWORD rop);
-
+INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn);
#endif /* __WINE_METAFILE_H */
diff --git a/include/metafiledrv.h b/include/metafiledrv.h
index a8e67a9..e89d091 100644
--- a/include/metafiledrv.h
+++ b/include/metafiledrv.h
@@ -72,5 +72,6 @@
extern BOOL32 MFDRV_ExtTextOut( struct tagDC *dc, INT32 x, INT32 y,
UINT32 flags, const RECT32 *lprect, LPCSTR str,
UINT32 count, const INT32 *lpDx );
+extern BOOL32 MFDRV_PaintRgn( DC *dc, HRGN32 hrgn );
#endif /* __WINE_METAFILEDRV_H */
diff --git a/include/options.h b/include/options.h
index c68158e..784614c 100644
--- a/include/options.h
+++ b/include/options.h
@@ -59,7 +59,6 @@
if write access is requested */
WINE_MODE mode; /* Start Wine in selected mode
(standard/enhanced) */
- int ipc; /* Use IPC mechanisms */
WINE_LANGUAGE language; /* Current language */
int managed; /* Managed windows */
int perfectGraphics; /* Favor correctness over speed for graphics */
diff --git a/include/process.h b/include/process.h
index ca0014f..21893db 100644
--- a/include/process.h
+++ b/include/process.h
@@ -98,20 +98,12 @@
LCID locale; /* c4 Locale to be queried by GetThreadLocale (NT) */
} PDB32;
-/* PDB <-> Process id conversion macros */
-#define PROCESS_OBFUSCATOR ((DWORD)0xdeadbeef)
-#define PROCESS_ID_TO_PDB(id) ((PDB32 *)((id) ^ PROCESS_OBFUSCATOR))
-#define PDB_TO_PROCESS_ID(pdb) ((DWORD)(pdb) ^ PROCESS_OBFUSCATOR)
-
/* scheduler/process.c */
+extern PDB32 *PROCESS_Current(void);
+extern PDB32 *PROCESS_IdToPDB( DWORD id );
extern HANDLE32 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags);
extern K32OBJ *PROCESS_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type );
extern BOOL32 PROCESS_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags );
extern PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line );
-extern PDB32 *pCurrentProcess;
-
-/* scheduler/event.c */
-extern void EVENT_Set( K32OBJ *obj );
-extern K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state );
#endif /* __WINE_PROCESS_H */
diff --git a/include/region.h b/include/region.h
index d53546a..263379b 100644
--- a/include/region.h
+++ b/include/region.h
@@ -1,25 +1,394 @@
/*
* GDI region definitions
- *
- * Copyright 1994 Alexandre Julliard
+ * Mainly taken from the X11 distribution.
+ * Modifications: Copyright 1998 Huw Davies
*/
+/************************************************************************
+
+Copyright (c) 1987 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+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 and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+************************************************************************/
#ifndef __WINE_REGION_H
#define __WINE_REGION_H
+#include "windows.h"
#include "gdi.h"
+
+typedef struct {
+ INT32 size;
+ INT32 numRects;
+ INT32 type; /* NULL, SIMPLE or COMPLEX */
+ RECT32 *rects;
+ RECT32 extents;
+} WINEREGION;
+
/* GDI logical region object */
typedef struct
{
GDIOBJHDR header;
- Region xrgn;
+ WINEREGION *rgn;
} RGNOBJ;
+/* 1 if two RECTs overlap.
+ * 0 if two RECTs do not overlap.
+ */
+#define EXTENTCHECK(r1, r2) \
+ ((r1)->right > (r2)->left && \
+ (r1)->left < (r2)->right && \
+ (r1)->bottom > (r2)->top && \
+ (r1)->top < (r2)->bottom)
+
+/*
+ * Check to see if there is enough memory in the present region.
+ */
+#define MEMCHECK(reg, rect, firstrect){\
+ if ((reg)->numRects >= ((reg)->size - 1)){\
+ (firstrect) = HeapReAlloc( SystemHeap, 0, \
+ (firstrect), (2 * (sizeof(RECT32)) * ((reg)->size)));\
+ if ((firstrect) == 0)\
+ return;\
+ (reg)->size *= 2;\
+ (rect) = &(firstrect)[(reg)->numRects];\
+ }\
+ }
+
+#define EMPTY_REGION(pReg) { \
+ (pReg)->numRects = 0; \
+ (pReg)->extents.left = (pReg)->extents.top = 0; \
+ (pReg)->extents.right = (pReg)->extents.bottom = 0; \
+ (pReg)->type = NULLREGION; \
+ }
+
+#define REGION_NOT_EMPTY(pReg) pReg->numRects
+
+#define INRECT(r, x, y) \
+ ( ( ((r).right > x)) && \
+ ( ((r).left <= x)) && \
+ ( ((r).bottom > y)) && \
+ ( ((r).top <= y)) )
+
+
+/*
+ * number of points to buffer before sending them off
+ * to scanlines() : Must be an even number
+ */
+#define NUMPTSTOBUFFER 200
+
+/*
+ * used to allocate buffers for points and link
+ * the buffers together
+ */
+
+typedef struct _POINTBLOCK {
+ POINT32 pts[NUMPTSTOBUFFER];
+ struct _POINTBLOCK *next;
+} POINTBLOCK;
+
+
+
+/*
+ * This file contains a few macros to help track
+ * the edge of a filled object. The object is assumed
+ * to be filled in scanline order, and thus the
+ * algorithm used is an extension of Bresenham's line
+ * drawing algorithm which assumes that y is always the
+ * major axis.
+ * Since these pieces of code are the same for any filled shape,
+ * it is more convenient to gather the library in one
+ * place, but since these pieces of code are also in
+ * the inner loops of output primitives, procedure call
+ * overhead is out of the question.
+ * See the author for a derivation if needed.
+ */
+
+
+/*
+ * In scan converting polygons, we want to choose those pixels
+ * which are inside the polygon. Thus, we add .5 to the starting
+ * x coordinate for both left and right edges. Now we choose the
+ * first pixel which is inside the pgon for the left edge and the
+ * first pixel which is outside the pgon for the right edge.
+ * Draw the left pixel, but not the right.
+ *
+ * How to add .5 to the starting x coordinate:
+ * If the edge is moving to the right, then subtract dy from the
+ * error term from the general form of the algorithm.
+ * If the edge is moving to the left, then add dy to the error term.
+ *
+ * The reason for the difference between edges moving to the left
+ * and edges moving to the right is simple: If an edge is moving
+ * to the right, then we want the algorithm to flip immediately.
+ * If it is moving to the left, then we don't want it to flip until
+ * we traverse an entire pixel.
+ */
+#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
+ int dx; /* local storage */ \
+\
+ /* \
+ * if the edge is horizontal, then it is ignored \
+ * and assumed not to be processed. Otherwise, do this stuff. \
+ */ \
+ if ((dy) != 0) { \
+ xStart = (x1); \
+ dx = (x2) - xStart; \
+ if (dx < 0) { \
+ m = dx / (dy); \
+ m1 = m - 1; \
+ incr1 = -2 * dx + 2 * (dy) * m1; \
+ incr2 = -2 * dx + 2 * (dy) * m; \
+ d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
+ } else { \
+ m = dx / (dy); \
+ m1 = m + 1; \
+ incr1 = 2 * dx - 2 * (dy) * m1; \
+ incr2 = 2 * dx - 2 * (dy) * m; \
+ d = -2 * m * (dy) + 2 * dx; \
+ } \
+ } \
+}
+
+#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
+ if (m1 > 0) { \
+ if (d > 0) { \
+ minval += m1; \
+ d += incr1; \
+ } \
+ else { \
+ minval += m; \
+ d += incr2; \
+ } \
+ } else {\
+ if (d >= 0) { \
+ minval += m1; \
+ d += incr1; \
+ } \
+ else { \
+ minval += m; \
+ d += incr2; \
+ } \
+ } \
+}
+
+/*
+ * This structure contains all of the information needed
+ * to run the bresenham algorithm.
+ * The variables may be hardcoded into the declarations
+ * instead of using this structure to make use of
+ * register declarations.
+ */
+typedef struct {
+ INT32 minor_axis; /* minor axis */
+ INT32 d; /* decision variable */
+ INT32 m, m1; /* slope and slope+1 */
+ INT32 incr1, incr2; /* error increments */
+} BRESINFO;
+
+
+#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
+ BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
+ bres.m, bres.m1, bres.incr1, bres.incr2)
+
+#define BRESINCRPGONSTRUCT(bres) \
+ BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
+
+
+
+/*
+ * These are the data structures needed to scan
+ * convert regions. Two different scan conversion
+ * methods are available -- the even-odd method, and
+ * the winding number method.
+ * The even-odd rule states that a point is inside
+ * the polygon if a ray drawn from that point in any
+ * direction will pass through an odd number of
+ * path segments.
+ * By the winding number rule, a point is decided
+ * to be inside the polygon if a ray drawn from that
+ * point in any direction passes through a different
+ * number of clockwise and counter-clockwise path
+ * segments.
+ *
+ * These data structures are adapted somewhat from
+ * the algorithm in (Foley/Van Dam) for scan converting
+ * polygons.
+ * The basic algorithm is to start at the top (smallest y)
+ * of the polygon, stepping down to the bottom of
+ * the polygon by incrementing the y coordinate. We
+ * keep a list of edges which the current scanline crosses,
+ * sorted by x. This list is called the Active Edge Table (AET)
+ * As we change the y-coordinate, we update each entry in
+ * in the active edge table to reflect the edges new xcoord.
+ * This list must be sorted at each scanline in case
+ * two edges intersect.
+ * We also keep a data structure known as the Edge Table (ET),
+ * which keeps track of all the edges which the current
+ * scanline has not yet reached. The ET is basically a
+ * list of ScanLineList structures containing a list of
+ * edges which are entered at a given scanline. There is one
+ * ScanLineList per scanline at which an edge is entered.
+ * When we enter a new edge, we move it from the ET to the AET.
+ *
+ * From the AET, we can implement the even-odd rule as in
+ * (Foley/Van Dam).
+ * The winding number rule is a little trickier. We also
+ * keep the EdgeTableEntries in the AET linked by the
+ * nextWETE (winding EdgeTableEntry) link. This allows
+ * the edges to be linked just as before for updating
+ * purposes, but only uses the edges linked by the nextWETE
+ * link as edges representing spans of the polygon to
+ * drawn (as with the even-odd rule).
+ */
+
+/*
+ * for the winding number rule
+ */
+#define CLOCKWISE 1
+#define COUNTERCLOCKWISE -1
+
+typedef struct _EdgeTableEntry {
+ INT32 ymax; /* ycoord at which we exit this edge. */
+ BRESINFO bres; /* Bresenham info to run the edge */
+ struct _EdgeTableEntry *next; /* next in the list */
+ struct _EdgeTableEntry *back; /* for insertion sort */
+ struct _EdgeTableEntry *nextWETE; /* for winding num rule */
+ int ClockWise; /* flag for winding number rule */
+} EdgeTableEntry;
+
+
+typedef struct _ScanLineList{
+ INT32 scanline; /* the scanline represented */
+ EdgeTableEntry *edgelist; /* header node */
+ struct _ScanLineList *next; /* next in the list */
+} ScanLineList;
+
+
+typedef struct {
+ INT32 ymax; /* ymax for the polygon */
+ INT32 ymin; /* ymin for the polygon */
+ ScanLineList scanlines; /* header node */
+} EdgeTable;
+
+
+/*
+ * Here is a struct to help with storage allocation
+ * so we can allocate a big chunk at a time, and then take
+ * pieces from this heap when we need to.
+ */
+#define SLLSPERBLOCK 25
+
+typedef struct _ScanLineListBlock {
+ ScanLineList SLLs[SLLSPERBLOCK];
+ struct _ScanLineListBlock *next;
+} ScanLineListBlock;
+
+
+/*
+ *
+ * a few macros for the inner loops of the fill code where
+ * performance considerations don't allow a procedure call.
+ *
+ * Evaluate the given edge at the given scanline.
+ * If the edge has expired, then we leave it and fix up
+ * the active edge table; otherwise, we increment the
+ * x value to be ready for the next scanline.
+ * The winding number rule is in effect, so we must notify
+ * the caller when the edge has been removed so he
+ * can reorder the Winding Active Edge Table.
+ */
+#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
+ if (pAET->ymax == y) { /* leaving this edge */ \
+ pPrevAET->next = pAET->next; \
+ pAET = pPrevAET->next; \
+ fixWAET = 1; \
+ if (pAET) \
+ pAET->back = pPrevAET; \
+ } \
+ else { \
+ BRESINCRPGONSTRUCT(pAET->bres); \
+ pPrevAET = pAET; \
+ pAET = pAET->next; \
+ } \
+}
+
+
+/*
+ * Evaluate the given edge at the given scanline.
+ * If the edge has expired, then we leave it and fix up
+ * the active edge table; otherwise, we increment the
+ * x value to be ready for the next scanline.
+ * The even-odd rule is in effect.
+ */
+#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
+ if (pAET->ymax == y) { /* leaving this edge */ \
+ pPrevAET->next = pAET->next; \
+ pAET = pPrevAET->next; \
+ if (pAET) \
+ pAET->back = pPrevAET; \
+ } \
+ else { \
+ BRESINCRPGONSTRUCT(pAET->bres); \
+ pPrevAET = pAET; \
+ pAET = pAET->next; \
+ } \
+}
extern BOOL32 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj );
extern BOOL32 REGION_UnionRectWithRgn( HRGN32 hrgn, const RECT32 *lpRect );
extern BOOL32 REGION_FrameRgn( HRGN32 dest, HRGN32 src, INT32 x, INT32 y );
-extern BOOL32 REGION_IsEmpty( HRGN32 rgn );
+extern BOOL32 REGION_LPTODP( HDC32 hdc, HRGN32 hDest, HRGN32 hSrc );
#endif /* __WINE_REGION_H */
+
+
+
+
+
+
+
+
+
+
diff --git a/include/stackframe.h b/include/stackframe.h
index e1cfa77..1435bbb 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -13,36 +13,37 @@
#pragma pack(1)
+ /* 32-bit stack layout after CallTo16() */
+typedef struct _STACK32FRAME
+{
+ SEGPTR frame16; /* 00 16-bit frame from last CallFrom16() */
+ DWORD edi; /* 04 saved registers */
+ DWORD esi; /* 08 */
+ DWORD edx; /* 0c */
+ DWORD ecx; /* 10 */
+ DWORD ebx; /* 14 */
+ DWORD restore_addr; /* 18 return address for restoring code selector */
+ DWORD codeselector; /* 1c code selector to restore */
+ DWORD ebp; /* 20 saved 32-bit frame pointer */
+ DWORD retaddr; /* 24 actual return address */
+ DWORD args[1]; /* 28 arguments to 16-bit function */
+} STACK32FRAME;
+
/* 16-bit stack layout after CallFrom16() */
typedef struct
{
- DWORD saved_ss_sp; /* 00 saved previous 16-bit stack */
- DWORD ebp; /* 04 full 32-bit content of ebp */
- WORD entry_ip; /* 08 ip of entry point */
- WORD ds; /* 0a ds */
- WORD entry_cs; /* 0c cs of entry point */
- WORD es; /* 0e es */
- DWORD entry_point; /* 10 32-bit entry point to call */
- WORD bp; /* 14 16-bit bp */
- WORD ip; /* 16 return address */
- WORD cs; /* 18 */
+ STACK32FRAME *frame32; /* 00 32-bit frame from last CallTo16() */
+ DWORD ebp; /* 04 full 32-bit content of ebp */
+ WORD entry_ip; /* 08 ip of entry point */
+ WORD ds; /* 0a ds */
+ WORD entry_cs; /* 0c cs of entry point */
+ WORD es; /* 0e es */
+ DWORD entry_point; /* 10 32-bit entry point to call */
+ WORD bp; /* 14 16-bit bp */
+ WORD ip; /* 16 return address */
+ WORD cs; /* 18 */
} STACK16FRAME;
- /* 32-bit stack layout after CallTo16() */
-typedef struct
-{
- DWORD edi; /* 00 saved registers */
- DWORD esi; /* 04 */
- DWORD edx; /* 08 */
- DWORD ecx; /* 0c */
- DWORD ebx; /* 10 */
- DWORD restore_addr; /* 14 return address for restoring code selector */
- DWORD codeselector; /* 18 code selector to restore */
- DWORD ebp; /* 1c saved 32-bit frame pointer */
- DWORD retaddr; /* 20 actual return address */
- DWORD args[1]; /* 24 arguments to 16-bit function */
-} STACK32FRAME;
-
#pragma pack(4)
/* Saved 16-bit stack for current process (Win16 only) */
diff --git a/include/thread.h b/include/thread.h
index 4e9b61f..361d165 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -55,9 +55,9 @@
DWORD exit_code; /* 48 Termination status */
WORD teb_sel; /* 4c Selector to TEB */
WORD emu_sel; /* 4e 80387 emulator selector */
- DWORD unknown1; /* 50 Unknown */
+ int thread_errno; /* 50 Per-thread errno (was: unknown) */
WAIT_STRUCT *wait_list; /* 54 Event waiting list */
- DWORD unknown2; /* 58 Unknown */
+ int thread_h_errno; /* 50 Per-thread h_errno (was: unknown) */
void *ring0_thread; /* 5c Pointer to ring 0 thread */
void *ptdbx; /* 60 Pointer to TDBX structure */
void *stack_base; /* 64 Base of the stack */
@@ -86,7 +86,8 @@
K32OBJ *win16_mutex; /* 1e8 Pointer to Win16 mutex */
K32OBJ *win32_mutex; /* 1ec Pointer to KERNEL32 mutex */
K32OBJ *crit_section2; /* 1f0 Another critical section */
- DWORD unknown6[3]; /* 1f4 Unknown */
+ K32OBJ *mutex_list; /* 1f4 List of owned mutex (was: unknown)*/
+ DWORD unknown6[2]; /* 1f8 Unknown */
/* The following are Wine-specific fields */
CONTEXT context; /* 200 Thread context */
WAIT_STRUCT wait_struct; /* Event wait structure */
@@ -124,8 +125,20 @@
extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread );
extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
+/* scheduler/event.c */
+extern void EVENT_Set( K32OBJ *obj );
+extern K32OBJ *EVENT_Create( BOOL32 manual_reset, BOOL32 initial_state );
+
+/* scheduler/mutex.c */
+extern void MUTEX_Abandon( K32OBJ *obj );
+
/* scheduler/synchro.c */
extern void SYNC_WaitForCondition( WAIT_STRUCT *wait, DWORD timeout );
extern void SYNC_WakeUp( THREAD_QUEUE *queue, DWORD max );
+/* scheduler/sysdeps.c */
+extern int SYSDEPS_SpawnThread( THDB *thread );
+extern void SYSDEPS_ExitThread(void);
+extern TEB * WINAPI NtCurrentTeb(void);
+
#endif /* __WINE_THREAD_H */
diff --git a/include/version.h b/include/version.h
index bb64ee6..686a913 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1 +1 @@
-#define WINE_RELEASE_INFO "Wine release 980104"
+#define WINE_RELEASE_INFO "Wine release 980118"
diff --git a/include/windows.h b/include/windows.h
index d9fe47d..43a00b8 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -5689,6 +5689,7 @@
DWORD WINAPI ExpandEnvironmentStrings32A(LPCSTR,LPSTR,DWORD);
DWORD WINAPI ExpandEnvironmentStrings32W(LPCWSTR,LPWSTR,DWORD);
#define ExpandEnvironmentStrings WINELIB_NAME_AW(ExpandEnvironmentStrings)
+HRGN32 WINAPI ExtCreateRegion(LPXFORM,DWORD,LPRGNDATA);
BOOL32 WINAPI FileTimeToDosDateTime(const FILETIME*,LPWORD,LPWORD);
BOOL32 WINAPI FileTimeToLocalFileTime(const FILETIME*,LPFILETIME);
BOOL32 WINAPI FileTimeToSystemTime(const FILETIME*,LPSYSTEMTIME);
@@ -5752,6 +5753,7 @@
INT32 WINAPI GetPrivateProfileSection32W(LPCWSTR,LPWSTR,INT32,LPCWSTR);
#define GetPrivateProfileSection WINELIB_NAME_AW(GetPrivateProfileSection)
HANDLE32 WINAPI GetProcessHeap(void);
+DWORD WINAPI GetRegionData(HRGN32,DWORD,LPRGNDATA);
DWORD WINAPI GetShortPathName32A(LPCSTR,LPSTR,DWORD);
DWORD WINAPI GetShortPathName32W(LPCWSTR,LPWSTR,DWORD);
#define GetShortPathName WINELIB_NAME_AW(GetShortPathName)
diff --git a/loader/main.c b/loader/main.c
index b596be2..767eb10 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -48,6 +48,7 @@
BOOL32 MAIN_KernelInit(void)
{
extern BOOL32 EVENT_Init(void);
+ extern BOOL32 PROCESS_Init(void);
extern BOOL32 VIRTUAL_Init(void);
/* Initialize virtual memory management */
@@ -57,15 +58,18 @@
if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
+ /* Create the initial process */
+ if (!PROCESS_Init()) return FALSE;
+
+ /* Initialize signal handling */
+ if (!SIGNAL_Init()) return FALSE;
+
/* Load the configuration file */
if (!PROFILE_LoadWineIni()) return FALSE;
/* Initialize DOS memory */
if (!DOSMEM_Init()) return FALSE;
- /* Initialize signal handling */
- if (!SIGNAL_Init()) return FALSE;
-
/* Initialise DOS drives */
if (!DRIVE_Init()) return FALSE;
diff --git a/loader/module.c b/loader/module.c
index 6cea6c5..831a001 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1437,7 +1437,7 @@
hmod = PE_LoadLibraryEx32A(buffer,hfile,flags);
}
/* initialize all DLLs, which haven't been initialized yet. */
- PE_InitializeDLLs( pCurrentProcess, DLL_PROCESS_ATTACH, NULL);
+ PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, NULL);
return hmod;
}
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 98a8a9c..14278c8 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -78,7 +78,7 @@
IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(*stack16Top));
stack16Top = CURRENT_STACK16;
- stack16Top->saved_ss_sp = 0;
+ stack16Top->frame32 = 0;
stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
stack16Top->entry_point = 0;
stack16Top->entry_ip = 0;
@@ -386,7 +386,7 @@
IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(*stack16Top) );
stack16Top = CURRENT_STACK16;
- stack16Top->saved_ss_sp = 0;
+ stack16Top->frame32 = 0;
stack16Top->ebp = 0;
stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
stack16Top->entry_point = 0;
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 043404d..e3f31d4 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -97,7 +97,7 @@
u_long * function;
u_char ** name, *ename;
int i;
- PDB32 *process=pCurrentProcess;
+ PDB32 *process=PROCESS_Current();
PE_MODREF *pem;
u_long rva_start, rva_end, addr;
char * forward;
@@ -690,14 +690,14 @@
if (!HIWORD(hModule)) /* internal (or bad) */
return hModule;
/* check if this module is already mapped */
- pem = pCurrentProcess->modref_list;
+ pem = PROCESS_Current()->modref_list;
while (pem) {
if (pem->module == hModule) return hModule;
pem = pem->next;
}
pModule = MODULE_GetPtr(hModule);
if (pModule->flags & NE_FFLAGS_BUILTIN) {
- PDB32 *process = pCurrentProcess;
+ PDB32 *process = PROCESS_Current();
IMAGE_DOS_HEADER *dh;
IMAGE_NT_HEADERS *nh;
IMAGE_SECTION_HEADER *sh;
@@ -743,7 +743,7 @@
if (pModule->module32 < 32) return 21;
}
/* recurse */
- pModule->module32 = PE_MapImage( pModule->module32, pCurrentProcess,
+ pModule->module32 = PE_MapImage( pModule->module32, PROCESS_Current(),
&ofs,flags);
return pModule->module32;
}
@@ -776,7 +776,7 @@
(LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
*((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
}
- pModule->module32 = PE_MapImage( hModule32, pCurrentProcess, ofs, 0 );
+ pModule->module32 = PE_MapImage( hModule32, PROCESS_Current(), ofs, 0 );
return hInstance;
}
@@ -875,7 +875,7 @@
*/
BOOL32 WINAPI DisableThreadLibraryCalls(HMODULE32 hModule)
{
- PDB32 *process = pCurrentProcess;
+ PDB32 *process = PROCESS_Current();
PE_MODREF *pem = process->modref_list;
while (pem) {
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 4e4098c..60fa5b8 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -33,7 +33,7 @@
static PE_MODREF*
HMODULE32toPE_MODREF(HMODULE32 hmod) {
NE_MODULE *pModule;
- PDB32 *pdb = pCurrentProcess;
+ PDB32 *pdb = PROCESS_Current();
PE_MODREF *pem;
if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
diff --git a/loader/task.c b/loader/task.c
index 110a799..7c31fae 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -56,7 +56,7 @@
static HGLOBAL16 TASK_CreateDOSEnvironment(void);
static void TASK_YieldToSystem(TDB*);
-static THDB TASK_SystemTHDB;
+
/***********************************************************************
* TASK_Init
*/
@@ -64,8 +64,6 @@
{
if (!(hDOSEnvironment = TASK_CreateDOSEnvironment()))
fprintf( stderr, "Not enough memory for DOS Environment\n" );
- TASK_SystemTHDB.teb_sel = SELECTOR_AllocBlock( &TASK_SystemTHDB, 0x1000, SEGMENT_DATA, TRUE, FALSE );
- SET_FS( TASK_SystemTHDB.teb_sel );
return (hDOSEnvironment != 0);
}
@@ -340,6 +338,8 @@
SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
IF1632_Saved16_ss_sp = pTask->ss_sp;
+ /* Terminate the stack frame */
+ CURRENT_STACK16->frame32 = NULL;
SET_CUR_THREAD( pTask->thdb );
if (pModule->flags & NE_FFLAGS_WIN32)
{
@@ -347,11 +347,11 @@
extern void InitTask( CONTEXT *context );
- FARPROC32 entry = (FARPROC32)RVA_PTR( pCurrentProcess->exe_modref->module, OptionalHeader.AddressOfEntryPoint );
+ FARPROC32 entry = (FARPROC32)RVA_PTR( PROCESS_Current()->exe_modref->module, OptionalHeader.AddressOfEntryPoint );
InitTask( NULL );
InitApp( pTask->hModule );
- PE_InitializeDLLs( pCurrentProcess, DLL_PROCESS_ATTACH, (LPVOID)-1 );
+ PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, (LPVOID)-1 );
dprintf_relay( stddeb, "CallTo32(entryproc=%p)\n", entry );
exit_code = entry();
TASK_KillCurrentTask( exit_code );
@@ -514,7 +514,7 @@
/* Create the Win32 part of the task */
- pCurrentProcess = pdb32 = PROCESS_Create( pTask, cmdLine );
+ pdb32 = PROCESS_Create( pTask, cmdLine );
/* FIXME: check for pdb32 == NULL. */
pdb32->task = hTask;
if (pModule->flags & NE_FFLAGS_WIN32)
@@ -522,8 +522,8 @@
/*
LPTHREAD_START_ROUTINE start =
(LPTHREAD_START_ROUTINE)(
- pCurrentProcess->exe_modref->load_addr +
- pCurrentProcess->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
+ PROCESS_Current()->exe_modref->load_addr +
+ PROCESS_Current()->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
*/
pTask->thdb = THREAD_Create( pdb32,
PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve,
@@ -541,11 +541,11 @@
stack32Top = (char*)pTask->thdb->teb.stack_top;
frame32 = (STACK32FRAME *)stack32Top - 1;
- frame32->edi = 0;
- frame32->esi = 0;
- frame32->edx = 0;
- frame32->ecx = 0;
- frame32->ebx = 0;
+ frame32->edi = 0;
+ frame32->esi = 0;
+ frame32->edx = 0;
+ frame32->ecx = 0;
+ frame32->ebx = 0;
frame32->retaddr = (DWORD)TASK_CallToStart;
/* The remaining fields will be initialized in TASK_Reschedule */
@@ -555,9 +555,9 @@
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
sp &= ~1;
pTask->ss_sp = PTR_SEG_OFF_TO_SEGPTR( hInstance, sp );
- pTask->ss_sp -= sizeof(STACK16FRAME) + sizeof(DWORD) /* for saved %esp */;
+ pTask->ss_sp -= sizeof(STACK16FRAME);
frame16 = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->ss_sp );
- frame16->saved_ss_sp = 0;
+ frame16->frame32 = frame32;
frame16->ebp = sp + (int)&((STACK16FRAME *)0)->bp;
frame16->bp = LOWORD(frame16->ebp);
frame16->ds = frame16->es = pTask->hInstance;
@@ -565,8 +565,6 @@
frame16->entry_cs = 0;
/* The remaining fields will be initialized in TASK_Reschedule */
- *(STACK32FRAME **)(frame16 + 1) = frame32; /* Store the 32-bit %esp */
-
/* If there's no 16-bit stack yet, use a part of the new task stack */
/* This is only needed to have a stack to switch from on the first */
/* call to DirectedYield(). */
@@ -775,8 +773,8 @@
if (!newframe16->entry_cs)
{
STACK16FRAME *oldframe16 = CURRENT_STACK16;
- STACK32FRAME *oldframe32 = *(STACK32FRAME **)(oldframe16 + 1);
- STACK32FRAME *newframe32 = *(STACK32FRAME **)(newframe16 + 1);
+ STACK32FRAME *oldframe32 = oldframe16->frame32;
+ STACK32FRAME *newframe32 = newframe16->frame32;
newframe16->entry_ip = oldframe16->entry_ip;
newframe16->entry_cs = oldframe16->entry_cs;
newframe16->ip = oldframe16->ip;
@@ -790,7 +788,6 @@
hCurrentTask = hTask;
SET_CUR_THREAD( pNewTask->thdb );
- pCurrentProcess = pNewTask->thdb->process;
IF1632_Saved16_ss_sp = pNewTask->ss_sp;
}
@@ -1197,7 +1194,7 @@
/* Build a stack frame for the return */
newFrame = CURRENT_STACK16;
- newFrame->saved_ss_sp = oldFrame->saved_ss_sp;
+ newFrame->frame32 = oldFrame->frame32;
if (debugging_relay)
{
newFrame->entry_ip = oldFrame->entry_ip;
diff --git a/memory/atom.c b/memory/atom.c
index 83d7a4c..dc82162 100644
--- a/memory/atom.c
+++ b/memory/atom.c
@@ -24,7 +24,6 @@
#ifdef CONFIG_IPC
#include "dde_atom.h"
-#include "options.h"
#endif
#define DEFAULT_ATOMTABLE_SIZE 37
@@ -399,9 +398,10 @@
{
if (!HIWORD(str)) return (ATOM)LOWORD(str); /* Integer atom */
#ifdef CONFIG_IPC
- if (Options.ipc) return DDE_GlobalAddAtom( str );
-#endif
+ return DDE_GlobalAddAtom( str );
+#else
return ATOM_AddAtom( USER_HeapSel, (LPCSTR)PTR_SEG_TO_LIN(str) );
+#endif
}
@@ -433,9 +433,10 @@
ATOM WINAPI GlobalDeleteAtom( ATOM atom )
{
#ifdef CONFIG_IPC
- if (Options.ipc) return DDE_GlobalDeleteAtom( atom );
-#endif
+ return DDE_GlobalDeleteAtom( atom );
+#else
return ATOM_DeleteAtom( USER_HeapSel, atom );
+#endif
}
@@ -446,9 +447,10 @@
{
if (!HIWORD(str)) return (ATOM)LOWORD(str); /* Integer atom */
#ifdef CONFIG_IPC
- if (Options.ipc) return DDE_GlobalFindAtom( str );
-#endif
+ return DDE_GlobalFindAtom( str );
+#else
return ATOM_FindAtom( USER_HeapSel, (LPCSTR)PTR_SEG_TO_LIN(str) );
+#endif
}
@@ -480,9 +482,10 @@
UINT16 WINAPI GlobalGetAtomName16( ATOM atom, LPSTR buffer, INT16 count )
{
#ifdef CONFIG_IPC
- if (Options.ipc) return DDE_GlobalGetAtomName( atom, buffer, count );
-#endif
+ return DDE_GlobalGetAtomName( atom, buffer, count );
+#else
return (UINT16)ATOM_GetAtomName( USER_HeapSel, atom, buffer, count );
+#endif
}
diff --git a/memory/global.c b/memory/global.c
index 0830c14..ecb6c95 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -18,7 +18,6 @@
#include "dde_mem.h"
#include "stackframe.h"
#include "module.h"
-#include "options.h"
#include "stddebug.h"
#include "debug.h"
#include "winerror.h"
@@ -124,7 +123,7 @@
pArena->size = GET_SEL_LIMIT(sel) + 1;
#ifdef CONFIG_IPC
- if ((flags & GMEM_DDESHARE) && Options.ipc)
+ if (flags & GMEM_DDESHARE)
{
pArena->handle = shmdata->handle;
pArena->shmid = shmdata->shmid;
@@ -200,7 +199,7 @@
/* Allocate the linear memory */
#ifdef CONFIG_IPC
- if ((flags & GMEM_DDESHARE) && Options.ipc)
+ if (flags & GMEM_DDESHARE)
ptr = DDE_malloc(flags, size, &shmdata);
else
#endif /* CONFIG_IPC */
@@ -297,7 +296,8 @@
if (!handle) return 0;
#ifdef CONFIG_IPC
- if (Options.ipc && (flags & GMEM_DDESHARE || is_dde_handle(handle))) {
+ if (flags & GMEM_DDESHARE || is_dde_handle(handle))
+ {
fprintf(stdnimp,
"GlobalReAlloc16: shared memory reallocating unimplemented\n");
return 0;
diff --git a/memory/selector.c b/memory/selector.c
index 410c0d5..28c8a61 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -182,7 +182,8 @@
{
if ((frame->ds >= sel) && (frame->ds < nextsel)) frame->ds = 0;
if ((frame->es >= sel) && (frame->es < nextsel)) frame->es = 0;
- frame = PTR_SEG_TO_LIN( frame->saved_ss_sp );
+ if (!frame->frame32) break;
+ frame = PTR_SEG_TO_LIN( frame->frame32->frame16 );
}
}
diff --git a/memory/virtual.c b/memory/virtual.c
index 9ffde82..65f17d4 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -660,7 +660,7 @@
PDB32 *pdb = (PDB32 *)PROCESS_GetObjPtr( handle, K32OBJ_PROCESS );
if (pdb)
{
- if (pdb == pCurrentProcess)
+ if (pdb == PROCESS_Current())
ret = VirtualProtect( addr, size, new_prot, old_prot );
else
fprintf(stderr,"Unsupported: VirtualProtectEx on other process\n");
@@ -743,7 +743,7 @@
PDB32 *pdb = (PDB32 *)PROCESS_GetObjPtr( handle, K32OBJ_PROCESS );
if (pdb)
{
- if (pdb == pCurrentProcess)
+ if (pdb == PROCESS_Current())
ret = VirtualQuery( addr, info, len );
else
fprintf(stderr,"Unsupported: VirtualQueryEx on other process\n");
diff --git a/misc/lstr.c b/misc/lstr.c
index 234ec07..1e54527 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -10,16 +10,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-
-#include "windows.h"
-#include "winnt.h" /* HEAP_ macros */
-#include "task.h"
-#include "heap.h"
-#include "ldt.h"
-#include "stackframe.h"
-#include "module.h"
-#include "stddebug.h"
-#include "debug.h"
+#include "config.h"
#ifdef HAVE_WCTYPE_H
# include <wctype.h>
@@ -32,6 +23,17 @@
# define iswlower(c) islower(c)
#endif /* HAVE_WCTYPE_H */
+
+#include "windows.h"
+#include "winnt.h" /* HEAP_ macros */
+#include "task.h"
+#include "heap.h"
+#include "ldt.h"
+#include "stackframe.h"
+#include "module.h"
+#include "stddebug.h"
+#include "debug.h"
+
/* Funny to divide them between user and kernel. */
/* be careful: always use functions from wctype.h if character > 255 */
diff --git a/misc/main.c b/misc/main.c
index cbc551b..ca68de1 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -81,7 +81,6 @@
FALSE,
FALSE, /* failReadOnly */
MODE_ENHANCED, /* Enhanced mode */
- FALSE, /* IPC enabled */
#ifdef DEFAULT_LANG
DEFAULT_LANG, /* Default language */
#else
@@ -99,7 +98,6 @@
{ "-depth", ".depth", XrmoptionSepArg, (caddr_t)NULL },
{ "-display", ".display", XrmoptionSepArg, (caddr_t)NULL },
{ "-iconic", ".iconic", XrmoptionNoArg, (caddr_t)"on" },
- { "-ipc", ".ipc", XrmoptionNoArg, (caddr_t)"off"},
{ "-language", ".language", XrmoptionSepArg, (caddr_t)"En" },
{ "-name", ".name", XrmoptionSepArg, (caddr_t)NULL },
{ "-perfect", ".perfect", XrmoptionNoArg, (caddr_t)"on" },
@@ -131,7 +129,6 @@
" -failreadonly Read only files may not be opened in write mode\n" \
" -fixedmap Use a \"standard\" color map\n" \
" -iconic Start as an icon\n" \
- " -ipc Enable IPC facilities\n" \
" -language xx Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It,Ko,\n Hu,Pl,Po)\n" \
" -managed Allow the window manager to manage created windows\n" \
" -mode mode Start Wine in a particular mode (standard or enhanced)\n" \
@@ -359,8 +356,6 @@
Options.debug = TRUE;
if (MAIN_GetResource( db, ".failreadonly", &value ))
Options.failReadOnly = TRUE;
- if (MAIN_GetResource( db, ".ipc", &value ))
- Options.ipc = TRUE;
if (MAIN_GetResource( db, ".perfect", &value ))
Options.perfectGraphics = TRUE;
if (MAIN_GetResource( db, ".depth", &value))
@@ -537,8 +532,6 @@
int *depth_list;
struct timeval tv;
- extern int _WinMain(int argc, char **argv);
-
#ifdef MALLOC_DEBUGGING
char *trace;
diff --git a/misc/port.c b/misc/port.c
index f98a951..657450e 100644
--- a/misc/port.c
+++ b/misc/port.c
@@ -57,3 +57,36 @@
return sys_errlist[err];
}
#endif /* HAVE_STRERROR */
+
+#if !defined(HAVE_CLONE) && defined(__linux__)
+#include <assert.h>
+#include <errno.h>
+#include <syscall.h>
+int clone( int (*fn)(void *), void *stack, int flags, void *arg )
+{
+#ifdef __i386__
+ int ret;
+ void **stack_ptr = (void **)stack;
+ *--stack_ptr = arg; /* Push argument on stack */
+ *--stack_ptr = fn; /* Push function pointer (popped into ebx) */
+ __asm__ __volatile__( "pushl %%ebx\n\t"
+ "movl %2,%%ebx\n\t"
+ "int $0x80\n\t"
+ "popl %%ebx\n\t" /* Contains fn in the child */
+ "testl %%eax,%%eax\n\t"
+ "jnz 0f\n\t"
+ "call *%%ebx\n\t" /* Should never return */
+ "xorl %%eax,%%eax\n\t" /* Just in case it does*/
+ "0:"
+ : "=a" (ret)
+ : "0" (SYS_clone), "g" (flags), "c" (stack_ptr) );
+ assert( ret ); /* If ret is 0, we returned from the child function */
+ if (ret > 0) return ret;
+ errno = -ret;
+ return -1;
+#else
+ errno = EINVAL;
+ return -1;
+#endif /* __i386__ */
+}
+#endif /* !HAVE_CLONE && __linux__ */
diff --git a/misc/registry.c b/misc/registry.c
index 90e233c..9aa04ce 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -18,6 +18,7 @@
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <pwd.h>
+#include <assert.h>
#include <time.h>
#include "windows.h"
#include "win.h"
@@ -587,6 +588,11 @@
LPKEYVALUE val=NULL;
int i;
+ if (name && !*name) {/* empty string equals default (NULL) value */
+ free(name);
+ name = NULL;
+ }
+
for (i=0;i<lpkey->nrofvalues;i++) {
val=lpkey->values+i;
if (name==NULL) {
@@ -711,7 +717,10 @@
}
*ws = 0;
ws = *str;
- *str = strdupW(*str);
+ if (*ws)
+ *str = strdupW(*str);
+ else
+ *str = NULL;
free(ws);
return s;
}
@@ -1038,7 +1047,10 @@
int len;
name = strdupA2W(key->values[i].name);
- if (!*name) name = NULL;
+ if (!*name) {
+ free(name);
+ name = NULL;
+ }
free(key->values[i].name);
len = key->values[i].datalen;
@@ -2085,6 +2097,8 @@
lpkey = lookup_hkey(hkey);
if (!lpkey)
return SHELL_ERROR_BADKEY;
+ if (lpszValueName && !*lpszValueName)
+ lpszValueName = NULL;
if (lpszValueName==NULL) {
for (i=0;i<lpkey->nrofvalues;i++)
if (lpkey->values[i].name==NULL)
@@ -2726,9 +2740,8 @@
memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
*lpcchValue=lstrlen32W(val->name)*2+2;
} else {
- /* how to handle NULL value? */
*lpszValue = 0;
- *lpcchValue = 2;
+ *lpcchValue = 0;
}
if (lpdwType)
*lpdwType=val->type;
diff --git a/misc/ver.c b/misc/ver.c
index 40c3241..c19e5f3 100644
--- a/misc/ver.c
+++ b/misc/ver.c
@@ -168,7 +168,7 @@
static int read_xx_header(HFILE32 lzfd) {
IMAGE_DOS_HEADER mzh;
- char magic[2];
+ char magic[3];
LZSeek32(lzfd,0,SEEK_SET);
if (sizeof(mzh)!=LZRead32(lzfd,&mzh,sizeof(mzh)))
@@ -183,7 +183,8 @@
return IMAGE_OS2_SIGNATURE;
if (magic[0] == 'P' && magic[1] == 'E')
return IMAGE_NT_SIGNATURE;
- fprintf(stderr,"misc/ver.c:read_ne_header:can't handle %*s files.\n",2,magic);
+ magic[2]='\0';
+ fprintf(stderr,"misc/ver.c:read_ne_header:can't handle %s files.\n",magic);
return 0;
}
@@ -727,7 +728,7 @@
strcpy(curDir, "");
strcpy(destDir, "");
- if(flags & VFFF_ISSHAREDFILE && !getuid()) {
+ if(flags & VFFF_ISSHAREDFILE) {
GetSystemDirectory32A(destDir, 256);
/* Were we given a filename? If so, try to find the file. */
diff --git a/misc/version.c b/misc/version.c
index dafa443..e62438e 100644
--- a/misc/version.c
+++ b/misc/version.c
@@ -114,17 +114,15 @@
if (versionForced) /* user has overridden any sensible checks */
return defaultVersion;
- if (!pCurrentProcess) /* at startuptime probably */
- return defaultVersion;
- if (!pCurrentProcess->exe_modref)
+ if (!PROCESS_Current()->exe_modref)
{
/* HACK: if we have loaded a PE image into this address space,
* we are probably using thunks, so Win95 is our best bet
*/
- if (pCurrentProcess->modref_list) return WIN95;
+ if (PROCESS_Current()->modref_list) return WIN95;
return WIN31; /* FIXME: hmm, look at DDB.version ? */
}
- peheader = PE_HEADER(pCurrentProcess->exe_modref->module);
+ peheader = PE_HEADER(PROCESS_Current()->exe_modref->module);
if (peheader->OptionalHeader.MajorSubsystemVersion == 4)
/* FIXME: NT4 has the same majorversion; add a check here for it. */
return WIN95;
diff --git a/msdos/int2f.c b/msdos/int2f.c
index 755e05b..c8efcab 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -41,6 +41,25 @@
do_int2f_16( context );
break;
+ case 0x45:
+ switch (AL_reg(context))
+ {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ /* Microsoft Profiler - not installed */
+ break;
+ default:
+ INT_BARF( context, 0x2f );
+ }
+ break;
+
case 0x4a:
switch(AL_reg(context))
{
diff --git a/multimedia/Makefile.in b/multimedia/Makefile.in
index f4a288f..cc7446d 100644
--- a/multimedia/Makefile.in
+++ b/multimedia/Makefile.in
@@ -15,6 +15,7 @@
midi.c \
mixer.c \
mmaux.c \
+ mmio.c \
mmsystem.c \
time.c
diff --git a/multimedia/audio.c b/multimedia/audio.c
index 58d8365..8abae8c 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -1,5 +1,5 @@
/*
- * Sample Wine Driver for Linux
+ * Sample Wine Driver for Open Sound System (featured in Linux and FreeBSD)
*
* Copyright 1994 Martin Ayotte
*/
@@ -24,17 +24,12 @@
#include "mmsystem.h"
#include "heap.h"
#include "ldt.h"
-
-#ifdef linux
-#include <linux/soundcard.h>
-#elif __FreeBSD__
-#include <machine/soundcard.h>
-#endif
-
#include "stddebug.h"
#include "debug.h"
-#if defined(linux) || defined(__FreeBSD__)
+#ifdef HAVE_OSS
+#include <sys/soundcard.h>
+
#define SOUND_DEV "/dev/dsp"
#define MIXER_DEV "/dev/mixer"
@@ -62,7 +57,7 @@
typedef struct {
int unixdev;
int state;
- DWORD bufsize; /* Linux '/dev/dsp' give us that size */
+ DWORD bufsize; /* OpenSound '/dev/dsp' give us that size */
WAVEOPENDESC waveDesc;
WORD wFlags;
PCMWAVEFORMAT Format;
@@ -749,17 +744,17 @@
lpParms->lpstrReturn = NULL;
switch(dwFlags) {
case MCI_INFO_PRODUCT:
- lpParms->lpstrReturn = "Linux Sound System 0.5";
+ lpParms->lpstrReturn = "Open Sound System 0.5";
break;
case MCI_INFO_FILE:
lpParms->lpstrReturn =
(LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
break;
case MCI_WAVE_INPUT:
- lpParms->lpstrReturn = "Linux Sound System 0.5";
+ lpParms->lpstrReturn = "Open Sound System 0.5";
break;
case MCI_WAVE_OUTPUT:
- lpParms->lpstrReturn = "Linux Sound System 0.5";
+ lpParms->lpstrReturn = "Open Sound System 0.5";
break;
default:
return MCIERR_UNRECOGNIZED_COMMAND;
@@ -799,7 +794,7 @@
#else
lpCaps->wMid = 0x00FF; /* Manufac ID */
lpCaps->wPid = 0x0001; /* Product ID */
- strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
+ strcpy(lpCaps->szPname, "OpenSoundSystem WAVOUT Driver");
#endif
lpCaps->vDriverVersion = 0x0100;
lpCaps->dwFormats = 0x00000000;
@@ -1213,8 +1208,6 @@
return MMSYSERR_NOERROR;
}
-#endif /* linux || __FreeBSD__*/
-
/**************************************************************************
* wodMessage [sample driver]
*/
@@ -1223,7 +1216,6 @@
{
dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
-#if defined(linux) || defined(__FreeBSD__)
switch(wMsg) {
case WODM_OPEN:
return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
@@ -1267,16 +1259,11 @@
dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
}
return MMSYSERR_NOTSUPPORTED;
-#else
- return MMSYSERR_NOTENABLED;
-#endif
}
/*-----------------------------------------------------------------------*/
-#if defined(linux) || defined(__FreeBSD__)
-
/**************************************************************************
* widGetDevCaps [internal]
*/
@@ -1297,7 +1284,7 @@
#else
lpCaps->wMid = 0x00FF; /* Manufac ID */
lpCaps->wPid = 0x0001; /* Product ID */
- strcpy(lpCaps->szPname, "Linux WAVIN Driver");
+ strcpy(lpCaps->szPname, "OpenSoundSystem WAVIN Driver");
#endif
lpCaps->dwFormats = 0x00000000;
lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
@@ -1688,8 +1675,6 @@
return MMSYSERR_NOERROR;
}
-#endif /* linux || __FreeBSD__ */
-
/**************************************************************************
* widMessage [sample driver]
*/
@@ -1698,7 +1683,6 @@
{
dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
-#if defined(linux) || defined(__FreeBSD__)
switch(wMsg) {
case WIDM_OPEN:
return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
@@ -1728,9 +1712,6 @@
dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
}
return MMSYSERR_NOTSUPPORTED;
-#else
- return MMSYSERR_NOTENABLED;
-#endif
}
@@ -1740,7 +1721,6 @@
LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
-#if defined(linux) || defined(__FreeBSD__)
dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
dwDevID, hDriv, wMsg, dwParam1, dwParam2);
switch(wMsg) {
@@ -1831,7 +1811,39 @@
default:
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
}
-#else
return MMSYSERR_NOTENABLED;
-#endif
}
+
+#else /* !HAVE_OSS */
+
+/**************************************************************************
+ * wodMessage [sample driver]
+ */
+DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
+ DWORD dwParam1, DWORD dwParam2)
+{
+ fprintf(stderr,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
+ wDevID, wMsg, dwUser, dwParam1, dwParam2);
+ return MMSYSERR_NOTENABLED;
+}
+
+/**************************************************************************
+ * widMessage [sample driver]
+ */
+DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
+ DWORD dwParam1, DWORD dwParam2)
+{
+ fprintf(stderr,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
+ wDevID, wMsg, dwUser, dwParam1, dwParam2);
+ return MMSYSERR_NOTENABLED;
+}
+
+/**************************************************************************
+ * AUDIO_DriverProc [sample driver]
+ */
+LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
+ DWORD dwParam1, DWORD dwParam2)
+{
+ return MMSYSERR_NOTENABLED;
+}
+#endif /* HAVE_OSS */
diff --git a/multimedia/dsound.c b/multimedia/dsound.c
index 5b3983b..fafa959 100644
--- a/multimedia/dsound.c
+++ b/multimedia/dsound.c
@@ -1,20 +1,120 @@
-/* DS
+/* DirectSound
+ *
+ * Copyright 1998 Marcus Meissner
+ */
+/*
+ * Note: This file requires multithread ability. It is not possible to
+ * implement the stuff in a single thread anyway. And most DirectX apps
+ * require threading themselves.
+ *
+ * FIXME: This file is full of race conditions and unlocked variable access
+ * from two threads. But we usually don't need to bother.
+ *
*/
#include <stdio.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <sys/signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
#include "windows.h"
+#include "winerror.h"
#include "interfaces.h"
#include "mmsystem.h"
#include "dsound.h"
+#ifdef HAVE_OSS
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+static int audiofd = 0;
+static LPDIRECTSOUND dsound = NULL;
+#endif
+
HRESULT WINAPI DirectSoundEnumerate32A(LPDSENUMCALLBACK32A enumcb,LPVOID context) {
return 0;
}
+#ifdef HAVE_OSS
+static void _dump_DSBCAPS(DWORD xmask) {
+ struct {
+ DWORD mask;
+ char *name;
+ } flags[] = {
+#define FE(x) { x, #x },
+ FE(DSBCAPS_PRIMARYBUFFER)
+ FE(DSBCAPS_STATIC)
+ FE(DSBCAPS_LOCHARDWARE)
+ FE(DSBCAPS_LOCSOFTWARE)
+ FE(DSBCAPS_CTRLFREQUENCY)
+ FE(DSBCAPS_CTRLPAN)
+ FE(DSBCAPS_CTRLVOLUME)
+ FE(DSBCAPS_CTRLDEFAULT)
+ FE(DSBCAPS_CTRLALL)
+ FE(DSBCAPS_STICKYFOCUS)
+ FE(DSBCAPS_GETCURRENTPOSITION2)
+ };
+ int i;
+
+ for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
+ if (flags[i].mask & xmask)
+ fprintf(stderr,"%s ",flags[i].name);
+}
+
static HRESULT WINAPI IDirectSoundBuffer_SetFormat(
LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX wfex
) {
+ int xx,channels,speed,format,nformat;
+
fprintf(stderr,"IDirectSoundBuffer(%p)->SetFormat(%p),stub!\n",this,wfex);
+ memcpy(&(this->wfx),wfex,sizeof(this->wfx));
+ fprintf(stderr," [formattag=0x%04x,",wfex->wFormatTag);
+ fprintf(stderr,"chans=%d,",wfex->nChannels);
+ fprintf(stderr,"samplerate=%ld,",wfex->nSamplesPerSec);
+ fprintf(stderr,"bytespersec=%ld,",wfex->nAvgBytesPerSec);
+ fprintf(stderr,"blockalign=%d,",wfex->nBlockAlign);
+ fprintf(stderr,"bitspersamp=%d,",wfex->wBitsPerSample);
+ fprintf(stderr,"cbSize=%d]\n",wfex->cbSize);
+
+ switch (wfex->wFormatTag) {
+ default:
+ fprintf(stderr,"unknown WAVE_FORMAT tag %d\n",wfex->wFormatTag);
+ return DSERR_BADFORMAT;
+ case WAVE_FORMAT_PCM:
+ format = AFMT_S16_LE;
+ break;
+ }
+ if (-1==ioctl(audiofd,SNDCTL_DSP_GETFMTS,&xx)) {
+ perror("ioctl SNDCTL_DSP_GETFMTS");
+ return DSERR_BADFORMAT;
+ }
+ if ((xx&format)!=format) {/* format unsupported */
+ fprintf(stderr,"SNDCTL_DSP_GETFMTS: format not supported\n");
+ return DSERR_BADFORMAT;
+ }
+ nformat = format;
+ if (-1==ioctl(audiofd,SNDCTL_DSP_SETFMT,&nformat)) {
+ perror("ioctl SNDCTL_DSP_SETFMT");
+ return DSERR_BADFORMAT;
+ }
+ if (nformat!=format) {/* didn't work */
+ fprintf(stderr,"SNDCTL_DSP_GETFMTS: format not set\n");
+ return DSERR_BADFORMAT;
+ }
+
+ channels = wfex->nChannels-1;
+ if (-1==ioctl(audiofd,SNDCTL_DSP_STEREO,&channels)) {
+ perror("ioctl SNDCTL_DSP_STEREO");
+ return DSERR_BADFORMAT;
+ }
+ speed = wfex->nSamplesPerSec;
+ if (-1==ioctl(audiofd,SNDCTL_DSP_SPEED,&speed)) {
+ perror("ioctl SNDCTL_DSP_SPEED");
+ return DSERR_BADFORMAT;
+ }
return 0;
}
@@ -41,28 +141,44 @@
}
static HRESULT WINAPI IDirectSoundBuffer_Play(
- LPDIRECTSOUNDBUFFER this,DWORD x,DWORD y,DWORD z
+ LPDIRECTSOUNDBUFFER this,DWORD reserved1,DWORD reserved2,DWORD flags
) {
+
fprintf(stderr,"IDirectSoundBuffer(%p)->Play(%08lx,%08lx,%08lx),stub!\n",
- this,x,y,z
+ this,reserved1,reserved2,flags
);
+ this->playing = 1;
return 0;
}
static HRESULT WINAPI IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER this) {
- fprintf(stderr,"IDirectSoundBuffer(%p)->Stop()\n",this);
+ /*fprintf(stderr,"IDirectSoundBuffer(%p)->Stop()\n",this);*/
+ this->playing = 0;
return 0;
}
static DWORD WINAPI IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER this) {
- fprintf(stderr,"IDirectSoundBuffer(%p)->AddRef()\n",this);
return ++(this->ref);
}
static DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) {
- fprintf(stderr,"IDirectSoundBuffer(%p)->Release(),stub!\n",this);
+ int i;
+
if (--this->ref)
return this->ref;
fprintf(stderr," -> IDirectSoundBuffer(%p) freed.\n",this);
+ for (i=0;i<this->dsound->nrofbuffers;i++)
+ if (this->dsound->buffers[i] == this)
+ break;
+ if (i < this->dsound->nrofbuffers) {
+ memcpy(
+ this->dsound->buffers+i,
+ this->dsound->buffers+i+1,
+ sizeof(LPDIRECTSOUNDBUFFER)*(this->dsound->nrofbuffers-i-1)
+ );
+ this->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,this->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER)*this->dsound->nrofbuffers);
+ this->dsound->nrofbuffers--;
+ this->dsound->lpvtbl->fnRelease(this->dsound);
+ }
HeapFree(GetProcessHeap(),0,this);
return 0;
}
@@ -70,7 +186,11 @@
static HRESULT WINAPI IDirectSoundBuffer_GetCurrentPosition(
LPDIRECTSOUNDBUFFER this,LPDWORD playpos,LPDWORD writepos
) {
- fprintf(stderr,"IDirectSoundBuffer(%p)->GetCurrentPosition(%p,%p),stub!\n",this,playpos,writepos);
+/* fprintf(stderr,"IDirectSoundBuffer(%p)->GetCurrentPosition(%p,%p),stub!\n",this,playpos,writepos);*/
+
+ if (playpos) *playpos = this->playpos;
+ this->writepos = (this->playpos+512) % this->buflen;
+ if (writepos) *writepos = this->writepos; /* hmm */
return 0;
}
@@ -78,17 +198,85 @@
LPDIRECTSOUNDBUFFER this,LPDWORD status
) {
fprintf(stderr,"IDirectSoundBuffer(%p)->GetStatus(%p),stub!\n",this,status);
- *status = 0; /* hmm. set playing? or not ? */
+ if (this->playing)
+ *status = DSBSTATUS_PLAYING;
+ *status |= DSBSTATUS_LOOPING; /* FIXME */
+ return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_GetFormat(
+ LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
+) {
+ fprintf(stderr,"IDirectSoundBuffer(%p)->GetFormat(%p,0x%08lx,%p),stub!\n",this,lpwf,wfsize,wfwritten);
+ if (wfsize>sizeof(this->wfx)) wfsize = sizeof(this->wfx);
+ memcpy(lpwf,&(this->wfx),wfsize);
+ if (wfwritten) *wfwritten = wfsize;
return 0;
}
static HRESULT WINAPI IDirectSoundBuffer_Lock(
- LPDIRECTSOUNDBUFFER this,DWORD x1,DWORD x2,LPVOID p1,LPDWORD x3,LPVOID p2,LPDWORD x4,DWORD x5
+ LPDIRECTSOUNDBUFFER this,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
) {
- fprintf(stderr,"IDirectSoundBuffer(%p)->Lock(0x%08lx,0x%08lx,%p,%p,%p,%p,0x%08lx,),stub!\n",this,x1,x2,p1,x3,p2,x4,x5);
- return 0x80000000;
+
+/*
+ fprintf(stderr,"IDirectSoundBuffer(%p)->Lock(%ld,%ld,%p,%p,%p,%p,0x%08lx),stub!\n",
+ this,
+ writecursor,
+ writebytes,
+ lplpaudioptr1,
+ audiobytes1,
+ lplpaudioptr2,
+ audiobytes2,
+ flags
+ );
+*/
+ if (flags & DSBLOCK_FROMWRITECURSOR)
+ writecursor = this->writepos;
+
+ if (writecursor+writebytes < this->buflen) {
+ *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
+ *audiobytes1 = writebytes;
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = NULL;
+ if (audiobytes2)
+ *audiobytes2 = 0;
+ } else {
+ *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
+ *audiobytes1 = this->buflen-writecursor;
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = this->buffer;
+ if (audiobytes2)
+ *audiobytes2 = writebytes-(this->buflen-writecursor);
+ }
+ this->writepos=(writecursor+writebytes)%this->buflen;
+ return 0;
}
+static HRESULT WINAPI IDirectSoundBuffer_SetCurrentPosition(
+ LPDIRECTSOUNDBUFFER this,DWORD newpos
+) {
+ fprintf(stderr,"IDirectSoundBuffer(%p)->SetCurrentPosition(%ld)\n",this,newpos);
+ this->playpos = newpos;
+ return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_SetPan(
+ LPDIRECTSOUNDBUFFER this,LONG newpan
+) {
+ fprintf(stderr,"IDirectSoundBuffer(%p)->SetPan(%ld),stub!\n",this,newpan);
+ return 0;
+}
+
+static HRESULT WINAPI IDirectSoundBuffer_Unlock(
+ LPDIRECTSOUNDBUFFER this,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
+) {
+ struct count_info ci;
+/*
+ fprintf(stderr,"IDirectSoundBuffer(%p)->Unlock(%p,%ld,%p,%ld),stub!\n",this,p1,x1,p2,x2);
+ */
+ fprintf(stderr,"u%ld.%ld,",x1,x2);
+ return 0;
+}
static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = {
(void *)1,
@@ -96,7 +284,7 @@
IDirectSoundBuffer_Release,
(void *)4,
IDirectSoundBuffer_GetCurrentPosition,
- (void *)6,
+ IDirectSoundBuffer_GetFormat,
IDirectSoundBuffer_GetVolume,
(void *)8,
(void *)9,
@@ -104,13 +292,13 @@
(void *)11,
IDirectSoundBuffer_Lock,
IDirectSoundBuffer_Play,
- (void *)14,
+ IDirectSoundBuffer_SetCurrentPosition,
IDirectSoundBuffer_SetFormat,
IDirectSoundBuffer_SetVolume,
- (void *)17,
+ IDirectSoundBuffer_SetPan,
IDirectSoundBuffer_SetFrequency,
IDirectSoundBuffer_Stop,
- (void *)20
+ IDirectSoundBuffer_Unlock
};
@@ -128,27 +316,70 @@
static HRESULT WINAPI IDirectSound_CreateSoundBuffer(
LPDIRECTSOUND this,LPDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk
) {
- fprintf(stderr,"IDirectSound(%p)->CreateBuffer(%p,%p,%p),stub!\n",this,dsbd,ppdsb,lpunk);
+ fprintf(stderr,"IDirectSound(%p)->CreateSoundBuffer(%p,%p,%p),stub!\n",this,dsbd,ppdsb,lpunk);
+ fprintf(stderr,"[size=%ld,",dsbd->dwSize);
+ fprintf(stderr,"flags = 0x%08lx,",dsbd->dwFlags);
+ _dump_DSBCAPS(dsbd->dwFlags);
+ fprintf(stderr,"bufferbytes = %ld,",dsbd->dwBufferBytes);
+ fprintf(stderr,"lpwfxFormat = %p]\n",dsbd->lpwfxFormat);
*ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBuffer));
(*ppdsb)->ref =1;
+ (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsbd->dwBufferBytes);
+ (*ppdsb)->buflen = dsbd->dwBufferBytes;
+ (*ppdsb)->playpos = 0;
+ (*ppdsb)->writepos = 0;
(*ppdsb)->lpvtbl = &dsbvt;
+ (*ppdsb)->dsound = this;
+ (*ppdsb)->playing = 0;
+
+ /* register buffer */
+ this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
+ this->buffers[this->nrofbuffers] = *ppdsb;
+ this->nrofbuffers++;
+ this->lpvtbl->fnAddRef(this);
+
+ if (dsbd->lpwfxFormat) dsbvt.fnSetFormat(*ppdsb,dsbd->lpwfxFormat);
return 0;
}
+static HRESULT WINAPI IDirectSound_DuplicateSoundBuffer(
+ LPDIRECTSOUND this,LPDIRECTSOUNDBUFFER pdsb,LPLPDIRECTSOUNDBUFFER ppdsb
+) {
+ fprintf(stderr,"IDirectSound(%p)->DuplicateSoundBuffer(%p,%p),stub!\n",this,pdsb,ppdsb);
+
+ *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBuffer));
+ (*ppdsb)->ref =1;
+ (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,pdsb->buflen);
+ (*ppdsb)->buflen = pdsb->buflen;
+ (*ppdsb)->playpos = 0;
+ (*ppdsb)->writepos = 0;
+ (*ppdsb)->lpvtbl = &dsbvt;
+ (*ppdsb)->dsound = this;
+ dsbvt.fnSetFormat(*ppdsb,&(pdsb->wfx));
+ /* register buffer */
+ this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
+ this->buffers[this->nrofbuffers] = *ppdsb;
+ this->nrofbuffers++;
+ this->lpvtbl->fnAddRef(this);
+ return 0;
+}
+
+
static HRESULT WINAPI IDirectSound_GetCaps(LPDIRECTSOUND this,LPDSCAPS dscaps) {
fprintf(stderr,"IDirectSound(%p)->GetCaps(%p),stub!\n",this,dscaps);
+ fprintf(stderr," flags = 0x%08lx\n",dscaps->dwFlags);
return 0;
}
static ULONG WINAPI IDirectSound_AddRef(LPDIRECTSOUND this) {
- fprintf(stderr,"IDirectSound(%p)->AddRef()\n",this);
return ++(this->ref);
}
static ULONG WINAPI IDirectSound_Release(LPDIRECTSOUND this) {
- fprintf(stderr,"IDirectSound(%p)->Release()\n",this);
if (!--(this->ref)) {
HeapFree(GetProcessHeap(),0,this);
+ fprintf(stderr," IDIrectSound(%p) freed!\n",this);
+ dsound = NULL;
return 0;
}
return this->ref;
@@ -160,7 +391,7 @@
IDirectSound_Release,
IDirectSound_CreateSoundBuffer,
IDirectSound_GetCaps,
- (void *)6,
+ IDirectSound_DuplicateSoundBuffer,
IDirectSound_SetCooperativeLevel,
(void *)8,
(void *)9,
@@ -168,10 +399,98 @@
(void *)11
};
+void
+DSOUND_thread(void) {
+ int res,i,j,curleft,playing;
+ short buf[512];
+
+ while (1) {
+ if (!dsound) {
+ fprintf(stderr,"DSOUND thread killed\n");
+ kill(getpid(),SIGTERM);
+ return;
+ }
+ dsound->lpvtbl->fnAddRef(dsound);
+ memset(buf,0,sizeof(buf));
+ /* FIXME: assumes 16 bit and same format on all buffers
+ * which must not be the case
+ */
+ playing = 0;
+ for (i=dsound->nrofbuffers;i--;) {
+
+ dsound->buffers[i]->lpvtbl->fnAddRef(dsound->buffers[i]);
+ if ( dsound->buffers[i]->buflen &&
+ dsound->buffers[i]->playing
+ ) {
+ int playpos = dsound->buffers[i]->playpos/sizeof(short);
+ int buflen = dsound->buffers[i]->buflen/sizeof(short);
+ short *xbuf = (short*)(dsound->buffers[i]->buffer);
+
+ playing++;
+ dsound->buffers[i]->playpos = (sizeof(buf)+(playpos<<1))%(buflen<<1);
+ for (j=0;j<sizeof(buf)/sizeof(short);j++)
+ buf[j]+=xbuf[(j+playpos)%buflen];
+ }
+ dsound->buffers[i]->lpvtbl->fnRelease(dsound->buffers[i]);
+ }
+ dsound->lpvtbl->fnRelease(dsound);
+ /*fputc('0'+playing,stderr);*/
+ curleft = 0;
+ while (curleft < sizeof(buf)) {
+ res = write(audiofd,(LPBYTE)buf+curleft,sizeof(buf)-curleft);
+ if (res==-1) {
+ perror("write audiofd");
+ fprintf(stderr,"buf is %p, curleft is %d\n",buf,curleft);
+ kill(getpid(),SIGTERM);
+ break;
+ }
+ curleft+=res;
+ }
+ }
+}
+
+#endif /* HAVE_OSS */
+
HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) {
+#ifdef HAVE_OSS
+ int xx;
+
fprintf(stderr,"DirectSoundCreate(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter);
+ if (audiofd)
+ return DSERR_ALLOCATED;
+ audiofd = open("/dev/audio",O_WRONLY);
+ if (audiofd==-1) {
+ perror("open /dev/audio");
+ audiofd=0;
+ return DSERR_NODRIVER;
+ }
+ /* make it nonblocking */
+ if (-1==ioctl(audiofd,SNDCTL_DSP_NONBLOCK,NULL)) {
+ perror("ioctl SNDCTL_DSP_NONBLOCK");
+ close(audiofd);
+ audiofd=0;
+ return DSERR_NODRIVER;
+ }
+ if (-1==ioctl(audiofd,SNDCTL_DSP_GETCAPS,&xx)) {
+ perror("ioctl SNDCTL_DSP_GETCAPS");
+ close(audiofd);
+ audiofd=0;
+ return DSERR_NODRIVER;
+ }
+ fprintf(stderr,"SNDCTL_DSP_GETCAPS returned %x\n",xx);
*ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound));
- (*ppDS)->ref = 1;
- (*ppDS)->lpvtbl = &dsvt;
+ (*ppDS)->ref = 1;
+ (*ppDS)->lpvtbl = &dsvt;
+ (*ppDS)->buffers = NULL;
+ (*ppDS)->nrofbuffers = 0;
+
+ if (!dsound) {
+ dsound = (*ppDS);
+/* THREAD_CreateSysThread(0,DSOUND_thread); FIXME */
+ }
return 0;
+#else
+ MessageBox32A(0,"DirectSound needs the Open Sound System Driver, which has not been found by ./configure.","WINE DirectSound",MB_OK|MB_ICONSTOP);
+ return DSERR_NODRIVER; /* check */
+#endif
}
diff --git a/multimedia/mmio.c b/multimedia/mmio.c
new file mode 100644
index 0000000..d140fe1
--- /dev/null
+++ b/multimedia/mmio.c
@@ -0,0 +1,674 @@
+/*
+ * MMIO functions
+ *
+ * Copyright 1998 Andrew Taylor
+ *
+ * NOTES: I/O is still unbuffered; mmioSetBuffer must be implemented
+ * and mmio{Read,Write,Seek,others?} need buffer support.
+ * Buffering should almost give us memory files for free.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "windows.h"
+#include "win.h"
+#include "heap.h"
+#include "user.h"
+#include "file.h"
+#include "mmsystem.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+/**************************************************************************
+* mmioDosIOProc [internal]
+*/
+static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
+ dprintf_mmio(stddeb, "mmioDosIOProc(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
+
+ switch (uMessage) {
+
+ case MMIOM_OPEN: {
+ /* Parameters:
+ * lParam1 = szFileName parameter from mmioOpen
+ * lParam2 = unused
+ * Returns: zero on success, error code on error
+ * NOTE: lDiskOffset automatically set to zero
+ */
+
+ OFSTRUCT ofs;
+ LPSTR szFileName = (LPSTR) lParam1;
+
+ if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
+ dprintf_mmio(stdnimp, "mmioDosIOProc // MMIO_GETTEMP not implemented\n");
+ return MMIOERR_CANNOTOPEN;
+ }
+
+ /* if filename NULL, assume open file handle in adwInfo[0] */
+ if (!szFileName)
+ return 0;
+
+ lpmmioinfo->adwInfo[0] =
+ (DWORD) OpenFile32(szFileName, &ofs, lpmmioinfo->dwFlags);
+ if (lpmmioinfo->adwInfo[0] == -1)
+ return MMIOERR_CANNOTOPEN;
+
+ return 0;
+ }
+
+ case MMIOM_CLOSE: {
+ /* Parameters:
+ * lParam1 = wFlags parameter from mmioClose
+ * lParam2 = unused
+ * Returns: zero on success, error code on error
+ */
+
+ UINT16 uFlags = (UINT16) lParam1;
+
+ if (uFlags & MMIO_FHOPEN)
+ return 0;
+
+ _lclose32((HFILE32)lpmmioinfo->adwInfo[0]);
+ return 0;
+
+ }
+
+ case MMIOM_READ: {
+ /* Parameters:
+ * lParam1 = huge pointer to read buffer
+ * lParam2 = number of bytes to read
+ * Returns: number of bytes read, 0 for EOF, -1 for error (error code
+ * in wErrorRet)
+ * NOTE: lDiskOffset should be updated
+ */
+
+ HPSTR pch = (HPSTR) lParam1;
+ LONG cch = (LONG) lParam2;
+ LONG count;
+
+ count = _lread32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
+ if (count != -1)
+ lpmmioinfo->lDiskOffset += count;
+
+ return count;
+ }
+
+ case MMIOM_WRITE:
+ case MMIOM_WRITEFLUSH: {
+ /* no internal buffering, so WRITEFLUSH handled same as WRITE */
+
+ /* Parameters:
+ * lParam1 = huge pointer to write buffer
+ * lParam2 = number of bytes to write
+ * Returns: number of bytes written, -1 for error (error code in
+ * wErrorRet)
+ * NOTE: lDiskOffset should be updated
+ */
+
+ HPSTR pch = (HPSTR) lParam1;
+ LONG cch = (LONG) lParam2;
+ LONG count;
+
+ count = _hwrite16((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
+ if (count != -1)
+ lpmmioinfo->lDiskOffset += count;
+
+ return count;
+ }
+
+ case MMIOM_SEEK: {
+ /* Parameters:
+ * lParam1 = new position
+ * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
+ * Returns: new file postion, -1 on error
+ * NOTE: lDiskOffset should be updated
+ */
+
+ LONG Offset = (LONG) lParam1;
+ LONG Whence = (LONG) lParam2;
+ LONG pos;
+
+ pos = _llseek32((HFILE32)lpmmioinfo->adwInfo[0], Offset, Whence);
+ if (pos != -1)
+ lpmmioinfo->lDiskOffset = pos;
+
+ return pos;
+ }
+
+ case MMIOM_RENAME: {
+ /* Parameters:
+ * lParam1 = old name
+ * lParam2 = new name
+ * Returns: zero on success, non-zero on failure
+ */
+
+ dprintf_mmio(stddeb, "mmioDosIOProc: MMIOM_RENAME unimplemented\n");
+ return MMIOERR_FILENOTFOUND;
+ }
+
+ default:
+ dprintf_mmio(stddeb, "mmioDosIOProc: unexpected message %u\n", uMessage);
+ return 0;
+ }
+
+ return 0;
+}
+
+/**************************************************************************
+* mmioDosIOProc [internal]
+*/
+static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
+ return 0;
+}
+
+/**************************************************************************
+ * mmioOpenW [WINMM.123]
+ */
+HMMIO32 WINAPI mmioOpen32W(LPWSTR szFileName, MMIOINFO32 * lpmmioinfo,
+ DWORD dwOpenFlags)
+{
+ LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
+ HMMIO32 ret = mmioOpen16(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
+
+ HeapFree(GetProcessHeap(),0,szFn);
+ return ret;
+}
+
+/**************************************************************************
+ * mmioOpenA [WINMM.122]
+ */
+HMMIO32 WINAPI mmioOpen32A(LPSTR szFileName, MMIOINFO32 * lpmmioinfo,
+ DWORD dwOpenFlags)
+{
+ return mmioOpen16(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
+}
+
+/**************************************************************************
+ * mmioOpen [MMSYSTEM.1210]
+ */
+HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
+ DWORD dwOpenFlags)
+{
+ LPMMIOINFO16 lpmminfo;
+ HMMIO16 hmmio;
+ UINT16 result;
+
+ dprintf_mmio(stddeb, "mmioOpen('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
+
+ hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL)
+ return 0;
+ memset(lpmminfo, 0, sizeof(MMIOINFO16));
+
+ /* assume DOS file if not otherwise specified */
+ if (!lpmmioinfo ||
+ (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
+
+ lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
+ lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
+ }
+ /* if just the four character code is present, look up IO proc */
+ else if (lpmmioinfo->pIOProc == NULL) {
+
+ lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
+ lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
+
+ }
+ /* if IO proc specified, use it and specified four character code */
+ else {
+
+ lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
+ lpmminfo->pIOProc = lpmmioinfo->pIOProc;
+ }
+
+ if (dwOpenFlags & MMIO_ALLOCBUF) {
+ if ((result = mmioSetBuffer(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
+ if (lpmmioinfo)
+ lpmmioinfo->wErrorRet = result;
+ return 0;
+ }
+ }
+
+ lpmminfo->hmmio = hmmio;
+
+ /* call IO proc to actually open file */
+ result = (UINT16) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) 0);
+
+ GlobalUnlock16(hmmio);
+
+ if (result != 0) {
+ GlobalFree16(hmmio);
+ return 0;
+ }
+
+ return hmmio;
+}
+
+
+/**************************************************************************
+* mmioClose [MMSYSTEM.1211]
+*/
+UINT16 WINAPI mmioClose(HMMIO16 hmmio, UINT16 uFlags)
+{
+ LPMMIOINFO16 lpmminfo;
+ UINT16 result;
+
+ dprintf_mmio(stddeb, "mmioClose(%04X, %04X);\n", hmmio, uFlags);
+
+ lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
+ if (lpmminfo == NULL)
+ return 0;
+
+ /* flush the file - if error reported, ignore */
+ if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
+ lpmminfo->dwFlags &= ~MMIO_DIRTY;
+
+ result = (UINT16) mmioSendMessage(hmmio, MMIOM_CLOSE, (LPARAM) uFlags, (LPARAM) 0);
+
+ mmioSetBuffer(hmmio, NULL, 0, 0);
+
+ GlobalUnlock16(hmmio);
+ GlobalFree16(hmmio);
+
+ return result;
+}
+
+
+
+/**************************************************************************
+* mmioRead [MMSYSTEM.1212]
+*/
+LONG WINAPI mmioRead(HMMIO16 hmmio, HPSTR pch, LONG cch)
+{
+ LONG count;
+ LPMMIOINFO16 lpmminfo;
+
+ dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch);
+
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL)
+ return -1;
+
+ count = mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
+
+ GlobalUnlock16(hmmio);
+ dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count);
+ return count;
+}
+
+
+
+/**************************************************************************
+* mmioWrite [MMSYSTEM.1213]
+*/
+LONG WINAPI mmioWrite(HMMIO16 hmmio, HPCSTR pch, LONG cch)
+{
+ LONG count;
+ LPMMIOINFO16 lpmminfo;
+
+ dprintf_mmio(stddeb, "mmioWrite(%04X, %p, %ld);\n", hmmio, pch, cch);
+
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL)
+ return -1;
+
+ count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
+
+ GlobalUnlock16(hmmio);
+ dprintf_mmio(stddeb, "mmioWrite // count=%ld\n", count);
+ return count;
+}
+
+/**************************************************************************
+* mmioSeek [MMSYSTEM.1214]
+*/
+LONG WINAPI mmioSeek(HMMIO16 hmmio, LONG lOffset, int iOrigin)
+{
+ int offset;
+ LPMMIOINFO16 lpmminfo;
+
+ dprintf_mmio(stddeb, "mmioSeek(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
+
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL)
+ return 0;
+
+ offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
+
+ GlobalUnlock16(hmmio);
+ return offset;
+}
+
+/**************************************************************************
+* mmioGetInfo [MMSYSTEM.1215]
+*/
+UINT16 WINAPI mmioGetInfo(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+ LPMMIOINFO16 lpmminfo;
+ dprintf_mmio(stddeb, "mmioGetInfo\n");
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL) return 0;
+ memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
+ GlobalUnlock16(hmmio);
+ return 0;
+}
+
+/**************************************************************************
+* mmioSetInfo [MMSYSTEM.1216]
+*/
+UINT16 WINAPI mmioSetInfo(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+ LPMMIOINFO16 lpmminfo;
+ dprintf_mmio(stddeb, "mmioSetInfo\n");
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL) return 0;
+ GlobalUnlock16(hmmio);
+ return 0;
+}
+
+/**************************************************************************
+* mmioSetBuffer [MMSYSTEM.1217]
+*/
+UINT16 WINAPI mmioSetBuffer(HMMIO16 hmmio, LPSTR pchBuffer,
+ LONG cchBuffer, UINT16 uFlags)
+{
+ dprintf_mmio(stddeb, "mmioSetBuffer // empty stub \n");
+ return 0;
+}
+
+/**************************************************************************
+* mmioFlush [MMSYSTEM.1218]
+*/
+UINT16 WINAPI mmioFlush(HMMIO16 hmmio, UINT16 uFlags)
+{
+ LPMMIOINFO16 lpmminfo;
+ dprintf_mmio(stddeb, "mmioFlush(%04X, %04X)\n", hmmio, uFlags);
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL) return 0;
+ GlobalUnlock16(hmmio);
+ return 0;
+}
+
+/**************************************************************************
+* mmioAdvance [MMSYSTEM.1219]
+*/
+UINT16 WINAPI mmioAdvance(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+ int count = 0;
+ LPMMIOINFO16 lpmminfo;
+ dprintf_mmio(stddeb, "mmioAdvance\n");
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+ if (lpmminfo == NULL) return 0;
+ if (uFlags == MMIO_READ) {
+ count = _lread32(LOWORD(lpmminfo->adwInfo[0]),
+ lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
+ }
+ if (uFlags == MMIO_WRITE) {
+ count = _lwrite32(LOWORD(lpmminfo->adwInfo[0]),
+ lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
+ }
+ lpmmioinfo->pchNext += count;
+ GlobalUnlock16(hmmio);
+ lpmminfo->lDiskOffset = _llseek32((HFILE32)lpmminfo->adwInfo[0], 0, SEEK_CUR);
+ return 0;
+}
+
+/**************************************************************************
+ * mmioStringToFOURCCA [WINMM.131]
+ */
+FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
+{
+ return mmioStringToFOURCC16(sz,uFlags);
+}
+
+/**************************************************************************
+ * mmioStringToFOURCCW [WINMM.132]
+ */
+FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
+{
+ LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
+ FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
+
+ HeapFree(GetProcessHeap(),0,szA);
+ return ret;
+}
+
+/**************************************************************************
+ * mmioStringToFOURCC [MMSYSTEM.1220]
+ */
+FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
+{
+ dprintf_mmio(stddeb, "mmioStringToFOURCC // empty stub \n");
+ return 0;
+}
+
+/**************************************************************************
+* mmioInstallIOProc16 [MMSYSTEM.1221]
+*/
+LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
+ LPMMIOPROC16 pIOProc, DWORD dwFlags)
+{
+ dprintf_mmio(stddeb, "mmioInstallIOProc(%ld, %p, %08lX)\n",
+ fccIOProc, pIOProc, dwFlags);
+
+ if (dwFlags & MMIO_GLOBALPROC) {
+ fprintf(stdnimp, "mmioInstallIOProc: global procedures not "
+ "implemented\n");
+ }
+
+ /* just handle the known procedures for now */
+ switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
+ case MMIO_INSTALLPROC:
+ return NULL;
+ case MMIO_REMOVEPROC:
+ return NULL;
+ case MMIO_FINDPROC:
+ if (fccIOProc == FOURCC_DOS)
+ return (LPMMIOPROC16) mmioDosIOProc;
+ else if (fccIOProc == FOURCC_MEM)
+ return (LPMMIOPROC16) mmioMemIOProc;
+ else
+ return NULL;
+ default:
+ return NULL;
+ }
+}
+
+/**************************************************************************
+ * mmioInstallIOProc32A [WINMM.120]
+ */
+LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
+ LPMMIOPROC32 pIOProc, DWORD dwFlags)
+{
+ dprintf_mmio(stddeb, "mmioInstallIOProcA (%c%c%c%c,%p,0x%08lx)// empty stub \n",
+ (char)((fccIOProc&0xff000000)>>24),
+ (char)((fccIOProc&0x00ff0000)>>16),
+ (char)((fccIOProc&0x0000ff00)>> 8),
+ (char)(fccIOProc&0x000000ff),
+ pIOProc, dwFlags );
+ return 0;
+}
+
+/**************************************************************************
+* mmioSendMessage [MMSYSTEM.1222]
+*/
+LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
+ LPARAM lParam1, LPARAM lParam2)
+{
+ LPMMIOINFO16 lpmminfo;
+ LRESULT result;
+ const char *msg = NULL;
+
+#ifdef DEBUG_RUNTIME
+ switch (uMessage) {
+#define msgname(x) case x: msg = #x; break;
+ msgname(MMIOM_OPEN);
+ msgname(MMIOM_CLOSE);
+ msgname(MMIOM_READ);
+ msgname(MMIOM_WRITE);
+ msgname(MMIOM_WRITEFLUSH);
+ msgname(MMIOM_SEEK);
+ msgname(MMIOM_RENAME);
+#undef msgname
+ }
+#endif
+
+ if (msg)
+ dprintf_mmio(stddeb, "mmioSendMessage(%04X, %s, %ld, %ld)\n",
+ hmmio, msg, lParam1, lParam2);
+ else
+ dprintf_mmio(stddeb, "mmioSendMessage(%04X, %u, %ld, %ld)\n",
+ hmmio, uMessage, lParam1, lParam2);
+
+ lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+
+ if (lpmminfo && lpmminfo->pIOProc)
+ result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
+ else
+ result = MMSYSERR_INVALPARAM;
+
+ GlobalUnlock16(hmmio);
+
+ return result;
+}
+
+/**************************************************************************
+* mmioDescend [MMSYSTEM.1223]
+*/
+UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
+ const MMCKINFO * lpckParent, UINT16 uFlags)
+{
+ DWORD dwfcc, dwOldPos;
+
+ dprintf_mmio(stddeb, "mmioDescend(%04X, %p, %p, %04X);\n",
+ hmmio, lpck, lpckParent, uFlags);
+
+ if (lpck == NULL)
+ return 0;
+
+ dwfcc = lpck->ckid;
+ dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX\n", dwfcc);
+
+ dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
+ dprintf_mmio(stddeb, "mmioDescend // dwOldPos=%ld\n", dwOldPos);
+
+ if (lpckParent != NULL) {
+ dprintf_mmio(stddeb, "mmioDescend // seek inside parent at %ld !\n", lpckParent->dwDataOffset);
+ dwOldPos = mmioSeek(hmmio, lpckParent->dwDataOffset, SEEK_SET);
+ }
+/*
+
+ It seems to be that FINDRIFF should not be treated the same as the
+ other FINDxxx so I treat it as a MMIO_FINDxxx
+
+ if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
+ (uFlags & MMIO_FINDLIST)) {
+*/
+ if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
+ dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
+ while (TRUE) {
+ LONG ix;
+
+ ix = mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO));
+ dprintf_mmio(stddeb, "mmioDescend // after _lread32 ix = %ld req = %d, errno = %d\n",ix,sizeof(MMCKINFO),errno);
+ if (ix < sizeof(MMCKINFO)) {
+
+ mmioSeek(hmmio, dwOldPos, SEEK_SET);
+ dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound\n");
+ return MMIOERR_CHUNKNOTFOUND;
+ }
+ dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
+ dwfcc, lpck->ckid, lpck->cksize);
+ if (dwfcc == lpck->ckid)
+ break;
+
+ dwOldPos += lpck->cksize + 2 * sizeof(DWORD);
+ if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
+ dwOldPos += sizeof(DWORD);
+ mmioSeek(hmmio, dwOldPos, SEEK_SET);
+ }
+ }
+ else {
+ if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
+ mmioSeek(hmmio, dwOldPos, SEEK_SET);
+ dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound 2nd\n");
+ return MMIOERR_CHUNKNOTFOUND;
+ }
+ }
+ lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
+ if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
+ lpck->dwDataOffset += sizeof(DWORD);
+ mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
+
+ dprintf_mmio(stddeb, "mmioDescend // lpck->ckid=%08lX lpck->cksize=%ld !\n",
+ lpck->ckid, lpck->cksize);
+ dprintf_mmio(stddeb, "mmioDescend // lpck->fccType=%08lX !\n", lpck->fccType);
+
+ return 0;
+}
+
+/**************************************************************************
+* mmioAscend [MMSYSTEM.1224]
+*/
+UINT16 WINAPI mmioAscend(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
+{
+ dprintf_mmio(stddeb, "mmioAscend // empty stub !\n");
+ return 0;
+}
+
+/**************************************************************************
+* mmioCreateChunk [MMSYSTEM.1225]
+*/
+UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
+{
+ dprintf_mmio(stddeb, "mmioCreateChunk // empty stub \n");
+ return 0;
+}
+
+
+/**************************************************************************
+* mmioRename [MMSYSTEM.1226]
+*/
+UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
+ MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
+{
+ UINT16 result;
+ LPMMIOINFO16 lpmminfo;
+ HMMIO16 hmmio;
+
+ dprintf_mmio(stddeb, "mmioRename('%s', '%s', %p, %08lX);\n",
+ szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
+
+ hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
+ lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
+
+ if (lpmmioinfo)
+ memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
+
+ /* assume DOS file if not otherwise specified */
+ if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
+
+ lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
+ lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
+
+ }
+ /* if just the four character code is present, look up IO proc */
+ else if (lpmminfo->pIOProc == NULL) {
+
+ lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
+
+ }
+ /* (if IO proc specified, use it and specified four character code) */
+
+ result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
+
+ GlobalUnlock16(hmmio);
+ GlobalFree16(hmmio);
+
+ return result;
+}
+
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index ad9d211..4f1e47c 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -3647,370 +3647,6 @@
}
/**************************************************************************
- * mmioOpenW [WINMM.123]
- */
-HMMIO32 WINAPI mmioOpen32W(LPWSTR szFileName, MMIOINFO32 * lpmmioinfo,
- DWORD dwOpenFlags)
-{
- LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
- HMMIO32 ret = mmioOpen16(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
-
- HeapFree(GetProcessHeap(),0,szFn);
- return ret;
-}
-
-/**************************************************************************
- * mmioOpenA [WINMM.122]
- */
-HMMIO32 WINAPI mmioOpen32A(LPSTR szFileName, MMIOINFO32 * lpmmioinfo,
- DWORD dwOpenFlags)
-{
- return mmioOpen16(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
-}
-
-/**************************************************************************
- * mmioOpen [MMSYSTEM.1210]
- */
-HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
- DWORD dwOpenFlags)
-{
- HFILE32 hFile;
- HMMIO16 hmmio;
- OFSTRUCT ofs;
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioOpen('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
- if (!szFileName)
- {
- /* FIXME: should load memory file if szFileName == NULL */
- fprintf(stderr, "WARNING: mmioOpen(): szFileName == NULL (memory file ???)\n");
- return 0;
- }
- hFile = OpenFile32(szFileName, &ofs, dwOpenFlags);
- if (hFile == -1) return 0;
- hmmio = GlobalAlloc16(GMEM_MOVEABLE, sizeof(MMIOINFO16));
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- memset(lpmminfo, 0, sizeof(MMIOINFO16));
- lpmminfo->hmmio = hmmio;
- lpmminfo->dwReserved2 = hFile;
- GlobalUnlock16(hmmio);
- dprintf_mmio(stddeb, "mmioOpen // return hmmio=%04X\n", hmmio);
- return hmmio;
-}
-
-
-/**************************************************************************
-* mmioClose [MMSYSTEM.1211]
-*/
-UINT16 WINAPI mmioClose(HMMIO16 hmmio, UINT16 uFlags)
-{
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioClose(%04X, %04X);\n", hmmio, uFlags);
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- _lclose32((HFILE32)lpmminfo->dwReserved2);
- GlobalUnlock16(hmmio);
- GlobalFree16(hmmio);
- return 0;
-}
-
-
-
-/**************************************************************************
-* mmioRead [MMSYSTEM.1212]
-*/
-LONG WINAPI mmioRead(HMMIO16 hmmio, HPSTR pch, LONG cch)
-{
- LONG count;
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch);
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- count = _lread32(LOWORD(lpmminfo->dwReserved2), pch, cch);
- GlobalUnlock16(hmmio);
- dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count);
- return count;
-}
-
-
-
-/**************************************************************************
-* mmioWrite [MMSYSTEM.1213]
-*/
-LONG WINAPI mmioWrite(HMMIO16 hmmio, HPCSTR pch, LONG cch)
-{
- LONG count;
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioWrite(%04X, %p, %ld);\n", hmmio, pch, cch);
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- count = _lwrite32(LOWORD(lpmminfo->dwReserved2), (LPSTR)pch, cch);
- GlobalUnlock16(hmmio);
- return count;
-}
-
-/**************************************************************************
-* mmioSeek [MMSYSTEM.1214]
-*/
-LONG WINAPI mmioSeek(HMMIO16 hmmio, LONG lOffset, int iOrigin)
-{
- int count;
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioSeek(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) {
- dprintf_mmio(stddeb, "mmioSeek // can't lock hmmio=%04X !\n", hmmio);
- return 0;
- }
- count = _llseek32((HFILE32)lpmminfo->dwReserved2, lOffset, iOrigin);
- GlobalUnlock16(hmmio);
- return count;
-}
-
-/**************************************************************************
-* mmioGetInfo [MMSYSTEM.1215]
-*/
-UINT16 WINAPI mmioGetInfo(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
-{
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioGetInfo\n");
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
- GlobalUnlock16(hmmio);
- return 0;
-}
-
-/**************************************************************************
-* mmioSetInfo [MMSYSTEM.1216]
-*/
-UINT16 WINAPI mmioSetInfo(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
-{
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioSetInfo\n");
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- GlobalUnlock16(hmmio);
- return 0;
-}
-
-/**************************************************************************
-* mmioSetBuffer [MMSYSTEM.1217]
-*/
-UINT16 WINAPI mmioSetBuffer(HMMIO16 hmmio, LPSTR pchBuffer,
- LONG cchBuffer, UINT16 uFlags)
-{
- dprintf_mmio(stddeb, "mmioSetBuffer // empty stub \n");
- return 0;
-}
-
-/**************************************************************************
-* mmioFlush [MMSYSTEM.1218]
-*/
-UINT16 WINAPI mmioFlush(HMMIO16 hmmio, UINT16 uFlags)
-{
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioFlush(%04X, %04X)\n", hmmio, uFlags);
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- GlobalUnlock16(hmmio);
- return 0;
-}
-
-/**************************************************************************
-* mmioAdvance [MMSYSTEM.1219]
-*/
-UINT16 WINAPI mmioAdvance(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
-{
- int count = 0;
- LPMMIOINFO16 lpmminfo;
- dprintf_mmio(stddeb, "mmioAdvance\n");
- lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
- if (lpmminfo == NULL) return 0;
- if (uFlags == MMIO_READ) {
- count = _lread32(LOWORD(lpmminfo->dwReserved2),
- lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
- }
- if (uFlags == MMIO_WRITE) {
- count = _lwrite32(LOWORD(lpmminfo->dwReserved2),
- lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
- }
- lpmmioinfo->pchNext += count;
- GlobalUnlock16(hmmio);
- lpmminfo->lDiskOffset = _llseek32((HFILE32)lpmminfo->dwReserved2, 0, SEEK_CUR);
- return 0;
-}
-
-/**************************************************************************
- * mmioStringToFOURCCW [WINMM.131]
- */
-FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
-{
- return mmioStringToFOURCC16(sz,uFlags);
-}
-
-/**************************************************************************
- * mmioStringToFOURCCW [WINMM.132]
- */
-FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
-{
- LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
- FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
-
- HeapFree(GetProcessHeap(),0,szA);
- return ret;
-}
-
-/**************************************************************************
- * mmioStringToFOURCC [MMSYSTEM.1220]
- */
-FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
-{
- dprintf_mmio(stddeb, "mmioStringToFOURCC // empty stub \n");
- return 0;
-}
-
-/**************************************************************************
-* mmioInstallIOProc16 [MMSYSTEM.1221]
-*/
-LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
- LPMMIOPROC16 pIOProc, DWORD dwFlags)
-{
- dprintf_mmio(stddeb, "mmioInstallIOProc // empty stub \n");
- return 0;
-}
-
-/**************************************************************************
- * mmioInstallIOProc32A [WINMM.120]
- */
-LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
- LPMMIOPROC32 pIOProc, DWORD dwFlags)
-{
- dprintf_mmio(stddeb, "mmioInstallIOProcA (%c%c%c%c,%p,0x%08lx)// empty stub \n",
- (char)((fccIOProc&0xff000000)>>24),
- (char)((fccIOProc&0x00ff0000)>>16),
- (char)((fccIOProc&0x0000ff00)>> 8),
- (char)(fccIOProc&0x000000ff),
- pIOProc, dwFlags );
- return 0;
-}
-
-/**************************************************************************
-* mmioSendMessage [MMSYSTEM.1222]
-*/
-LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
- LPARAM lParam1, LPARAM lParam2)
-{
- dprintf_mmio(stddeb, "mmioSendMessage // empty stub \n");
- return 0;
-}
-
-/**************************************************************************
-* mmioDescend [MMSYSTEM.1223]
-*/
-UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
- const MMCKINFO * lpckParent, UINT16 uFlags)
-{
- DWORD dwfcc, dwOldPos;
-
- dprintf_mmio(stddeb, "mmioDescend(%04X, %p, %p, %04X);\n",
- hmmio, lpck, lpckParent, uFlags);
-
- if (lpck == NULL)
- return 0;
-
- dwfcc = lpck->ckid;
- dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX\n", dwfcc);
-
- dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
- dprintf_mmio(stddeb, "mmioDescend // dwOldPos=%ld\n", dwOldPos);
-
- if (lpckParent != NULL) {
- dprintf_mmio(stddeb, "mmioDescend // seek inside parent at %ld !\n", lpckParent->dwDataOffset);
- dwOldPos = mmioSeek(hmmio, lpckParent->dwDataOffset, SEEK_SET);
- }
-/*
-
- It seems to be that FINDRIFF should not be treated the same as the
- other FINDxxx so I treat it as a MMIO_FINDxxx
-
- if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
- (uFlags & MMIO_FINDLIST)) {
-*/
- if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
- dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
- while (TRUE) {
- LONG ix;
-
- ix = mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO));
- dprintf_mmio(stddeb, "mmioDescend // after _lread32 ix = %ld req = %d, errno = %d\n",ix,sizeof(MMCKINFO),errno);
- if (ix < sizeof(MMCKINFO)) {
-
- mmioSeek(hmmio, dwOldPos, SEEK_SET);
- dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound\n");
- return MMIOERR_CHUNKNOTFOUND;
- }
- dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
- dwfcc, lpck->ckid, lpck->cksize);
- if (dwfcc == lpck->ckid)
- break;
-
- dwOldPos += lpck->cksize + 2 * sizeof(DWORD);
- if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
- dwOldPos += sizeof(DWORD);
- mmioSeek(hmmio, dwOldPos, SEEK_SET);
- }
- }
- else {
- if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
- mmioSeek(hmmio, dwOldPos, SEEK_SET);
- dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound 2nd\n");
- return MMIOERR_CHUNKNOTFOUND;
- }
- }
- lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
- if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
- lpck->dwDataOffset += sizeof(DWORD);
- mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
-
- dprintf_mmio(stddeb, "mmioDescend // lpck->ckid=%08lX lpck->cksize=%ld !\n",
- lpck->ckid, lpck->cksize);
- dprintf_mmio(stddeb, "mmioDescend // lpck->fccType=%08lX !\n", lpck->fccType);
-
- return 0;
-}
-
-/**************************************************************************
-* mmioAscend [MMSYSTEM.1224]
-*/
-UINT16 WINAPI mmioAscend(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
-{
- dprintf_mmio(stddeb, "mmioAscend // empty stub !\n");
- return 0;
-}
-
-/**************************************************************************
-* mmioCreateChunk [MMSYSTEM.1225]
-*/
-UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
-{
- dprintf_mmio(stddeb, "mmioCreateChunk // empty stub \n");
- return 0;
-}
-
-
-/**************************************************************************
-* mmioRename [MMSYSTEM.1226]
-*/
-UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
- MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
-{
- dprintf_mmio(stddeb, "mmioRename('%s', '%s', %p, %08lX); // empty stub \n",
- szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
- return 0;
-}
-
-/**************************************************************************
* DrvOpen [MMSYSTEM.1100]
*/
HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 4092719..3290ae7 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -26,9 +26,6 @@
/* GCs used for B&W and color bitmap operations */
GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
-extern void CLIPPING_UpdateGCRegion( DC * dc ); /* objects/clipping.c */
-
-
/***********************************************************************
* XPutImage_wrapper
*
diff --git a/objects/clipping.c b/objects/clipping.c
index d417c71..7f9acb2 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -505,6 +505,8 @@
HRGN32 saved;
RGNOBJ *obj, *savedObj;
DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ INT16 ret;
+
if (!dc) return ERROR;
if (!dc->w.hVisRgn)
{
@@ -533,6 +535,7 @@
dc->w.hVisRgn = saved;
CLIPPING_UpdateGCRegion( dc );
GDI_HEAP_UNLOCK( hdc );
+ ret = savedObj->rgn->type; /* FIXME */
GDI_HEAP_UNLOCK( saved );
- return savedObj->xrgn ? COMPLEXREGION : NULLREGION;
+ return ret;
}
diff --git a/objects/cursoricon.c b/objects/cursoricon.c
index 2ec3b59..a7e77c4 100644
--- a/objects/cursoricon.c
+++ b/objects/cursoricon.c
@@ -42,6 +42,7 @@
#include "debug.h"
#include "task.h"
#include "user.h"
+#include "keyboard.h"
extern UINT16 COLOR_GetSystemPaletteSize();
@@ -1243,6 +1244,18 @@
{
pt->x = childX;
pt->y = childY;
+ if (mousebut & Button1Mask)
+ AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
+ else
+ MouseButtonsStates[0] = FALSE;
+ if (mousebut & Button2Mask)
+ AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
+ else
+ MouseButtonsStates[1] = FALSE;
+ if (mousebut & Button3Mask)
+ AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
+ else
+ MouseButtonsStates[2] = FALSE;
}
dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
}
diff --git a/objects/dib.c b/objects/dib.c
index 0f1ef17..8955624 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -1420,6 +1420,8 @@
hdc,bmi->bmiHeader.biWidth,bmi->bmiHeader.biHeight,
usage,bits,section,offset
);
+ if (bmi->bmiHeader.biHeight < 0 ) bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
+ if (bmi->bmiHeader.biWidth < 0 ) bmi->bmiHeader.biWidth = -bmi->bmiHeader.biWidth;
/* FIXME. The following line isn't quite right. */
res = CreateDIBitmap32 (hdc, &bmi->bmiHeader, 0, NULL, bmi, 0);
if (res)
@@ -1429,6 +1431,9 @@
{
/* FIXME: this is wrong! (bmBits is always NULL) */
if (bits) *bits = bmp.bmBits;
+ /* hmpf */
+ fprintf(stderr,"allocating %d bytes of memory\n",bmi->bmiHeader.biWidth*bmi->bmiHeader.biHeight*4);
+ if (bits) *bits = (LPBYTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,bmi->bmiHeader.biWidth*bmi->bmiHeader.biHeight*4);
return res;
}
}
diff --git a/objects/metafile.c b/objects/metafile.c
index 373c851..9fabc7c 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <fcntl.h>
+#include "windows.h"
#include "gdi.h"
#include "bitmap.h"
#include "file.h"
@@ -233,16 +234,15 @@
/******************************************************************
- * PlayMetafile16 (GDI.123)
+ * PlayMetaFile16 (GDI.123)
*/
BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
{
return PlayMetaFile32( hdc, hmf );
}
-
/******************************************************************
- * PlayMetafile32 (GDI32.265)
+ * PlayMetaFile32 (GDI32.265)
*/
BOOL32 WINAPI PlayMetaFile32( HDC32 hdc, HMETAFILE32 hmf )
{
@@ -256,9 +256,8 @@
HBRUSH32 hBrush;
HFONT32 hFont;
DC *dc;
-
+
dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
-
if (!mh) return FALSE;
if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
hPen = dc->w.hPen;
@@ -270,13 +269,14 @@
sizeof(HANDLETABLE16) * mh->mtNoObjects);
ht = (HANDLETABLE16 *)GlobalLock16(hHT);
+
/* loop through metafile playing records */
offset = mh->mtHeaderSize * 2;
while (offset < mh->mtSize * 2)
{
- mr = (METARECORD *)((char *)mh + offset);
- dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
- offset,mr->rdSize,mr->rdFunction);
+ mr = (METARECORD *)((char *)mh + offset);
+ dprintf_metafile(stddeb,"offset = %04x size = %08lx\n",
+ offset, mr->rdSize);
if (!mr->rdSize) {
fprintf(stderr,"METAFILE entry got size 0 at offset %d, total mf length is %ld\n",offset,mh->mtSize*2);
break; /* would loop endlessly otherwise */
@@ -368,6 +368,7 @@
return TRUE;
}
+static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
/******************************************************************
* PlayMetaFileRecord16 (GDI.176)
@@ -380,8 +381,9 @@
char *ptr;
BITMAPINFOHEADER *infohdr;
- dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
- hdc,(LONG)ht, (LONG)mr, nHandles);
+ dprintf_metafile(stddeb,
+"PlayMetaFileRecord(%04x %08lx %08lx %04x) function %04x\n",
+ hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
switch (mr->rdFunction)
{
@@ -420,6 +422,7 @@
case META_SETSTRETCHBLTMODE:
SetStretchBltMode16(hdc, *(mr->rdParam));
break;
+
case META_SETTEXTCOLOR:
SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
break;
@@ -732,23 +735,13 @@
/* --- Begin of new metafile operations. April, 1997 (ak) ----*/
case META_CREATEREGION:
- {
- int i;
- HRGN32 h2,hrgn=CreateRectRgn32(mr->rdParam[7],mr->rdParam[8],
- mr->rdParam[9],mr->rdParam[10]);
- for (i = 0; i < mr->rdParam[5]; i++)
- {
- if (mr->rdParam[11+i*6]==2)
- {
- h2=CreateRectRgn32(mr->rdParam[14+i*6],mr->rdParam[12+i*6],
- mr->rdParam[15+i*6],mr->rdParam[13+i*6]);
- CombineRgn32(hrgn,hrgn,h2,mr->rdParam[16+i*6]); /* e.g. RGN_OR */
- DeleteObject32( h2 );
- }
- }
- MF_AddHandle(ht, nHandles,hrgn);
- }
- break;
+ {
+ HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
+
+ MF_Meta_CreateRegion(mr, hrgn);
+ MF_AddHandle(ht, nHandles, hrgn);
+ }
+ break;
case META_FILLREGION:
FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)),
@@ -861,6 +854,79 @@
}
/******************************************************************
+ * MF_Meta_CreateRegion
+ *
+ * Handles META_CREATEREGION for PlayMetaFileRecord().
+ */
+
+/*
+ * The layout of the record looks something like this:
+ *
+ * rdParam meaning
+ * 0 Always 0?
+ * 1 Always 6?
+ * 2 Looks like a handle? - not constant
+ * 3 0 or 1 ??
+ * 4 Total number of bytes
+ * 5 No. of seperate bands = n [see below]
+ * 6 Largest number of x co-ords in a band
+ * 7-10 Bounding box x1 y1 x2 y2
+ * 11-... n bands
+ *
+ * Regions are divided into bands that are uniform in the
+ * y-direction. Each band consists of pairs of on/off x-coords and is
+ * written as
+ * m y0 y1 x1 x2 x3 ... xm m
+ * into successive rdParam[]s.
+ *
+ * This is probably just a dump of the internal RGNOBJ?
+ *
+ * HDMD - 18/12/97
+ *
+ */
+
+static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
+{
+ WORD band, pair;
+ WORD *start, *end;
+ INT16 y0, y1;
+ HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
+
+ for(band = 0, start = &(mr->rdParam[11]); band < mr->rdParam[5];
+ band++, start = end + 1) {
+ if(*start / 2 != (*start + 1) / 2) {
+ fprintf(stderr, "META_CREATEREGION: delimiter not even.\n");
+ DeleteObject32( hrgn2 );
+ return FALSE;
+ }
+
+ end = start + *start + 3;
+ if(end > (WORD *)mr + mr->rdSize) {
+ fprintf(stderr, "META_CREATEREGION: end points outside record.\n");
+ DeleteObject32( hrgn2 );
+ return FALSE;
+ }
+
+ if(*start != *end) {
+ fprintf(stderr, "META_CREATEREGION: mismatched delimiters.\n");
+ DeleteObject32( hrgn2 );
+ return FALSE;
+ }
+
+ y0 = *(INT16 *)(start + 1);
+ y1 = *(INT16 *)(start + 2);
+ for(pair = 0; pair < *start / 2; pair++) {
+ SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
+ *(INT16 *)(start + 4 + 2*pair), y1 );
+ CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
+ }
+ }
+ DeleteObject32( hrgn2 );
+ return TRUE;
+ }
+
+
+/******************************************************************
* MF_WriteRecord
*
* Warning: this function can change the metafile handle.
@@ -1389,3 +1455,88 @@
}
+/******************************************************************
+ * MF_CreateRegion
+ */
+INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
+{
+ DWORD len;
+ METARECORD *mr;
+ RGNDATA *rgndata;
+ RECT32 *pCurRect, *pEndRect;
+ WORD Bands = 0, MaxBands = 0;
+ WORD *Param, *StartBand;
+ BOOL32 ret;
+
+ len = GetRegionData( hrgn, 0, NULL );
+ if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
+ fprintf(stderr, "MF_CreateRegion: can't alloc rgndata buffer\n");
+ return -1;
+ }
+ GetRegionData( hrgn, len, rgndata );
+
+ /* Overestimate of length:
+ * Assume every rect is a separate band -> 6 WORDs per rect
+ */
+ len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
+ if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
+ fprintf(stderr, "MF_CreateRegion: can't alloc METARECORD buffer\n");
+ HeapFree( SystemHeap, 0, rgndata );
+ return -1;
+ }
+
+ memset(mr, 0, len);
+
+ Param = mr->rdParam + 11;
+ StartBand = NULL;
+
+ pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
+ for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
+ {
+ if( StartBand && pCurRect->top == *(StartBand + 1) )
+ {
+ *Param++ = pCurRect->left;
+ *Param++ = pCurRect->right;
+ }
+ else
+ {
+ if(StartBand)
+ {
+ *StartBand = Param - StartBand - 3;
+ *Param++ = *StartBand;
+ if(*StartBand > MaxBands)
+ MaxBands = *StartBand;
+ Bands++;
+ }
+ StartBand = Param++;
+ *Param++ = pCurRect->top;
+ *Param++ = pCurRect->bottom;
+ *Param++ = pCurRect->left;
+ *Param++ = pCurRect->right;
+ }
+ }
+ len = Param - (WORD *)mr;
+
+ mr->rdParam[0] = 0;
+ mr->rdParam[1] = 6;
+ mr->rdParam[2] = 0x1234;
+ mr->rdParam[3] = 0;
+ mr->rdParam[4] = len * 2;
+ mr->rdParam[5] = Bands;
+ mr->rdParam[6] = MaxBands;
+ mr->rdParam[7] = rgndata->rdh.rcBound.left;
+ mr->rdParam[8] = rgndata->rdh.rcBound.top;
+ mr->rdParam[9] = rgndata->rdh.rcBound.right;
+ mr->rdParam[10] = rgndata->rdh.rcBound.bottom;
+ mr->rdFunction = META_CREATEREGION;
+ mr->rdSize = len / 2;
+ ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );
+ HeapFree( SystemHeap, 0, mr );
+ HeapFree( SystemHeap, 0, rgndata );
+ if(!ret)
+ {
+ fprintf(stderr, "MF_CreateRegion: MF_WriteRecord failed\n");
+ return -1;
+ }
+ return MF_AddHandleDC( dc );
+}
diff --git a/objects/region.c b/objects/region.c
index c68686f..a26cb96 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -1,17 +1,170 @@
/*
- * GDI region objects
+ * GDI region objects. Shamelessly ripped out from the X11 distribution
+ * Thanks for the nice licence.
*
* Copyright 1993, 1994, 1995 Alexandre Julliard
+ * Modifications and additions: Copyright 1998 Huw Davies
*
- * RGNOBJ is documented in the Dr. Dobbs Journal March 1993.
*/
-#include <stdlib.h>
+/************************************************************************
+
+Copyright (c) 1987, 1988 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+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 and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+************************************************************************/
+/*
+ * The functions in this file implement the Region abstraction, similar to one
+ * used in the X11 sample server. A Region is simply an area, as the name
+ * implies, and is implemented as a "y-x-banded" array of rectangles. To
+ * explain: Each Region is made up of a certain number of rectangles sorted
+ * by y coordinate first, and then by x coordinate.
+ *
+ * Furthermore, the rectangles are banded such that every rectangle with a
+ * given upper-left y coordinate (y1) will have the same lower-right y
+ * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it
+ * will span the entire vertical distance of the band. This means that some
+ * areas that could be merged into a taller rectangle will be represented as
+ * several shorter rectangles to account for shorter rectangles to its left
+ * or right but within its "vertical scope".
+ *
+ * An added constraint on the rectangles is that they must cover as much
+ * horizontal area as possible. E.g. no two rectangles in a band are allowed
+ * to touch.
+ *
+ * Whenever possible, bands will be merged together to cover a greater vertical
+ * distance (and thus reduce the number of rectangles). Two bands can be merged
+ * only if the bottom of one touches the top of the other and they have
+ * rectangles in the same places (of the same width, of course). This maintains
+ * the y-x-banding that's so nice to have...
+ */
+
#include <stdio.h>
#include "region.h"
#include "stddebug.h"
#include "debug.h"
+#include "heap.h"
+#include "dc.h"
+typedef void (*voidProcp)();
+
+/* Note the parameter order is different from the X11 equivalents */
+
+static void REGION_CopyRegion(WINEREGION *d, WINEREGION *s);
+static void REGION_IntersectRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
+static void REGION_UnionRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
+static void REGION_SubtractRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
+static void REGION_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
+static void REGION_UnionRectWithRegion(const RECT32 *rect, WINEREGION *rgn);
+
+
+/***********************************************************************
+ * REGION_DumpRegion
+ * Outputs the contents of a WINEREGION
+ */
+static void REGION_DumpRegion(WINEREGION *pReg)
+{
+ RECT32 *pRect, *pRectEnd = pReg->rects + pReg->numRects;
+
+ dprintf_region(stddeb, "Region %p: %d,%d - %d,%d %d rects\n", pReg,
+ pReg->extents.left, pReg->extents.top,
+ pReg->extents.right, pReg->extents.bottom, pReg->numRects);
+ for(pRect = pReg->rects; pRect < pRectEnd; pRect++)
+ dprintf_region(stddeb, "\t%d,%d - %d,%d\n", pRect->left, pRect->top,
+ pRect->right, pRect->bottom);
+ return;
+}
+
+/***********************************************************************
+ * REGION_AllocWineRegion
+ * Create a new empty WINEREGION.
+ */
+static WINEREGION *REGION_AllocWineRegion( void )
+{
+ WINEREGION *pReg;
+
+ if (!(pReg = HeapAlloc(SystemHeap, 0, sizeof( WINEREGION ))))
+ return NULL;
+ if (!(pReg->rects = HeapAlloc(SystemHeap, 0, sizeof( RECT32 ))))
+ {
+ HeapFree(SystemHeap, 0, pReg);
+ return NULL;
+ }
+ pReg->size = 1;
+ EMPTY_REGION(pReg);
+ return pReg;
+}
+
+/***********************************************************************
+ * REGION_CreateRegion
+ * Create a new empty region.
+ */
+static HRGN32 REGION_CreateRegion(void)
+{
+ HRGN32 hrgn;
+ RGNOBJ *obj;
+
+ if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
+ return 0;
+ obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
+ if(!(obj->rgn = REGION_AllocWineRegion())) {
+ GDI_FreeObject( hrgn );
+ return 0;
+ }
+ GDI_HEAP_UNLOCK( hrgn );
+ return hrgn;
+}
+
+/***********************************************************************
+ * REGION_DestroyWineRegion
+ */
+static void REGION_DestroyWineRegion( WINEREGION* pReg )
+{
+ HeapFree( SystemHeap, 0, pReg->rects );
+ HeapFree( SystemHeap, 0, pReg );
+ return;
+}
/***********************************************************************
* REGION_DeleteObject
@@ -19,11 +172,11 @@
BOOL32 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj )
{
dprintf_region(stddeb, "DeleteRegion: %04x\n", hrgn );
- if (obj->xrgn) XDestroyRegion( obj->xrgn );
+
+ REGION_DestroyWineRegion( obj->rgn );
return GDI_FreeObject( hrgn );
}
-
/***********************************************************************
* OffsetRgn16 (GDI.101)
*/
@@ -32,7 +185,6 @@
return OffsetRgn32( hrgn, x, y );
}
-
/***********************************************************************
* OffsetRgn32 (GDI32.256)
*/
@@ -43,14 +195,24 @@
if (obj)
{
INT32 ret;
+ int nbox = obj->rgn->numRects;
+ RECT32 *pbox = obj->rgn->rects;
+
dprintf_region(stddeb, "OffsetRgn: %04x %d,%d\n", hrgn, x, y );
- if (obj->xrgn)
- {
- XOffsetRegion( obj->xrgn, x, y );
- ret = COMPLEXREGION;
+ if(nbox && (x || y)) {
+ while(nbox--) {
+ pbox->left += x;
+ pbox->right += x;
+ pbox->top += y;
+ pbox->bottom += y;
+ pbox++;
+ }
+ obj->rgn->extents.left += x;
+ obj->rgn->extents.right += x;
+ obj->rgn->extents.top += y;
+ obj->rgn->extents.bottom += y;
}
- else
- ret = NULLREGION;
+ ret = obj->rgn->type;
GDI_HEAP_UNLOCK( hrgn );
return ret;
}
@@ -63,40 +225,31 @@
*/
INT16 WINAPI GetRgnBox16( HRGN16 hrgn, LPRECT16 rect )
{
- RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
- if (obj)
- {
- INT16 ret;
- dprintf_region(stddeb, "GetRgnBox: %04x\n", hrgn );
- if (obj->xrgn)
- {
- XRectangle xrect;
- XClipBox( obj->xrgn, &xrect );
- SetRect16( rect, xrect.x, xrect.y,
- xrect.x + xrect.width, xrect.y + xrect.height);
- ret = COMPLEXREGION;
- }
- else
- {
- SetRectEmpty16( rect );
- ret = NULLREGION;
- }
- GDI_HEAP_UNLOCK(hrgn);
- return ret;
- }
- return ERROR;
+ RECT32 r;
+ INT16 ret = (INT16)GetRgnBox32( hrgn, &r );
+ CONV_RECT32TO16( &r, rect );
+ return ret;
}
-
/***********************************************************************
* GetRgnBox32 (GDI32.219)
*/
INT32 WINAPI GetRgnBox32( HRGN32 hrgn, LPRECT32 rect )
{
- RECT16 r;
- INT16 ret = GetRgnBox16( hrgn, &r );
- CONV_RECT16TO32( &r, rect );
- return ret;
+ RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
+ if (obj)
+ {
+ INT32 ret;
+ dprintf_region(stddeb, "GetRgnBox: %04x\n", hrgn );
+ rect->left = obj->rgn->extents.left;
+ rect->top = obj->rgn->extents.top;
+ rect->right = obj->rgn->extents.right;
+ rect->bottom = obj->rgn->extents.bottom;
+ ret = obj->rgn->type;
+ GDI_HEAP_UNLOCK(hrgn);
+ return ret;
+ }
+ return ERROR;
}
@@ -115,28 +268,14 @@
HRGN32 WINAPI CreateRectRgn32(INT32 left, INT32 top, INT32 right, INT32 bottom)
{
HRGN32 hrgn;
- RGNOBJ *obj;
- if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
- obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
- if ((right > left) && (bottom > top))
- {
- XRectangle rect = { left, top, right - left, bottom - top };
- if (!(obj->xrgn = XCreateRegion()))
- {
- GDI_FreeObject( hrgn );
- return 0;
- }
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
- }
- else obj->xrgn = 0;
- dprintf_region( stddeb, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
- left, top, right, bottom, hrgn );
- GDI_HEAP_UNLOCK( hrgn );
+ if (!(hrgn = REGION_CreateRegion()))
+ return 0;
+ dprintf_region(stddeb, "CreateRectRgn: ");
+ SetRectRgn32(hrgn, left, top, right, bottom);
return hrgn;
}
-
/***********************************************************************
* CreateRectRgnIndirect16 (GDI.65)
*/
@@ -159,7 +298,7 @@
* SetRectRgn16 (GDI.172)
*/
VOID WINAPI SetRectRgn16( HRGN16 hrgn, INT16 left, INT16 top,
- INT16 right, INT16 bottom )
+ INT16 right, INT16 bottom )
{
SetRectRgn32( hrgn, left, top, right, bottom );
}
@@ -169,7 +308,7 @@
* SetRectRgn32 (GDI32.332)
*/
VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top,
- INT32 right, INT32 bottom )
+ INT32 right, INT32 bottom )
{
RGNOBJ * obj;
@@ -177,14 +316,18 @@
hrgn, left, top, right, bottom );
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
- if (obj->xrgn) XDestroyRegion( obj->xrgn );
if ((right > left) && (bottom > top))
{
- XRectangle rect = { left, top, right - left, bottom - top };
- if ((obj->xrgn = XCreateRegion()) != 0)
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
+ obj->rgn->rects->left = obj->rgn->extents.left = left;
+ obj->rgn->rects->top = obj->rgn->extents.top = top;
+ obj->rgn->rects->right = obj->rgn->extents.right = right;
+ obj->rgn->rects->bottom = obj->rgn->extents.bottom = bottom;
+ obj->rgn->numRects = 1;
+ obj->rgn->type = SIMPLEREGION;
}
- else obj->xrgn = 0;
+ else
+ EMPTY_REGION(obj->rgn);
+
GDI_HEAP_UNLOCK( hrgn );
}
@@ -193,39 +336,37 @@
* CreateRoundRectRgn16 (GDI.444)
*/
HRGN16 WINAPI CreateRoundRectRgn16( INT16 left, INT16 top,
- INT16 right, INT16 bottom,
- INT16 ellipse_width, INT16 ellipse_height )
+ INT16 right, INT16 bottom,
+ INT16 ellipse_width, INT16 ellipse_height )
{
return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
- ellipse_width, ellipse_height );
+ ellipse_width, ellipse_height );
}
-
/***********************************************************************
* CreateRoundRectRgn32 (GDI32.61)
*/
HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top,
- INT32 right, INT32 bottom,
- INT32 ellipse_width, INT32 ellipse_height )
+ INT32 right, INT32 bottom,
+ INT32 ellipse_width, INT32 ellipse_height )
{
RGNOBJ * obj;
HRGN32 hrgn;
- XRectangle rect;
int asq, bsq, d, xd, yd;
-
+ RECT32 rect;
+
/* Check if we can do a normal rectangle instead */
if ((right <= left) || (bottom <= top) ||
- (ellipse_width <= 0) || (ellipse_height <= 0))
- return CreateRectRgn32( left, top, right, bottom );
+ (ellipse_width <= 0) || (ellipse_height <= 0))
+ return CreateRectRgn32( left, top, right, bottom );
/* Create region */
- if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
+ if (!(hrgn = REGION_CreateRegion())) return 0;
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
- obj->xrgn = XCreateRegion();
- dprintf_region(stddeb,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
- left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
+ dprintf_region(stddeb,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): ret=%04x\n",
+ left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
/* Check parameters */
@@ -241,28 +382,29 @@
xd = 0;
yd = asq * ellipse_height; /* 2a^2b */
- rect.x = left + ellipse_width / 2;
- rect.width = right - left - ellipse_width;
- rect.height = 1;
+ rect.left = left + ellipse_width / 2;
+ rect.right = right - ellipse_width;
/* Loop to draw first half of quadrant */
while (xd < yd)
{
- if (d > 0) /* if nearest pixel is toward the center */
- {
- /* move toward center */
- rect.y = top++;
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
- rect.y = --bottom;
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
- yd -= 2*asq;
- d -= yd;
- }
- rect.x--; /* next horiz point */
- rect.width += 2;
- xd += 2*bsq;
- d += bsq + xd;
+ if (d > 0) /* if nearest pixel is toward the center */
+ {
+ /* move toward center */
+ rect.top = top++;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRegion( &rect, obj->rgn );
+ rect.top = --bottom;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRegion( &rect, obj->rgn );
+ yd -= 2*asq;
+ d -= yd;
+ }
+ rect.left--; /* next horiz point */
+ rect.right++;
+ xd += 2*bsq;
+ d += bsq + xd;
}
/* Loop to draw second half of quadrant */
@@ -270,30 +412,33 @@
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
while (yd >= 0)
{
- /* next vertical point */
- rect.y = top++;
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
- rect.y = --bottom;
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
- if (d < 0) /* if nearest pixel is outside ellipse */
- {
- rect.x--; /* move away from center */
- rect.width += 2;
- xd += 2*bsq;
- d += xd;
- }
- yd -= 2*asq;
- d += asq - yd;
+ /* next vertical point */
+ rect.top = top++;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRegion( &rect, obj->rgn );
+ rect.top = --bottom;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRegion( &rect, obj->rgn );
+ if (d < 0) /* if nearest pixel is outside ellipse */
+ {
+ rect.left--; /* move away from center */
+ rect.right++;
+ xd += 2*bsq;
+ d += xd;
+ }
+ yd -= 2*asq;
+ d += asq - yd;
}
/* Add the inside rectangle */
if (top <= bottom)
{
- rect.y = top;
- rect.height = bottom - top + 1;
- XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
+ rect.top = top;
+ rect.bottom = bottom;
+ REGION_UnionRectWithRegion( &rect, obj->rgn );
}
+ obj->rgn->type = SIMPLEREGION; /* FIXME? */
GDI_HEAP_UNLOCK( hrgn );
return hrgn;
}
@@ -303,10 +448,10 @@
* CreateEllipticRgn16 (GDI.54)
*/
HRGN16 WINAPI CreateEllipticRgn16( INT16 left, INT16 top,
- INT16 right, INT16 bottom )
+ INT16 right, INT16 bottom )
{
return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
- right-left, bottom-top );
+ right-left, bottom-top );
}
@@ -314,10 +459,10 @@
* CreateEllipticRgn32 (GDI32.39)
*/
HRGN32 WINAPI CreateEllipticRgn32( INT32 left, INT32 top,
- INT32 right, INT32 bottom )
+ INT32 right, INT32 bottom )
{
return CreateRoundRectRgn32( left, top, right, bottom,
- right-left, bottom-top );
+ right-left, bottom-top );
}
@@ -327,8 +472,8 @@
HRGN16 WINAPI CreateEllipticRgnIndirect16( const RECT16 *rect )
{
return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
- rect->bottom, rect->right - rect->left,
- rect->bottom - rect->top );
+ rect->bottom, rect->right - rect->left,
+ rect->bottom - rect->top );
}
@@ -338,132 +483,82 @@
HRGN32 WINAPI CreateEllipticRgnIndirect32( const RECT32 *rect )
{
return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
- rect->bottom, rect->right - rect->left,
- rect->bottom - rect->top );
+ rect->bottom, rect->right - rect->left,
+ rect->bottom - rect->top );
}
-
/***********************************************************************
- * CreatePolygonRgn16 (GDI.63)
+ * GetRegionData (GDI32.217)
+ *
*/
-HRGN16 WINAPI CreatePolygonRgn16( const POINT16 * points, INT16 count,
- INT16 mode )
+DWORD WINAPI GetRegionData(HRGN32 hrgn, DWORD count, LPRGNDATA rgndata)
{
- return CreatePolyPolygonRgn16( points, &count, 1, mode );
-}
+ DWORD size;
+ RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
+
+ dprintf_region(stddeb, "GetRegionData: %04x count = %ld, rgndata = %p\n",
+ hrgn, count, rgndata);
+ if(!obj) return 0;
-/***********************************************************************
- * CreatePolyPolygonRgn16 (GDI.451)
- */
-HRGN16 WINAPI CreatePolyPolygonRgn16( const POINT16 * points,
- const INT16 * count,
- INT16 nbpolygons, INT16 mode )
-{
- int i,nrofpts;
- LPINT32 count32;
- LPPOINT32 points32;
- HRGN32 ret;
-
- nrofpts=0;
- for (i=nbpolygons;i--;)
- nrofpts+=count[i];
- points32 = (LPPOINT32)HeapAlloc( GetProcessHeap(), 0,
- nrofpts*sizeof(POINT32) );
- for (i=nrofpts;i--;)
- CONV_POINT16TO32( &(points[i]), &(points32[i]) );
- count32 = (LPINT32)HeapAlloc( GetProcessHeap(), 0,
- sizeof(INT32)*nbpolygons );
- for (i=nbpolygons;i--;)
- count32[i]=count[i];
- ret = CreatePolyPolygonRgn32(points32,count32,nbpolygons,mode);
- HeapFree( GetProcessHeap(), 0, count32 );
- HeapFree( GetProcessHeap(), 0, points32 );
- return ret;
-}
-
-
-/***********************************************************************
- * CreatePolygonRgn32 (GDI32.58)
- */
-HRGN32 WINAPI CreatePolygonRgn32( const POINT32 *points, INT32 count,
- INT32 mode )
-{
- return CreatePolyPolygonRgn32( points, &count, 1, mode );
-}
-
-
-/***********************************************************************
- * CreatePolyPolygonRgn32 (GDI32.57)
- */
-HRGN32 WINAPI CreatePolyPolygonRgn32( const POINT32 * points,
- const INT32 * count,
- INT32 nbpolygons, INT32 mode )
-{
- RGNOBJ * obj;
- HRGN32 hrgn;
- int i, j, maxPoints;
- XPoint *xpoints, *pt;
- Region xrgn;
-
- /* Allocate points array */
-
- if (!nbpolygons) return 0;
- for (i = maxPoints = 0; i < nbpolygons; i++)
- if (maxPoints < count[i]) maxPoints = count[i];
- if (!maxPoints) return 0;
- if (!(xpoints = (XPoint *)HeapAlloc( GetProcessHeap(), 0,
- sizeof(XPoint) * maxPoints )))
- return 0;
-
- /* Allocate region */
-
- if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
+ size = obj->rgn->numRects * sizeof(RECT32);
+ if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
{
- HeapFree( GetProcessHeap(), 0, xpoints );
+ GDI_HEAP_UNLOCK( hrgn );
+ return size;
+ }
+
+ rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
+ rgndata->rdh.iType = RDH_RECTANGLES;
+ rgndata->rdh.nCount = obj->rgn->numRects;
+ rgndata->rdh.nRgnSize = size;
+ rgndata->rdh.rcBound.left = obj->rgn->extents.left;
+ rgndata->rdh.rcBound.top = obj->rgn->extents.top;
+ rgndata->rdh.rcBound.right = obj->rgn->extents.right;
+ rgndata->rdh.rcBound.bottom = obj->rgn->extents.bottom;
+
+ memcpy( rgndata->Buffer, obj->rgn->rects, size );
+
+ GDI_HEAP_UNLOCK( hrgn );
+ return 1;
+}
+
+/***********************************************************************
+ * ExtCreateRegion (GDI32.94)
+ *
+ */
+HRGN32 WINAPI ExtCreateRegion( XFORM *lpXform, DWORD dwCount, RGNDATA *rgndata)
+{
+ HRGN32 hrgn = CreateRectRgn32(0, 0, 0, 0);
+ RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
+ RECT32 *pCurRect, *pEndRect;
+
+ dprintf_region(stddeb, "ExtCreateRegion: %p %ld %p. Returning %04x\n",
+ lpXform, dwCount, rgndata, hrgn);
+ if(!hrgn)
+ {
+ fprintf(stderr, "ExtCreateRegion can't create a region!\n");
return 0;
}
- obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
- obj->xrgn = 0;
- dprintf_region(stddeb, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
- nbpolygons, hrgn );
-
- /* Create X region */
-
- for (i = 0; i < nbpolygons; i++, count++)
+ if(lpXform)
+ fprintf(stderr, "ExtCreateRegion: Xform not implemented - ignoring\n");
+
+ if(rgndata->rdh.iType != RDH_RECTANGLES)
{
- if (*count <= 1) continue;
- for (j = *count, pt = xpoints; j > 0; j--, points++, pt++)
- {
- pt->x = points->x;
- pt->y = points->y;
- }
- xrgn = XPolygonRegion( xpoints, *count,
- (mode == WINDING) ? WindingRule : EvenOddRule );
- if (!xrgn)
- {
- if (obj->xrgn) XDestroyRegion( obj->xrgn );
- HeapFree( GetProcessHeap(), 0, xpoints );
- GDI_FreeObject( hrgn );
- return 0;
- }
- if (obj->xrgn)
- {
- Region tmprgn = XCreateRegion();
- if (mode == WINDING) XUnionRegion( xrgn, obj->xrgn, tmprgn );
- else XXorRegion( xrgn, obj->xrgn, tmprgn );
- XDestroyRegion( obj->xrgn );
- obj->xrgn = tmprgn;
- }
- else obj->xrgn = xrgn;
+ fprintf(stderr, "ExtCreateRegion: type not RDH_RECTANGLES\n");
+ GDI_HEAP_UNLOCK( hrgn );
+ DeleteObject32( hrgn );
+ return 0;
}
- HeapFree( GetProcessHeap(), 0, xpoints );
+ pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
+ for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
+ REGION_UnionRectWithRegion( pCurRect, obj->rgn );
+
GDI_HEAP_UNLOCK( hrgn );
return hrgn;
}
-
/***********************************************************************
* PtInRegion16 (GDI.161)
*/
@@ -482,11 +577,13 @@
if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
{
- BOOL32 ret;
- if (obj->xrgn)
- ret = XPointInRegion( obj->xrgn, x, y );
- else
- ret = FALSE;
+ BOOL32 ret = FALSE;
+ int i;
+
+ if (obj->rgn->numRects > 0 && INRECT(obj->rgn->extents, x, y))
+ for (i = 0; i < obj->rgn->numRects; i++)
+ if (INRECT (obj->rgn->rects[i], x, y))
+ ret = TRUE;
GDI_HEAP_UNLOCK( hrgn );
return ret;
}
@@ -499,25 +596,17 @@
*/
BOOL16 WINAPI RectInRegion16( HRGN16 hrgn, const RECT16 *rect )
{
- RGNOBJ * obj;
+ RECT32 r32;
- if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
- {
- BOOL16 ret;
- if (obj->xrgn)
- ret = (XRectInRegion( obj->xrgn, rect->left, rect->top,
- rect->right-rect->left, rect->bottom-rect->top ) != RectangleOut);
- else
- ret = FALSE;
- GDI_HEAP_UNLOCK( hrgn );
- return ret;
- }
- return FALSE;
+ CONV_RECT16TO32(rect, &r32);
+ return (BOOL16)RectInRegion32(hrgn, &r32);
}
/***********************************************************************
* RectInRegion32 (GDI32.281)
+ *
+ * Returns TRUE if rect is at least partly inside hrgn
*/
BOOL32 WINAPI RectInRegion32( HRGN32 hrgn, const RECT32 *rect )
{
@@ -525,19 +614,42 @@
if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
{
- BOOL32 ret;
- if (obj->xrgn)
- ret = (XRectInRegion( obj->xrgn, rect->left, rect->top,
- rect->right-rect->left, rect->bottom-rect->top ) != RectangleOut);
- else
- ret = FALSE;
- GDI_HEAP_UNLOCK( hrgn );
+ RECT32 *pCurRect, *pRectEnd;
+ BOOL32 ret = FALSE;
+
+ /* this is (just) a useful optimization */
+ if ((obj->rgn->numRects > 0) && EXTENTCHECK(&obj->rgn->extents,
+ rect))
+ {
+ for (pCurRect = obj->rgn->rects, pRectEnd = pCurRect +
+ obj->rgn->numRects; pCurRect < pRectEnd; pCurRect++)
+ {
+ if (pCurRect->bottom <= rect->top)
+ continue; /* not far enough down yet */
+
+ if (pCurRect->top >= rect->bottom) {
+ ret = FALSE; /* too far down */
+ break;
+ }
+
+ if (pCurRect->right <= rect->left)
+ continue; /* not far enough over yet */
+
+ if (pCurRect->left >= rect->right) {
+ ret = FALSE; /* too far over */
+ break;
+ }
+
+ ret = TRUE;
+ break;
+ }
+ }
+ GDI_HEAP_UNLOCK(hrgn);
return ret;
}
return FALSE;
}
-
/***********************************************************************
* EqualRgn16 (GDI.72)
*/
@@ -550,122 +662,97 @@
/***********************************************************************
* EqualRgn32 (GDI32.90)
*/
-BOOL32 WINAPI EqualRgn32( HRGN32 rgn1, HRGN32 rgn2 )
+BOOL32 WINAPI EqualRgn32( HRGN32 hrgn1, HRGN32 hrgn2 )
{
RGNOBJ *obj1, *obj2;
BOOL32 ret = FALSE;
- if ((obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC )))
+ if ((obj1 = (RGNOBJ *) GDI_GetObjPtr( hrgn1, REGION_MAGIC )))
{
- if ((obj2 = (RGNOBJ *) GDI_GetObjPtr( rgn2, REGION_MAGIC )))
+ if ((obj2 = (RGNOBJ *) GDI_GetObjPtr( hrgn2, REGION_MAGIC )))
{
- if (!obj1->xrgn || !obj2->xrgn)
- ret = (!obj1->xrgn && !obj2->xrgn);
- else
- ret = XEqualRegion( obj1->xrgn, obj2->xrgn );
- GDI_HEAP_UNLOCK( rgn2 );
+ int i;
+
+ ret = TRUE;
+ if ( obj1->rgn->numRects != obj2->rgn->numRects ) ret = FALSE;
+ else if ( obj1->rgn->numRects == 0 ) ret = TRUE;
+ else if ( !EqualRect32(&obj1->rgn->extents, &obj2->rgn->extents) )
+ ret = FALSE;
+ else for( i = 0; i < obj1->rgn->numRects; i++ ) {
+ if (!EqualRect32(obj1->rgn->rects + i, obj2->rgn->rects + i)) {
+ ret = FALSE;
+ break;
+ }
+ }
+ GDI_HEAP_UNLOCK(hrgn2);
}
- GDI_HEAP_UNLOCK( rgn1 );
+ GDI_HEAP_UNLOCK(hrgn1);
}
return ret;
}
-
-
/***********************************************************************
- * REGION_CopyRegion
- *
- * Copy region src into dest.
+ * REGION_UnionRectWithRegion
+ * Adds a rectangle to a WINEREGION
+ * See below for REGION_UnionRectWithRgn
*/
-static INT32 REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest )
+static void REGION_UnionRectWithRegion(const RECT32 *rect, WINEREGION *rgn)
{
- Region tmprgn;
- if (src->xrgn)
- {
- if (src->xrgn == dest->xrgn) return COMPLEXREGION;
- tmprgn = XCreateRegion();
- if (!dest->xrgn) dest->xrgn = XCreateRegion();
- XUnionRegion( tmprgn, src->xrgn, dest->xrgn );
- XDestroyRegion( tmprgn );
- return COMPLEXREGION;
- }
- else
- {
- if (dest->xrgn) XDestroyRegion( dest->xrgn );
- dest->xrgn = 0;
- return NULLREGION;
- }
+ WINEREGION region;
+
+ region.rects = ®ion.extents;
+ region.numRects = 1;
+ region.size = 1;
+ region.type = SIMPLEREGION;
+ CopyRect32(&(region.extents), rect);
+ REGION_UnionRegion(rgn, rgn, ®ion);
+ return;
}
-
-/***********************************************************************
- * REGION_IsEmpty
- */
-BOOL32 REGION_IsEmpty( HRGN32 hRgn )
-{
- RGNOBJ* rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
- BOOL32 ret = TRUE;
-
- if( rgnObj )
- {
- if( rgnObj->xrgn && !XEmptyRegion(rgnObj->xrgn) ) ret = FALSE;
- GDI_HEAP_UNLOCK( hRgn );
- }
- return ret;
-}
-
-
/***********************************************************************
* REGION_UnionRectWithRgn
- *
- * Add rc rectangle to the region.
+ * Adds a rectangle to a HRGN32
+ * A helper used by scroll.c
*/
-BOOL32 REGION_UnionRectWithRgn( HRGN32 hRgn, const RECT32 *rc )
+BOOL32 REGION_UnionRectWithRgn( HRGN32 hrgn, const RECT32 *lpRect )
{
- RGNOBJ* rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
- XRectangle rect = { rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top };
- BOOL32 ret = ERROR;
+ RGNOBJ *obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
- if( rgnObj )
- {
- if( !rgnObj->xrgn )
- {
- if ((rgnObj->xrgn = XCreateRegion()))
- ret = SIMPLEREGION;
- else
- goto done;
- }
- else
- ret = COMPLEXREGION;
- XUnionRectWithRegion( &rect, rgnObj->xrgn, rgnObj->xrgn );
-done:
- GDI_HEAP_UNLOCK( hRgn );
- }
- return ret;
+ if(!obj) return FALSE;
+ REGION_UnionRectWithRegion( lpRect, obj->rgn );
+ GDI_HEAP_UNLOCK(hrgn);
+ return TRUE;
}
-
/***********************************************************************
* REGION_CreateFrameRgn
*
- * Create a region that is a frame around another region
+ * Create a region that is a frame around another region.
+ * Expand all rectangles by +/- x and y, then subtract original region.
*/
BOOL32 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y )
{
BOOL32 bRet;
RGNOBJ *srcObj = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
- if (srcObj->xrgn)
+ if (srcObj->rgn->numRects != 0)
{
RGNOBJ* destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
- Region resRgn;
+ RECT32 *pRect, *pEndRect;
+ RECT32 tempRect;
- REGION_CopyRegion( srcObj, destObj );
- XShrinkRegion( destObj->xrgn, -x, -y );
- resRgn = XCreateRegion();
- XSubtractRegion( destObj->xrgn, srcObj->xrgn, resRgn );
- XDestroyRegion( destObj->xrgn );
- destObj->xrgn = resRgn;
- GDI_HEAP_UNLOCK( hDest );
+ EMPTY_REGION( destObj->rgn );
+
+ pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
+ for(pRect = srcObj->rgn->rects; pRect < pEndRect; pRect++)
+ {
+ tempRect.left = pRect->left - x;
+ tempRect.top = pRect->top - y;
+ tempRect.right = pRect->right + x;
+ tempRect.bottom = pRect->bottom + y;
+ REGION_UnionRectWithRegion( &tempRect, destObj->rgn );
+ }
+ REGION_SubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn );
+ GDI_HEAP_UNLOCK ( hDest );
bRet = TRUE;
}
else
@@ -674,7 +761,55 @@
return bRet;
}
+/***********************************************************************
+ * REGION_LPTODP
+ *
+ * Convert region to device co-ords for the supplied dc.
+ * Used by X11DRV_PaintRgn.
+ */
+BOOL32 REGION_LPTODP( HDC32 hdc, HRGN32 hDest, HRGN32 hSrc )
+{
+ RECT32 *pCurRect, *pEndRect;
+ RGNOBJ *srcObj, *destObj;
+ DC * dc = DC_GetDCPtr( hdc );
+ RECT32 tmpRect;
+ dprintf_region( stddeb, "REGION_LPTODP: hdc=%04x dest=%04x src=%04x\n",
+ hdc, hDest, hSrc) ;
+
+ if (dc->w.MapMode == MM_TEXT) /* Requires only a translation */
+ {
+ if( CombineRgn32( hDest, hSrc, 0, RGN_COPY ) == ERROR ) return FALSE;
+ OffsetRgn32( hDest, dc->vportOrgX - dc->wndOrgX,
+ dc->vportOrgY - dc->wndOrgY );
+ return TRUE;
+ }
+
+ if(!( srcObj = (RGNOBJ *) GDI_GetObjPtr( hSrc, REGION_MAGIC) ))
+ return FALSE;
+ if(!( destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC) ))
+ {
+ GDI_HEAP_UNLOCK( hSrc );
+ return FALSE;
+ }
+ EMPTY_REGION( destObj->rgn );
+
+ pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
+ for(pCurRect = srcObj->rgn->rects; pCurRect < pEndRect; pCurRect++)
+ {
+ tmpRect = *pCurRect;
+ tmpRect.left = XLPTODP( dc, tmpRect.left );
+ tmpRect.top = YLPTODP( dc, tmpRect.top );
+ tmpRect.right = XLPTODP( dc, tmpRect.right );
+ tmpRect.bottom = YLPTODP( dc, tmpRect.bottom );
+ REGION_UnionRectWithRegion( &tmpRect, destObj->rgn );
+ }
+
+ GDI_HEAP_UNLOCK( hDest );
+ GDI_HEAP_UNLOCK( hSrc );
+ return TRUE;
+}
+
/***********************************************************************
* CombineRgn16 (GDI.451)
*/
@@ -702,107 +837,1673 @@
if (src1Obj)
{
+ dprintf_region(stddeb, "src1:\n");
+ if(debugging_region) REGION_DumpRegion(src1Obj->rgn);
if (mode == RGN_COPY)
- result = REGION_CopyRegion( src1Obj, destObj );
+ {
+ REGION_CopyRegion( destObj->rgn, src1Obj->rgn );
+ result = destObj->rgn->type;
+ }
else
{
RGNOBJ *src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC);
if (src2Obj)
{
- if (!src1Obj->xrgn || !src2Obj->xrgn)
+ dprintf_region(stddeb, "src2:\n");
+ if(debugging_region) REGION_DumpRegion(src2Obj->rgn);
+ switch (mode)
{
- /* Some optimizations for null regions */
- switch( mode )
- {
- case RGN_DIFF:
- if (src1Obj->xrgn)
- {
- result = REGION_CopyRegion( src1Obj, destObj );
- break;
- }
- /* else fall through */
- case RGN_AND:
- if (destObj->xrgn)
- {
- XDestroyRegion( destObj->xrgn );
- destObj->xrgn = 0;
- }
- result = NULLREGION;
- break;
-
- case RGN_OR:
- case RGN_XOR:
-#define __SRC_RGN ((src1Obj->xrgn) ? src1Obj : src2Obj)
- result = REGION_CopyRegion( __SRC_RGN, destObj );
-#undef __SRC_RGN
- break;
-
- case 0:
- default:
- /* makes gcc generate more efficient code */
- }
+ case RGN_AND:
+ REGION_IntersectRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn);
+ break;
+ case RGN_OR:
+ REGION_UnionRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
+ break;
+ case RGN_XOR:
+ REGION_XorRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
+ break;
+ case RGN_DIFF:
+ REGION_SubtractRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
+ break;
}
- else /* both regions are present */
- {
- Region destRgn = XCreateRegion();
-
- if (destRgn)
- {
- switch (mode)
- {
- case RGN_AND:
- XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
- break;
- case RGN_OR:
- XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
- break;
- case RGN_XOR:
- XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
- break;
- case RGN_DIFF:
- XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
- break;
-
- case 0: /* makes gcc generate more efficient code */
- default:
- XDestroyRegion( destRgn );
- goto done;
- }
-
- if ( destObj->xrgn )
- XDestroyRegion( destObj->xrgn );
- if ( XEmptyRegion( destRgn ) )
- {
- XDestroyRegion( destRgn );
- destObj->xrgn = 0;
- result = NULLREGION;
- }
- else
- {
- destObj->xrgn = destRgn;
- result = COMPLEXREGION;
- }
- }
- }
-done:
+ result = destObj->rgn->type;
GDI_HEAP_UNLOCK( hSrc2 );
}
}
GDI_HEAP_UNLOCK( hSrc1 );
}
+ dprintf_region(stddeb, "dest:\n");
+ if(debugging_region) REGION_DumpRegion(destObj->rgn);
+
GDI_HEAP_UNLOCK( hDest );
}
return result;
}
/***********************************************************************
- * GetRegionData (GDI32.217)
- *
- * This seems to be rather impossible with the current region implementation
- * for it seems you cannot query X regions.
+ * REGION_SetExtents
+ * Re-calculate the extents of a region
*/
-DWORD WINAPI GetRegionData(HRGN32 hrgn,DWORD x,LPRGNDATA rgndata) {
- fprintf(stderr,"GetRegionData(%04x,%08lx,%p), STUB!\n",hrgn,x,rgndata);
+static void REGION_SetExtents (WINEREGION *pReg)
+{
+ RECT32 *pRect, *pRectEnd, *pExtents;
+
+ if (pReg->numRects == 0)
+ {
+ pReg->extents.left = 0;
+ pReg->extents.top = 0;
+ pReg->extents.right = 0;
+ pReg->extents.bottom = 0;
+ return;
+ }
+
+ pExtents = &pReg->extents;
+ pRect = pReg->rects;
+ pRectEnd = &pRect[pReg->numRects - 1];
+
+ /*
+ * Since pRect is the first rectangle in the region, it must have the
+ * smallest top and since pRectEnd is the last rectangle in the region,
+ * it must have the largest bottom, because of banding. Initialize left and
+ * right from pRect and pRectEnd, resp., as good things to initialize them
+ * to...
+ */
+ pExtents->left = pRect->left;
+ pExtents->top = pRect->top;
+ pExtents->right = pRectEnd->right;
+ pExtents->bottom = pRectEnd->bottom;
+
+ while (pRect <= pRectEnd)
+ {
+ if (pRect->left < pExtents->left)
+ pExtents->left = pRect->left;
+ if (pRect->right > pExtents->right)
+ pExtents->right = pRect->right;
+ pRect++;
+ }
+}
+
+/***********************************************************************
+ * REGION_CopyRegion
+ */
+static void REGION_CopyRegion(WINEREGION *dst, WINEREGION *src)
+{
+ if (dst != src) /* don't want to copy to itself */
+ {
+ if (dst->size < src->numRects)
+ {
+ if (! (dst->rects = HeapReAlloc( SystemHeap, 0, dst->rects,
+ src->numRects * sizeof(RECT32) )))
+ return;
+ dst->size = src->numRects;
+ }
+ dst->numRects = src->numRects;
+ dst->extents.left = src->extents.left;
+ dst->extents.top = src->extents.top;
+ dst->extents.right = src->extents.right;
+ dst->extents.bottom = src->extents.bottom;
+ dst->type = src->type;
+
+ memcpy((char *) dst->rects, (char *) src->rects,
+ (int) (src->numRects * sizeof(RECT32)));
+ }
+ return;
+}
+
+/***********************************************************************
+ * REGION_Coalesce
+ *
+ * Attempt to merge the rects in the current band with those in the
+ * previous one. Used only by REGION_RegionOp.
+ *
+ * Results:
+ * The new index for the previous band.
+ *
+ * Side Effects:
+ * If coalescing takes place:
+ * - rectangles in the previous band will have their bottom fields
+ * altered.
+ * - pReg->numRects will be decreased.
+ *
+ */
+static INT32 REGION_Coalesce (WINEREGION *pReg, INT32 prevStart,
+ INT32 curStart)
+ /* pReg - Region to coalesce */
+ /* prevStart - Index of start of previous band */
+ /* curStart - Index of start of current band */
+{
+ RECT32 *pPrevRect; /* Current rect in previous band */
+ RECT32 *pCurRect; /* Current rect in current band */
+ RECT32 *pRegEnd; /* End of region */
+ INT32 curNumRects; /* Number of rectangles in current band */
+ INT32 prevNumRects; /* Number of rectangles in previous band */
+ INT32 bandtop; /* top coordinate for current band */
+
+ pRegEnd = &pReg->rects[pReg->numRects];
+
+ pPrevRect = &pReg->rects[prevStart];
+ prevNumRects = curStart - prevStart;
+
+ /*
+ * Figure out how many rectangles are in the current band. Have to do
+ * this because multiple bands could have been added in REGION_RegionOp
+ * at the end when one region has been exhausted.
+ */
+ pCurRect = &pReg->rects[curStart];
+ bandtop = pCurRect->top;
+ for (curNumRects = 0;
+ (pCurRect != pRegEnd) && (pCurRect->top == bandtop);
+ curNumRects++)
+ {
+ pCurRect++;
+ }
+
+ if (pCurRect != pRegEnd)
+ {
+ /*
+ * If more than one band was added, we have to find the start
+ * of the last band added so the next coalescing job can start
+ * at the right place... (given when multiple bands are added,
+ * this may be pointless -- see above).
+ */
+ pRegEnd--;
+ while (pRegEnd[-1].top == pRegEnd->top)
+ {
+ pRegEnd--;
+ }
+ curStart = pRegEnd - pReg->rects;
+ pRegEnd = pReg->rects + pReg->numRects;
+ }
+
+ if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
+ pCurRect -= curNumRects;
+ /*
+ * The bands may only be coalesced if the bottom of the previous
+ * matches the top scanline of the current.
+ */
+ if (pPrevRect->bottom == pCurRect->top)
+ {
+ /*
+ * Make sure the bands have rects in the same places. This
+ * assumes that rects have been added in such a way that they
+ * cover the most area possible. I.e. two rects in a band must
+ * have some horizontal space between them.
+ */
+ do
+ {
+ if ((pPrevRect->left != pCurRect->left) ||
+ (pPrevRect->right != pCurRect->right))
+ {
+ /*
+ * The bands don't line up so they can't be coalesced.
+ */
+ return (curStart);
+ }
+ pPrevRect++;
+ pCurRect++;
+ prevNumRects -= 1;
+ } while (prevNumRects != 0);
+
+ pReg->numRects -= curNumRects;
+ pCurRect -= curNumRects;
+ pPrevRect -= curNumRects;
+
+ /*
+ * The bands may be merged, so set the bottom of each rect
+ * in the previous band to that of the corresponding rect in
+ * the current band.
+ */
+ do
+ {
+ pPrevRect->bottom = pCurRect->bottom;
+ pPrevRect++;
+ pCurRect++;
+ curNumRects -= 1;
+ } while (curNumRects != 0);
+
+ /*
+ * If only one band was added to the region, we have to backup
+ * curStart to the start of the previous band.
+ *
+ * If more than one band was added to the region, copy the
+ * other bands down. The assumption here is that the other bands
+ * came from the same region as the current one and no further
+ * coalescing can be done on them since it's all been done
+ * already... curStart is already in the right place.
+ */
+ if (pCurRect == pRegEnd)
+ {
+ curStart = prevStart;
+ }
+ else
+ {
+ do
+ {
+ *pPrevRect++ = *pCurRect++;
+ } while (pCurRect != pRegEnd);
+ }
+
+ }
+ }
+ return (curStart);
+}
+
+/***********************************************************************
+ * REGION_RegionOp
+ *
+ * Apply an operation to two regions. Called by REGION_Union,
+ * REGION_Inverse, REGION_Subtract, REGION_Intersect...
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The new region is overwritten.
+ *
+ * Notes:
+ * The idea behind this function is to view the two regions as sets.
+ * Together they cover a rectangle of area that this function divides
+ * into horizontal bands where points are covered only by one region
+ * or by both. For the first case, the nonOverlapFunc is called with
+ * each the band and the band's upper and lower extents. For the
+ * second, the overlapFunc is called to process the entire band. It
+ * is responsible for clipping the rectangles in the band, though
+ * this function provides the boundaries.
+ * At the end of each band, the new region is coalesced, if possible,
+ * to reduce the number of rectangles in the region.
+ *
+ */
+static void REGION_RegionOp(WINEREGION *newReg, WINEREGION *reg1,
+ WINEREGION *reg2, void (*overlapFunc)(), void (*nonOverlap1Func)(),
+ void (*nonOverlap2Func)())
+
+ /* newReg - Place to store result */
+ /* reg1 - First region in operation */
+ /* reg2 - 2nd region in operation */
+ /* overlapFunc - Function to call for over-lapping bands */
+ /* nonOverlap1Func - Function to call for non-overlapping bands in
+ region 1 */
+ /* nonOverlap2Func - Function to call for non-overlapping bands in
+ region 2 */
+{
+ RECT32 *r1; /* Pointer into first region */
+ RECT32 *r2; /* Pointer into 2d region */
+ RECT32 *r1End; /* End of 1st region */
+ RECT32 *r2End; /* End of 2d region */
+ INT32 ybot; /* Bottom of intersection */
+ INT32 ytop; /* Top of intersection */
+ RECT32 *oldRects; /* Old rects for newReg */
+ INT32 prevBand; /* Index of start of
+ * previous band in newReg */
+ INT32 curBand; /* Index of start of current
+ * band in newReg */
+ RECT32 *r1BandEnd; /* End of current band in r1 */
+ RECT32 *r2BandEnd; /* End of current band in r2 */
+ INT32 top; /* Top of non-overlapping band */
+ INT32 bot; /* Bottom of non-overlapping band */
+
+ /*
+ * Initialization:
+ * set r1, r2, r1End and r2End appropriately, preserve the important
+ * parts of the destination region until the end in case it's one of
+ * the two source regions, then mark the "new" region empty, allocating
+ * another array of rectangles for it to use.
+ */
+ r1 = reg1->rects;
+ r2 = reg2->rects;
+ r1End = r1 + reg1->numRects;
+ r2End = r2 + reg2->numRects;
+
+ oldRects = newReg->rects;
+
+ EMPTY_REGION(newReg);
+
+ /*
+ * Allocate a reasonable number of rectangles for the new region. The idea
+ * is to allocate enough so the individual functions don't need to
+ * reallocate and copy the array, which is time consuming, yet we don't
+ * have to worry about using too much memory. I hope to be able to
+ * nuke the Xrealloc() at the end of this function eventually.
+ */
+ newReg->size = MAX(reg1->numRects,reg2->numRects) * 2;
+
+ if (! (newReg->rects = HeapAlloc( SystemHeap, 0,
+ sizeof(RECT32) * newReg->size )))
+ {
+ newReg->size = 0;
+ return;
+ }
+
+ /*
+ * Initialize ybot and ytop.
+ * In the upcoming loop, ybot and ytop serve different functions depending
+ * on whether the band being handled is an overlapping or non-overlapping
+ * band.
+ * In the case of a non-overlapping band (only one of the regions
+ * has points in the band), ybot is the bottom of the most recent
+ * intersection and thus clips the top of the rectangles in that band.
+ * ytop is the top of the next intersection between the two regions and
+ * serves to clip the bottom of the rectangles in the current band.
+ * For an overlapping band (where the two regions intersect), ytop clips
+ * the top of the rectangles of both regions and ybot clips the bottoms.
+ */
+ if (reg1->extents.top < reg2->extents.top)
+ ybot = reg1->extents.top;
+ else
+ ybot = reg2->extents.top;
+
+ /*
+ * prevBand serves to mark the start of the previous band so rectangles
+ * can be coalesced into larger rectangles. qv. miCoalesce, above.
+ * In the beginning, there is no previous band, so prevBand == curBand
+ * (curBand is set later on, of course, but the first band will always
+ * start at index 0). prevBand and curBand must be indices because of
+ * the possible expansion, and resultant moving, of the new region's
+ * array of rectangles.
+ */
+ prevBand = 0;
+
+ do
+ {
+ curBand = newReg->numRects;
+
+ /*
+ * This algorithm proceeds one source-band (as opposed to a
+ * destination band, which is determined by where the two regions
+ * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
+ * rectangle after the last one in the current band for their
+ * respective regions.
+ */
+ r1BandEnd = r1;
+ while ((r1BandEnd != r1End) && (r1BandEnd->top == r1->top))
+ {
+ r1BandEnd++;
+ }
+
+ r2BandEnd = r2;
+ while ((r2BandEnd != r2End) && (r2BandEnd->top == r2->top))
+ {
+ r2BandEnd++;
+ }
+
+ /*
+ * First handle the band that doesn't intersect, if any.
+ *
+ * Note that attention is restricted to one band in the
+ * non-intersecting region at once, so if a region has n
+ * bands between the current position and the next place it overlaps
+ * the other, this entire loop will be passed through n times.
+ */
+ if (r1->top < r2->top)
+ {
+ top = MAX(r1->top,ybot);
+ bot = MIN(r1->bottom,r2->top);
+
+ if ((top != bot) && (nonOverlap1Func != (void (*)())NULL))
+ {
+ (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot);
+ }
+
+ ytop = r2->top;
+ }
+ else if (r2->top < r1->top)
+ {
+ top = MAX(r2->top,ybot);
+ bot = MIN(r2->bottom,r1->top);
+
+ if ((top != bot) && (nonOverlap2Func != (void (*)())NULL))
+ {
+ (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot);
+ }
+
+ ytop = r1->top;
+ }
+ else
+ {
+ ytop = r1->top;
+ }
+
+ /*
+ * If any rectangles got added to the region, try and coalesce them
+ * with rectangles from the previous band. Note we could just do
+ * this test in miCoalesce, but some machines incur a not
+ * inconsiderable cost for function calls, so...
+ */
+ if (newReg->numRects != curBand)
+ {
+ prevBand = REGION_Coalesce (newReg, prevBand, curBand);
+ }
+
+ /*
+ * Now see if we've hit an intersecting band. The two bands only
+ * intersect if ybot > ytop
+ */
+ ybot = MIN(r1->bottom, r2->bottom);
+ curBand = newReg->numRects;
+ if (ybot > ytop)
+ {
+ (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
+
+ }
+
+ if (newReg->numRects != curBand)
+ {
+ prevBand = REGION_Coalesce (newReg, prevBand, curBand);
+ }
+
+ /*
+ * If we've finished with a band (bottom == ybot) we skip forward
+ * in the region to the next band.
+ */
+ if (r1->bottom == ybot)
+ {
+ r1 = r1BandEnd;
+ }
+ if (r2->bottom == ybot)
+ {
+ r2 = r2BandEnd;
+ }
+ } while ((r1 != r1End) && (r2 != r2End));
+
+ /*
+ * Deal with whichever region still has rectangles left.
+ */
+ curBand = newReg->numRects;
+ if (r1 != r1End)
+ {
+ if (nonOverlap1Func != (void (*)())NULL)
+ {
+ do
+ {
+ r1BandEnd = r1;
+ while ((r1BandEnd < r1End) && (r1BandEnd->top == r1->top))
+ {
+ r1BandEnd++;
+ }
+ (* nonOverlap1Func) (newReg, r1, r1BandEnd,
+ MAX(r1->top,ybot), r1->bottom);
+ r1 = r1BandEnd;
+ } while (r1 != r1End);
+ }
+ }
+ else if ((r2 != r2End) && (nonOverlap2Func != (void (*)())NULL))
+ {
+ do
+ {
+ r2BandEnd = r2;
+ while ((r2BandEnd < r2End) && (r2BandEnd->top == r2->top))
+ {
+ r2BandEnd++;
+ }
+ (* nonOverlap2Func) (newReg, r2, r2BandEnd,
+ MAX(r2->top,ybot), r2->bottom);
+ r2 = r2BandEnd;
+ } while (r2 != r2End);
+ }
+
+ if (newReg->numRects != curBand)
+ {
+ (void) REGION_Coalesce (newReg, prevBand, curBand);
+ }
+
+ /*
+ * A bit of cleanup. To keep regions from growing without bound,
+ * we shrink the array of rectangles to match the new number of
+ * rectangles in the region. This never goes to 0, however...
+ *
+ * Only do this stuff if the number of rectangles allocated is more than
+ * twice the number of rectangles in the region (a simple optimization...).
+ */
+ if (newReg->numRects < (newReg->size >> 1))
+ {
+ if (REGION_NOT_EMPTY(newReg))
+ {
+ RECT32 *prev_rects = newReg->rects;
+ newReg->size = newReg->numRects;
+ newReg->rects = HeapReAlloc( SystemHeap, 0, newReg->rects,
+ sizeof(RECT32) * newReg->size );
+ if (! newReg->rects)
+ newReg->rects = prev_rects;
+ }
+ else
+ {
+ /*
+ * No point in doing the extra work involved in an Xrealloc if
+ * the region is empty
+ */
+ newReg->size = 1;
+ HeapFree( SystemHeap, 0, newReg->rects );
+ newReg->rects = HeapAlloc( SystemHeap, 0, sizeof(RECT32) );
+ }
+ }
+ HeapFree( SystemHeap, 0, oldRects );
+ return;
+}
+
+/***********************************************************************
+ * Region Intersection
+ ***********************************************************************/
+
+
+/***********************************************************************
+ * REGION_IntersectO
+ *
+ * Handle an overlapping band for REGION_Intersect.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Rectangles may be added to the region.
+ *
+ */
+static void REGION_IntersectO(WINEREGION *pReg, RECT32 *r1, RECT32 *r1End,
+ RECT32 *r2, RECT32 *r2End, INT32 top, INT32 bottom)
+
+{
+ INT32 left, right;
+ RECT32 *pNextRect;
+
+ pNextRect = &pReg->rects[pReg->numRects];
+
+ while ((r1 != r1End) && (r2 != r2End))
+ {
+ left = MAX(r1->left, r2->left);
+ right = MIN(r1->right, r2->right);
+
+ /*
+ * If there's any overlap between the two rectangles, add that
+ * overlap to the new region.
+ * There's no need to check for subsumption because the only way
+ * such a need could arise is if some region has two rectangles
+ * right next to each other. Since that should never happen...
+ */
+ if (left < right)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = left;
+ pNextRect->top = top;
+ pNextRect->right = right;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ }
+
+ /*
+ * Need to advance the pointers. Shift the one that extends
+ * to the right the least, since the other still has a chance to
+ * overlap with that region's next rectangle, if you see what I mean.
+ */
+ if (r1->right < r2->right)
+ {
+ r1++;
+ }
+ else if (r2->right < r1->right)
+ {
+ r2++;
+ }
+ else
+ {
+ r1++;
+ r2++;
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+ * REGION_IntersectRegion
+ */
+static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
+ WINEREGION *reg2)
+{
+ /* check for trivial reject */
+ if ( (!(reg1->numRects)) || (!(reg2->numRects)) ||
+ (!EXTENTCHECK(®1->extents, ®2->extents)))
+ newReg->numRects = 0;
+ else
+ REGION_RegionOp (newReg, reg1, reg2,
+ (voidProcp) REGION_IntersectO, (voidProcp) NULL, (voidProcp) NULL);
+
+ /*
+ * Can't alter newReg's extents before we call miRegionOp because
+ * it might be one of the source regions and miRegionOp depends
+ * on the extents of those regions being the same. Besides, this
+ * way there's no checking against rectangles that will be nuked
+ * due to coalescing, so we have to examine fewer rectangles.
+ */
+ REGION_SetExtents(newReg);
+ newReg->type = (newReg->numRects) ? COMPLEXREGION : NULLREGION ;
+ return;
+}
+
+/***********************************************************************
+ * Region Union
+ ***********************************************************************/
+
+/***********************************************************************
+ * REGION_UnionNonO
+ *
+ * Handle a non-overlapping band for the union operation. Just
+ * Adds the rectangles into the region. Doesn't have to check for
+ * subsumption or anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * pReg->numRects is incremented and the final rectangles overwritten
+ * with the rectangles we're passed.
+ *
+ */
+static void REGION_UnionNonO (WINEREGION *pReg, RECT32 *r, RECT32 *rEnd,
+ INT32 top, INT32 bottom)
+{
+ RECT32 *pNextRect;
+
+ pNextRect = &pReg->rects[pReg->numRects];
+
+ while (r != rEnd)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = r->left;
+ pNextRect->top = top;
+ pNextRect->right = r->right;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ r++;
+ }
+ return;
+}
+
+/***********************************************************************
+ * REGION_UnionO
+ *
+ * Handle an overlapping band for the union operation. Picks the
+ * left-most rectangle each time and merges it into the region.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Rectangles are overwritten in pReg->rects and pReg->numRects will
+ * be changed.
+ *
+ */
+static void REGION_UnionO (WINEREGION *pReg, RECT32 *r1, RECT32 *r1End,
+ RECT32 *r2, RECT32 *r2End, INT32 top, INT32 bottom)
+{
+ RECT32 *pNextRect;
+
+ pNextRect = &pReg->rects[pReg->numRects];
+
+#define MERGERECT(r) \
+ if ((pReg->numRects != 0) && \
+ (pNextRect[-1].top == top) && \
+ (pNextRect[-1].bottom == bottom) && \
+ (pNextRect[-1].right >= r->left)) \
+ { \
+ if (pNextRect[-1].right < r->right) \
+ { \
+ pNextRect[-1].right = r->right; \
+ } \
+ } \
+ else \
+ { \
+ MEMCHECK(pReg, pNextRect, pReg->rects); \
+ pNextRect->top = top; \
+ pNextRect->bottom = bottom; \
+ pNextRect->left = r->left; \
+ pNextRect->right = r->right; \
+ pReg->numRects += 1; \
+ pNextRect += 1; \
+ } \
+ r++;
+
+ while ((r1 != r1End) && (r2 != r2End))
+ {
+ if (r1->left < r2->left)
+ {
+ MERGERECT(r1);
+ }
+ else
+ {
+ MERGERECT(r2);
+ }
+ }
+
+ if (r1 != r1End)
+ {
+ do
+ {
+ MERGERECT(r1);
+ } while (r1 != r1End);
+ }
+ else while (r2 != r2End)
+ {
+ MERGERECT(r2);
+ }
+ return;
+}
+
+/***********************************************************************
+ * REGION_UnionRegion
+ */
+static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
+ WINEREGION *reg2)
+{
+ /* checks all the simple cases */
+
+ /*
+ * Region 1 and 2 are the same or region 1 is empty
+ */
+ if ( (reg1 == reg2) || (!(reg1->numRects)) )
+ {
+ if (newReg != reg2)
+ REGION_CopyRegion(newReg, reg2);
+ return;
+ }
+
+ /*
+ * if nothing to union (region 2 empty)
+ */
+ if (!(reg2->numRects))
+ {
+ if (newReg != reg1)
+ REGION_CopyRegion(newReg, reg1);
+ return;
+ }
+
+ /*
+ * Region 1 completely subsumes region 2
+ */
+ if ((reg1->numRects == 1) &&
+ (reg1->extents.left <= reg2->extents.left) &&
+ (reg1->extents.top <= reg2->extents.top) &&
+ (reg1->extents.right >= reg2->extents.right) &&
+ (reg1->extents.bottom >= reg2->extents.bottom))
+ {
+ if (newReg != reg1)
+ REGION_CopyRegion(newReg, reg1);
+ return;
+ }
+
+ /*
+ * Region 2 completely subsumes region 1
+ */
+ if ((reg2->numRects == 1) &&
+ (reg2->extents.left <= reg1->extents.left) &&
+ (reg2->extents.top <= reg1->extents.top) &&
+ (reg2->extents.right >= reg1->extents.right) &&
+ (reg2->extents.bottom >= reg1->extents.bottom))
+ {
+ if (newReg != reg2)
+ REGION_CopyRegion(newReg, reg2);
+ return;
+ }
+
+ REGION_RegionOp (newReg, reg1, reg2, (voidProcp) REGION_UnionO,
+ (voidProcp) REGION_UnionNonO, (voidProcp) REGION_UnionNonO);
+
+ newReg->extents.left = MIN(reg1->extents.left, reg2->extents.left);
+ newReg->extents.top = MIN(reg1->extents.top, reg2->extents.top);
+ newReg->extents.right = MAX(reg1->extents.right, reg2->extents.right);
+ newReg->extents.bottom = MAX(reg1->extents.bottom, reg2->extents.bottom);
+ newReg->type = (newReg->numRects) ? COMPLEXREGION : NULLREGION ;
+ return;
+}
+
+/***********************************************************************
+ * Region Subtraction
+ ***********************************************************************/
+
+/***********************************************************************
+ * REGION_SubtractNonO1
+ *
+ * Deal with non-overlapping band for subtraction. Any parts from
+ * region 2 we discard. Anything from region 1 we add to the region.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * pReg may be affected.
+ *
+ */
+static void REGION_SubtractNonO1 (WINEREGION *pReg, RECT32 *r, RECT32 *rEnd,
+ INT32 top, INT32 bottom)
+{
+ RECT32 *pNextRect;
+
+ pNextRect = &pReg->rects[pReg->numRects];
+
+ while (r != rEnd)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = r->left;
+ pNextRect->top = top;
+ pNextRect->right = r->right;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ r++;
+ }
+ return;
+}
+
+
+/***********************************************************************
+ * REGION_SubtractO
+ *
+ * Overlapping band subtraction. x1 is the left-most point not yet
+ * checked.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * pReg may have rectangles added to it.
+ *
+ */
+static void REGION_SubtractO (WINEREGION *pReg, RECT32 *r1, RECT32 *r1End,
+ RECT32 *r2, RECT32 *r2End, INT32 top, INT32 bottom)
+{
+ RECT32 *pNextRect;
+ INT32 left;
+
+ left = r1->left;
+ pNextRect = &pReg->rects[pReg->numRects];
+
+ while ((r1 != r1End) && (r2 != r2End))
+ {
+ if (r2->right <= left)
+ {
+ /*
+ * Subtrahend missed the boat: go to next subtrahend.
+ */
+ r2++;
+ }
+ else if (r2->left <= left)
+ {
+ /*
+ * Subtrahend preceeds minuend: nuke left edge of minuend.
+ */
+ left = r2->right;
+ if (left >= r1->right)
+ {
+ /*
+ * Minuend completely covered: advance to next minuend and
+ * reset left fence to edge of new minuend.
+ */
+ r1++;
+ if (r1 != r1End)
+ left = r1->left;
+ }
+ else
+ {
+ /*
+ * Subtrahend now used up since it doesn't extend beyond
+ * minuend
+ */
+ r2++;
+ }
+ }
+ else if (r2->left < r1->right)
+ {
+ /*
+ * Left part of subtrahend covers part of minuend: add uncovered
+ * part of minuend to region and skip to next subtrahend.
+ */
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = left;
+ pNextRect->top = top;
+ pNextRect->right = r2->left;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ left = r2->right;
+ if (left >= r1->right)
+ {
+ /*
+ * Minuend used up: advance to new...
+ */
+ r1++;
+ if (r1 != r1End)
+ left = r1->left;
+ }
+ else
+ {
+ /*
+ * Subtrahend used up
+ */
+ r2++;
+ }
+ }
+ else
+ {
+ /*
+ * Minuend used up: add any remaining piece before advancing.
+ */
+ if (r1->right > left)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = left;
+ pNextRect->top = top;
+ pNextRect->right = r1->right;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ }
+ r1++;
+ left = r1->left;
+ }
+ }
+
+ /*
+ * Add remaining minuend rectangles to region.
+ */
+ while (r1 != r1End)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->left = left;
+ pNextRect->top = top;
+ pNextRect->right = r1->right;
+ pNextRect->bottom = bottom;
+ pReg->numRects += 1;
+ pNextRect++;
+ r1++;
+ if (r1 != r1End)
+ {
+ left = r1->left;
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+ * REGION_SubtractRegion
+ *
+ * Subtract regS from regM and leave the result in regD.
+ * S stands for subtrahend, M for minuend and D for difference.
+ *
+ * Results:
+ * TRUE.
+ *
+ * Side Effects:
+ * regD is overwritten.
+ *
+ */
+static void REGION_SubtractRegion(WINEREGION *regD, WINEREGION *regM,
+ WINEREGION *regS )
+{
+ /* check for trivial reject */
+ if ( (!(regM->numRects)) || (!(regS->numRects)) ||
+ (!EXTENTCHECK(®M->extents, ®S->extents)) )
+ {
+ REGION_CopyRegion(regD, regM);
+ return;
+ }
+
+ REGION_RegionOp (regD, regM, regS, (voidProcp) REGION_SubtractO,
+ (voidProcp) REGION_SubtractNonO1, (voidProcp) NULL);
+
+ /*
+ * Can't alter newReg's extents before we call miRegionOp because
+ * it might be one of the source regions and miRegionOp depends
+ * on the extents of those regions being the unaltered. Besides, this
+ * way there's no checking against rectangles that will be nuked
+ * due to coalescing, so we have to examine fewer rectangles.
+ */
+ REGION_SetExtents (regD);
+ regD->type = (regD->numRects) ? COMPLEXREGION : NULLREGION ;
+ return;
+}
+
+/***********************************************************************
+ * REGION_XorRegion
+ */
+static void REGION_XorRegion(WINEREGION *dr, WINEREGION *sra,
+ WINEREGION *srb)
+{
+ WINEREGION *tra, *trb;
+
+ if ((! (tra = REGION_AllocWineRegion())) ||
+ (! (trb = REGION_AllocWineRegion())))
+ return;
+ REGION_SubtractRegion(tra,sra,srb);
+ REGION_SubtractRegion(trb,srb,sra);
+ REGION_UnionRegion(dr,tra,trb);
+ REGION_DestroyWineRegion(tra);
+ REGION_DestroyWineRegion(trb);
+ return;
+}
+
+/**************************************************************************
+ *
+ * Poly Regions
+ *
+ *************************************************************************/
+
+#define LARGE_COORDINATE 0x7fffffff /* FIXME */
+#define SMALL_COORDINATE 0x80000000
+
+/***********************************************************************
+ * REGION_InsertEdgeInET
+ *
+ * Insert the given edge into the edge table.
+ * First we must find the correct bucket in the
+ * Edge table, then find the right slot in the
+ * bucket. Finally, we can insert it.
+ *
+ */
+static void REGION_InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE,
+ INT32 scanline, ScanLineListBlock **SLLBlock, INT32 *iSLLBlock)
+
+{
+ EdgeTableEntry *start, *prev;
+ ScanLineList *pSLL, *pPrevSLL;
+ ScanLineListBlock *tmpSLLBlock;
+
+ /*
+ * find the right bucket to put the edge into
+ */
+ pPrevSLL = &ET->scanlines;
+ pSLL = pPrevSLL->next;
+ while (pSLL && (pSLL->scanline < scanline))
+ {
+ pPrevSLL = pSLL;
+ pSLL = pSLL->next;
+ }
+
+ /*
+ * reassign pSLL (pointer to ScanLineList) if necessary
+ */
+ if ((!pSLL) || (pSLL->scanline > scanline))
+ {
+ if (*iSLLBlock > SLLSPERBLOCK-1)
+ {
+ tmpSLLBlock = HeapAlloc( SystemHeap, 0, sizeof(ScanLineListBlock));
+ if(!tmpSLLBlock)
+ {
+ fprintf(stderr, "REGION_InsertEdgeInET(): Can't alloc SLLB\n");
+ return;
+ }
+ (*SLLBlock)->next = tmpSLLBlock;
+ tmpSLLBlock->next = (ScanLineListBlock *)NULL;
+ *SLLBlock = tmpSLLBlock;
+ *iSLLBlock = 0;
+ }
+ pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
+
+ pSLL->next = pPrevSLL->next;
+ pSLL->edgelist = (EdgeTableEntry *)NULL;
+ pPrevSLL->next = pSLL;
+ }
+ pSLL->scanline = scanline;
+
+ /*
+ * now insert the edge in the right bucket
+ */
+ prev = (EdgeTableEntry *)NULL;
+ start = pSLL->edgelist;
+ while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
+ {
+ prev = start;
+ start = start->next;
+ }
+ ETE->next = start;
+
+ if (prev)
+ prev->next = ETE;
+ else
+ pSLL->edgelist = ETE;
+}
+
+/***********************************************************************
+ * REGION_CreateEdgeTable
+ *
+ * This routine creates the edge table for
+ * scan converting polygons.
+ * The Edge Table (ET) looks like:
+ *
+ * EdgeTable
+ * --------
+ * | ymax | ScanLineLists
+ * |scanline|-->------------>-------------->...
+ * -------- |scanline| |scanline|
+ * |edgelist| |edgelist|
+ * --------- ---------
+ * | |
+ * | |
+ * V V
+ * list of ETEs list of ETEs
+ *
+ * where ETE is an EdgeTableEntry data structure,
+ * and there is one ScanLineList per scanline at
+ * which an edge is initially entered.
+ *
+ */
+static void REGION_CreateETandAET(const INT32 *Count, INT32 nbpolygons,
+ const POINT32 *pts, EdgeTable *ET, EdgeTableEntry *AET,
+ EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
+{
+ const POINT32 *top, *bottom;
+ const POINT32 *PrevPt, *CurrPt, *EndPt;
+ INT32 poly, count;
+ int iSLLBlock = 0;
+ int dy;
+
+
+ /*
+ * initialize the Active Edge Table
+ */
+ AET->next = (EdgeTableEntry *)NULL;
+ AET->back = (EdgeTableEntry *)NULL;
+ AET->nextWETE = (EdgeTableEntry *)NULL;
+ AET->bres.minor_axis = SMALL_COORDINATE;
+
+ /*
+ * initialize the Edge Table.
+ */
+ ET->scanlines.next = (ScanLineList *)NULL;
+ ET->ymax = SMALL_COORDINATE;
+ ET->ymin = LARGE_COORDINATE;
+ pSLLBlock->next = (ScanLineListBlock *)NULL;
+
+ EndPt = pts - 1;
+ for(poly = 0; poly < nbpolygons; poly++)
+ {
+ count = Count[poly];
+ EndPt += count;
+ if(count < 2)
+ continue;
+
+ PrevPt = EndPt;
+
+ /*
+ * for each vertex in the array of points.
+ * In this loop we are dealing with two vertices at
+ * a time -- these make up one edge of the polygon.
+ */
+ while (count--)
+ {
+ CurrPt = pts++;
+
+ /*
+ * find out which point is above and which is below.
+ */
+ if (PrevPt->y > CurrPt->y)
+ {
+ bottom = PrevPt, top = CurrPt;
+ pETEs->ClockWise = 0;
+ }
+ else
+ {
+ bottom = CurrPt, top = PrevPt;
+ pETEs->ClockWise = 1;
+ }
+
+ /*
+ * don't add horizontal edges to the Edge table.
+ */
+ if (bottom->y != top->y)
+ {
+ pETEs->ymax = bottom->y-1;
+ /* -1 so we don't get last scanline */
+
+ /*
+ * initialize integer edge algorithm
+ */
+ dy = bottom->y - top->y;
+ BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
+
+ REGION_InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock,
+ &iSLLBlock);
+
+ if (PrevPt->y > ET->ymax)
+ ET->ymax = PrevPt->y;
+ if (PrevPt->y < ET->ymin)
+ ET->ymin = PrevPt->y;
+ pETEs++;
+ }
+
+ PrevPt = CurrPt;
+ }
+ }
+}
+
+/***********************************************************************
+ * REGION_loadAET
+ *
+ * This routine moves EdgeTableEntries from the
+ * EdgeTable into the Active Edge Table,
+ * leaving them sorted by smaller x coordinate.
+ *
+ */
+static void REGION_loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
+{
+ EdgeTableEntry *pPrevAET;
+ EdgeTableEntry *tmp;
+
+ pPrevAET = AET;
+ AET = AET->next;
+ while (ETEs)
+ {
+ while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
+ {
+ pPrevAET = AET;
+ AET = AET->next;
+ }
+ tmp = ETEs->next;
+ ETEs->next = AET;
+ if (AET)
+ AET->back = ETEs;
+ ETEs->back = pPrevAET;
+ pPrevAET->next = ETEs;
+ pPrevAET = ETEs;
+
+ ETEs = tmp;
+ }
+}
+
+/***********************************************************************
+ * REGION_computeWAET
+ *
+ * This routine links the AET by the
+ * nextWETE (winding EdgeTableEntry) link for
+ * use by the winding number rule. The final
+ * Active Edge Table (AET) might look something
+ * like:
+ *
+ * AET
+ * ---------- --------- ---------
+ * |ymax | |ymax | |ymax |
+ * | ... | |... | |... |
+ * |next |->|next |->|next |->...
+ * |nextWETE| |nextWETE| |nextWETE|
+ * --------- --------- ^--------
+ * | | |
+ * V-------------------> V---> ...
+ *
+ */
+static void REGION_computeWAET(EdgeTableEntry *AET)
+{
+ register EdgeTableEntry *pWETE;
+ register int inside = 1;
+ register int isInside = 0;
+
+ AET->nextWETE = (EdgeTableEntry *)NULL;
+ pWETE = AET;
+ AET = AET->next;
+ while (AET)
+ {
+ if (AET->ClockWise)
+ isInside++;
+ else
+ isInside--;
+
+ if ((!inside && !isInside) ||
+ ( inside && isInside))
+ {
+ pWETE->nextWETE = AET;
+ pWETE = AET;
+ inside = !inside;
+ }
+ AET = AET->next;
+ }
+ pWETE->nextWETE = (EdgeTableEntry *)NULL;
+}
+
+/***********************************************************************
+ * REGION_InsertionSort
+ *
+ * Just a simple insertion sort using
+ * pointers and back pointers to sort the Active
+ * Edge Table.
+ *
+ */
+static BOOL32 REGION_InsertionSort(EdgeTableEntry *AET)
+{
+ EdgeTableEntry *pETEchase;
+ EdgeTableEntry *pETEinsert;
+ EdgeTableEntry *pETEchaseBackTMP;
+ BOOL32 changed = FALSE;
+
+ AET = AET->next;
+ while (AET)
+ {
+ pETEinsert = AET;
+ pETEchase = AET;
+ while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
+ pETEchase = pETEchase->back;
+
+ AET = AET->next;
+ if (pETEchase != pETEinsert)
+ {
+ pETEchaseBackTMP = pETEchase->back;
+ pETEinsert->back->next = AET;
+ if (AET)
+ AET->back = pETEinsert->back;
+ pETEinsert->next = pETEchase;
+ pETEchase->back->next = pETEinsert;
+ pETEchase->back = pETEinsert;
+ pETEinsert->back = pETEchaseBackTMP;
+ changed = TRUE;
+ }
+ }
+ return changed;
+}
+
+/***********************************************************************
+ * REGION_FreeStorage
+ *
+ * Clean up our act.
+ */
+static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock)
+{
+ ScanLineListBlock *tmpSLLBlock;
+
+ while (pSLLBlock)
+ {
+ tmpSLLBlock = pSLLBlock->next;
+ HeapFree( SystemHeap, 0, pSLLBlock );
+ pSLLBlock = tmpSLLBlock;
+ }
+}
+
+
+/***********************************************************************
+ * REGION_PtsToRegion
+ *
+ * Create an array of rectangles from a list of points.
+ */
+static int REGION_PtsToRegion(int numFullPtBlocks, int iCurPtBlock,
+ POINTBLOCK *FirstPtBlock, WINEREGION *reg)
+{
+ RECT32 *rects;
+ POINT32 *pts;
+ POINTBLOCK *CurPtBlock;
+ int i;
+ RECT32 *extents;
+ INT32 numRects;
+
+ extents = ®->extents;
+
+ numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
+
+ if (!(reg->rects = HeapReAlloc( SystemHeap, 0, reg->rects,
+ sizeof(RECT32) * numRects )))
+ return(0);
+
+ reg->size = numRects;
+ CurPtBlock = FirstPtBlock;
+ rects = reg->rects - 1;
+ numRects = 0;
+ extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE;
+
+ for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
+ /* the loop uses 2 points per iteration */
+ i = NUMPTSTOBUFFER >> 1;
+ if (!numFullPtBlocks)
+ i = iCurPtBlock >> 1;
+ for (pts = CurPtBlock->pts; i--; pts += 2) {
+ if (pts->x == pts[1].x)
+ continue;
+ if (numRects && pts->x == rects->left && pts->y == rects->bottom &&
+ pts[1].x == rects->right &&
+ (numRects == 1 || rects[-1].top != rects->top) &&
+ (i && pts[2].y > pts[1].y)) {
+ rects->bottom = pts[1].y + 1;
+ continue;
+ }
+ numRects++;
+ rects++;
+ rects->left = pts->x; rects->top = pts->y;
+ rects->right = pts[1].x; rects->bottom = pts[1].y + 1;
+ if (rects->left < extents->left)
+ extents->left = rects->left;
+ if (rects->right > extents->right)
+ extents->right = rects->right;
+ }
+ CurPtBlock = CurPtBlock->next;
+ }
+
+ if (numRects) {
+ extents->top = reg->rects->top;
+ extents->bottom = rects->bottom;
+ } else {
+ extents->left = 0;
+ extents->top = 0;
+ extents->right = 0;
+ extents->bottom = 0;
+ }
+ reg->numRects = numRects;
+
+ return(TRUE);
+}
+
+/***********************************************************************
+ * CreatePolyPolygonRgn32 (GDI32.57)
+ */
+HRGN32 WINAPI CreatePolyPolygonRgn32(const POINT32 *Pts, const INT32 *Count,
+ INT32 nbpolygons, INT32 mode)
+{
+ HRGN32 hrgn;
+ RGNOBJ *obj;
+ WINEREGION *region;
+ register EdgeTableEntry *pAET; /* Active Edge Table */
+ register INT32 y; /* current scanline */
+ register int iPts = 0; /* number of pts in buffer */
+ register EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
+ register ScanLineList *pSLL; /* current scanLineList */
+ register POINT32 *pts; /* output buffer */
+ EdgeTableEntry *pPrevAET; /* ptr to previous AET */
+ EdgeTable ET; /* header node for ET */
+ EdgeTableEntry AET; /* header node for AET */
+ EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
+ ScanLineListBlock SLLBlock; /* header for scanlinelist */
+ int fixWAET = FALSE;
+ POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */
+ POINTBLOCK *tmpPtBlock;
+ int numFullPtBlocks = 0;
+ INT32 poly, total;
+
+ if(!(hrgn = REGION_CreateRegion()))
+ return 0;
+ obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
+ region = obj->rgn;
+
+ /* special case a rectangle */
+
+ if (((nbpolygons == 1) && ((*Count == 4) ||
+ ((*Count == 5) && (Pts[4].x == Pts[0].x) && (Pts[4].y == Pts[0].y)))) &&
+ (((Pts[0].y == Pts[1].y) &&
+ (Pts[1].x == Pts[2].x) &&
+ (Pts[2].y == Pts[3].y) &&
+ (Pts[3].x == Pts[0].x)) ||
+ ((Pts[0].x == Pts[1].x) &&
+ (Pts[1].y == Pts[2].y) &&
+ (Pts[2].x == Pts[3].x) &&
+ (Pts[3].y == Pts[0].y))))
+ {
+ SetRectRgn32( hrgn, MIN(Pts[0].x, Pts[2].x), MIN(Pts[0].y, Pts[2].y),
+ MAX(Pts[0].x, Pts[2].x), MAX(Pts[0].y, Pts[2].y) );
+ GDI_HEAP_UNLOCK( hrgn );
+ return hrgn;
+ }
+
+ for(poly = total = 0; poly < nbpolygons; poly++)
+ total += Count[poly];
+ if (! (pETEs = HeapAlloc( SystemHeap, 0, sizeof(EdgeTableEntry) * total )))
+ {
+ REGION_DeleteObject( hrgn, obj );
return 0;
+ }
+ pts = FirstPtBlock.pts;
+ REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
+ pSLL = ET.scanlines.next;
+ curPtBlock = &FirstPtBlock;
+
+ if (mode != WINDING) {
+ /*
+ * for each scanline
+ */
+ for (y = ET.ymin; y < ET.ymax; y++) {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL != NULL && y == pSLL->scanline) {
+ REGION_loadAET(&AET, pSLL->edgelist);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+
+ /*
+ * for each active edge
+ */
+ while (pAET) {
+ pts->x = pAET->bres.minor_axis, pts->y = y;
+ pts++, iPts++;
+
+ /*
+ * send out the buffer
+ */
+ if (iPts == NUMPTSTOBUFFER) {
+ tmpPtBlock = HeapAlloc( SystemHeap, 0, sizeof(POINTBLOCK));
+ if(!tmpPtBlock) {
+ fprintf(stderr,
+ "CreatePolyPolygonRgn(): can't alloc tPB\n");
+ return 0;
+ }
+ curPtBlock->next = tmpPtBlock;
+ curPtBlock = tmpPtBlock;
+ pts = curPtBlock->pts;
+ numFullPtBlocks++;
+ iPts = 0;
+ }
+ EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
+ }
+ REGION_InsertionSort(&AET);
+ }
+ }
+ else {
+ /*
+ * for each scanline
+ */
+ for (y = ET.ymin; y < ET.ymax; y++) {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL != NULL && y == pSLL->scanline) {
+ REGION_loadAET(&AET, pSLL->edgelist);
+ REGION_computeWAET(&AET);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+ pWETE = pAET;
+
+ /*
+ * for each active edge
+ */
+ while (pAET) {
+ /*
+ * add to the buffer only those edges that
+ * are in the Winding active edge table.
+ */
+ if (pWETE == pAET) {
+ pts->x = pAET->bres.minor_axis, pts->y = y;
+ pts++, iPts++;
+
+ /*
+ * send out the buffer
+ */
+ if (iPts == NUMPTSTOBUFFER) {
+ tmpPtBlock = HeapAlloc( SystemHeap, 0,
+ sizeof(POINTBLOCK) );
+ if(!tmpPtBlock) {
+ fprintf(stderr,
+ "CreatePolyPolygonRgn(): can't alloc tPB\n");
+ return 0;
+ }
+ curPtBlock->next = tmpPtBlock;
+ curPtBlock = tmpPtBlock;
+ pts = curPtBlock->pts;
+ numFullPtBlocks++; iPts = 0;
+ }
+ pWETE = pWETE->nextWETE;
+ }
+ EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
+ }
+
+ /*
+ * recompute the winding active edge table if
+ * we just resorted or have exited an edge.
+ */
+ if (REGION_InsertionSort(&AET) || fixWAET) {
+ REGION_computeWAET(&AET);
+ fixWAET = FALSE;
+ }
+ }
+ }
+ REGION_FreeStorage(SLLBlock.next);
+ REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
+ for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
+ tmpPtBlock = curPtBlock->next;
+ HeapFree( SystemHeap, 0, curPtBlock );
+ curPtBlock = tmpPtBlock;
+ }
+ HeapFree( SystemHeap, 0, pETEs );
+ GDI_HEAP_UNLOCK( hrgn );
+ return hrgn;
+}
+
+
+/***********************************************************************
+ * CreatePolygonRgn16 (GDI.63)
+ */
+HRGN16 WINAPI CreatePolygonRgn16( const POINT16 * points, INT16 count,
+ INT16 mode )
+{
+ return CreatePolyPolygonRgn16( points, &count, 1, mode );
+}
+
+/***********************************************************************
+ * CreatePolyPolygonRgn16 (GDI.451)
+ */
+HRGN16 WINAPI CreatePolyPolygonRgn16( const POINT16 *points,
+ const INT16 *count, INT16 nbpolygons, INT16 mode )
+{
+ HRGN32 hrgn;
+ int i, npts = 0;
+ INT32 *count32;
+ POINT32 *points32;
+
+ for (i = 0; i < nbpolygons; i++)
+ npts += count[i];
+ points32 = HeapAlloc( SystemHeap, 0, npts * sizeof(POINT32) );
+ for (i = 0; i < npts; i++)
+ CONV_POINT16TO32( &(points[i]), &(points32[i]) );
+
+ count32 = HeapAlloc( SystemHeap, 0, nbpolygons * sizeof(INT32) );
+ for (i = 0; i < nbpolygons; i++)
+ count32[i] = count[i];
+ hrgn = CreatePolyPolygonRgn32( points32, count32, nbpolygons, mode );
+ HeapFree( SystemHeap, 0, count32 );
+ HeapFree( SystemHeap, 0, points32 );
+ return hrgn;
+}
+
+/***********************************************************************
+ * CreatePolygonRgn32 (GDI32.58)
+ */
+HRGN32 WINAPI CreatePolygonRgn32( const POINT32 *points, INT32 count,
+ INT32 mode )
+{
+ return CreatePolyPolygonRgn32( points, &count, 1, mode );
}
diff --git a/programs/notepad/En.rc b/programs/notepad/En.rc
index e4ebc9e..01b24ae 100644
--- a/programs/notepad/En.rc
+++ b/programs/notepad/En.rc
@@ -2,7 +2,7 @@
* Notepad (English resources)
*
* Copyright 1997 Marcel Baur <mbaur@g26.ethz.ch>
- * FIXME: See TODO about how to fix weak translations.
+ * Proofread 1998 by David Lee Lambert <lamber45@egr.msu.edu>
*/
#define LANGUAGE_ID En
@@ -13,9 +13,9 @@
#define MENU_FILE "&File"
#define MENU_FILE_NEW "&New..."
-#define MENU_FILE_OPEN "O&pen"
+#define MENU_FILE_OPEN "&Open"
#define MENU_FILE_SAVE "&Save"
-#define MENU_FILE_SAVEAS "&Save as..."
+#define MENU_FILE_SAVEAS "Save &as..."
#define MENU_FILE_PRINT "&Print"
#define MENU_FILE_PAGESETUP "Page Se&tup..."
#define MENU_FILE_PRINTSETUP "P&rinter Setup..."
@@ -23,7 +23,7 @@
#define MENU_EDIT "&Edit"
#define MENU_EDIT_UNDO "&Undo\tCtrl+Z"
-#define MENU_EDIT_CUT "Cu&t\Ctrl+X"
+#define MENU_EDIT_CUT "Cu&t\tCtrl+X"
#define MENU_EDIT_COPY "&Copy\tCtrl+C"
#define MENU_EDIT_PASTE "&Paste\tCtrl+V"
#define MENU_EDIT_DELETE "&Delete\tDel"
@@ -57,7 +57,7 @@
#define DIALOG_PAGESETUP_CAPTION "Page Setup"
#define DIALOG_PAGESETUP_HEAD "&Header:"
#define DIALOG_PAGESETUP_TAIL "&Footer:"
-#define DIALOG_PAGESETUP_BORDER "Borders:"
+#define DIALOG_PAGESETUP_BORDER "&Margins:"
#define DIALOG_PAGESETUP_LEFT "&Left:"
#define DIALOG_PAGESETUP_RIGHT "&Right:"
#define DIALOG_PAGESETUP_TOP "&Top:"
@@ -75,7 +75,7 @@
#define STRING_ALLFILES "All files (*.*)"
#define STRING_TEXTFILES "Text files (*.txt)"
-#define STRING_TOOLARGE "File '%s' ist too large for notepad.\n \
+#define STRING_TOOLARGE "File '%s' is too large for notepad.\n \
Please use a different editor."
#define STRING_NOTEXT "You didn't enter any text. \
@@ -89,3 +89,7 @@
#include "notepad.rc"
+
+
+
+
diff --git a/programs/notepad/notepad.rc b/programs/notepad/notepad.rc
index c3d4748..5a438de 100644
--- a/programs/notepad/notepad.rc
+++ b/programs/notepad/notepad.rc
@@ -51,10 +51,12 @@
MENUITEM MENU_HELP_HELP_ON_HELP, NP_HELP_ON_HELP
MENUITEM SEPARATOR
- POPUP MENU_INFO {
- MENUITEM MENU_INFO_LICENSE, NP_HELP_LICENSE
- MENUITEM MENU_INFO_NO_WARRANTY, NP_HELP_NO_WARRANTY
- MENUITEM MENU_INFO_ABOUT_WINE, NP_HELP_ABOUT_WINE
+ POPUP MENU_INFO {
+ MENUITEM MENU_INFO_LICENSE, NP_HELP_LICENSE
+ MENUITEM MENU_INFO_NO_WARRANTY, NP_HELP_NO_WARRANTY
+ MENUITEM MENU_INFO_ABOUT_WINE, NP_HELP_ABOUT_WINE
+ }
}
+
}
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 764acad..01f9a7d 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -120,6 +120,7 @@
DEBUG_ENTRY_POINT *debug;
REG_ENTRY_POINT *regs;
PE_MODREF *pem;
+ PDB32 *pdb = PROCESS_Current();
INT32 i, size;
BYTE *addr;
@@ -278,8 +279,8 @@
sizeof(*pem) );
pem->module = (HMODULE32)addr;
pem->pe_export = exp;
- pem->next = pCurrentProcess->modref_list;
- pCurrentProcess->modref_list = pem;
+ pem->next = pdb->modref_list;
+ pdb->modref_list = pem;
/* Create a Win16 dummy module */
diff --git a/relay32/gdi32.spec b/relay32/gdi32.spec
index fad209f..b6c5bea 100644
--- a/relay32/gdi32.spec
+++ b/relay32/gdi32.spec
@@ -98,7 +98,7 @@
91 stdcall Escape(long long long ptr ptr) Escape32
92 stdcall ExcludeClipRect(long long long long long) ExcludeClipRect32
93 stdcall ExtCreatePen(long long ptr long ptr) ExtCreatePen32
- 94 stub ExtCreateRegion
+ 94 stdcall ExtCreateRegion(ptr long ptr) ExtCreateRegion
95 stdcall ExtEscape(long long long ptr long ptr) ExtEscape32
96 stdcall ExtFloodFill(long long long long long) ExtFloodFill32
97 stub ExtSelectClipRgn
diff --git a/relay32/relay386.c b/relay32/relay386.c
index 752a582..1b5f706 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -14,6 +14,22 @@
#include "stddebug.h"
#include "debug.h"
+static void _dumpstr(unsigned char *s) {
+ fputs("\"",stdout);
+ while (*s) {
+ if (*s<' ') {
+ printf("\\0x%02x",*s++);
+ continue;
+ }
+ if (*s=='\\') {
+ fputs("\\\\",stdout);
+ s++;
+ continue;
+ }
+ fputc(*s++,stdout);
+ }
+ fputs("\"",stdout);
+}
/***********************************************************************
* RELAY_CallFrom32
@@ -52,9 +68,14 @@
{
char buff[80];
lstrcpynWtoA( buff, (LPWSTR)args[i], sizeof(buff) );
- printf( "%08x L\"%s\"", args[i], buff );
+ buff[sizeof(buff)-1]='\0';
+ printf( "%08x L", args[i] );
+ _dumpstr((unsigned char*)buff);
}
- else printf( "%08x \"%s\"", args[i], (char *)args[i] );
+ else {
+ printf( "%08x ", args[i] );
+ _dumpstr((unsigned char*)args[i]);
+ }
}
else printf( "%08x", args[i] );
}
diff --git a/relay32/user32.spec b/relay32/user32.spec
index 06ce2b1..5fdddb2 100644
--- a/relay32/user32.spec
+++ b/relay32/user32.spec
@@ -281,7 +281,7 @@
276 stdcall GetNextDlgTabItem(long long long) GetNextDlgTabItem32
277 stdcall GetOpenClipboardWindow() GetOpenClipboardWindow32
278 stdcall GetParent(long) GetParent32
-279 stub GetPriorityClipboardFormat
+279 stdcall GetPriorityClipboardFormat(ptr long) GetPriorityClipboardFormat32
280 stub GetProcessWindowStation
281 stdcall GetPropA(long ptr) GetProp32A
282 stdcall GetPropW(long ptr) GetProp32W
diff --git a/relay32/wow32.spec b/relay32/wow32.spec
index 4a37728..c60e58d 100644
--- a/relay32/wow32.spec
+++ b/relay32/wow32.spec
@@ -1,13 +1,13 @@
name wow32
type win32
- 1 stub WOW_1
- 2 stub WOWCallback16
+ 1 stdcall WOW_1(long long) WOW32_1
+ 2 stdcall WOWCallback16(long long) WOWCallback16
3 stub WOWCallback16Ex
4 stub WOWDirectedYield16
- 5 stub WOWGetVDMPointer
- 6 stub WOWGetVDMPointerFix
- 7 stub WOWGetVDMPointerUnfix
+ 5 stdcall WOWGetVDMPointer(long long long) WOWGetVDMPointer
+ 6 stdcall WOWGetVDMPointerFix(long long long) WOWGetVDMPointerFix
+ 7 stdcall WOWGetVDMPointerUnfix(long) WOWGetVDMPointerUnfix
8 stub WOWGlobalAlloc16
9 stub WOWGlobalAllocLock16
10 stub WOWGlobalFree16
diff --git a/scheduler/Makefile.in b/scheduler/Makefile.in
index 632f046..178d43a 100644
--- a/scheduler/Makefile.in
+++ b/scheduler/Makefile.in
@@ -13,6 +13,7 @@
process.c \
semaphore.c \
synchro.c \
+ sysdeps.c \
thread.c
all: $(MODULE).o
diff --git a/scheduler/critsection.c b/scheduler/critsection.c
index 7f5c5b9..dc91651 100644
--- a/scheduler/critsection.c
+++ b/scheduler/critsection.c
@@ -28,9 +28,17 @@
BOOL32 signaled;
} CRIT_SECTION;
+/* On some systems this is supposed to be defined in the program */
+#ifndef HAVE_UNION_SEMUN
+union semun {
+ int val;
+ struct semid_ds *buf;
+ ushort *array;
+};
+#endif
static BOOL32 CRIT_SECTION_Signaled( K32OBJ *obj, DWORD thread_id );
-static void CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id );
static void CRIT_SECTION_AddWait( K32OBJ *obj, DWORD thread_id );
static void CRIT_SECTION_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void CRIT_SECTION_Destroy( K32OBJ *obj );
@@ -237,12 +245,13 @@
*
* Wait on this object has been satisfied.
*/
-static void CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 CRIT_SECTION_Satisfied( K32OBJ *obj, DWORD thread_id )
{
CRIT_SECTION *crit = (CRIT_SECTION *)obj;
assert( obj->type == K32OBJ_CRITICAL_SECTION );
/* Only one thread is allowed to wake up */
crit->signaled = FALSE;
+ return FALSE; /* Not abandoned */
}
diff --git a/scheduler/event.c b/scheduler/event.c
index 4eb5e0c..0b578ba 100644
--- a/scheduler/event.c
+++ b/scheduler/event.c
@@ -21,7 +21,7 @@
} EVENT;
static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id );
-static void EVENT_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id );
static void EVENT_AddWait( K32OBJ *obj, DWORD thread_id );
static void EVENT_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void EVENT_Destroy( K32OBJ *obj );
@@ -219,12 +219,13 @@
*
* Wait on this object has been satisfied.
*/
-static void EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 EVENT_Satisfied( K32OBJ *obj, DWORD thread_id )
{
EVENT *event = (EVENT *)obj;
assert( obj->type == K32OBJ_EVENT );
/* Reset if it's an auto-reset event */
if (!event->manual_reset) event->signaled = FALSE;
+ return FALSE; /* Not abandoned */
}
diff --git a/scheduler/mutex.c b/scheduler/mutex.c
index 737789a..aebf9a6 100644
--- a/scheduler/mutex.c
+++ b/scheduler/mutex.c
@@ -12,16 +12,19 @@
#include "thread.h"
#include "heap.h"
-typedef struct
+typedef struct _MUTEX
{
- K32OBJ header;
- THREAD_QUEUE wait_queue;
- DWORD owner;
- DWORD count;
+ K32OBJ header;
+ THREAD_QUEUE wait_queue;
+ DWORD owner;
+ DWORD count;
+ BOOL32 abandoned;
+ struct _MUTEX *next;
+ struct _MUTEX *prev;
} MUTEX;
static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id );
-static void MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id );
static void MUTEX_AddWait( K32OBJ *obj, DWORD thread_id );
static void MUTEX_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void MUTEX_Destroy( K32OBJ *obj );
@@ -37,6 +40,40 @@
/***********************************************************************
+ * MUTEX_Release
+ *
+ * Release a mutex once the count is 0.
+ * Helper function for MUTEX_Abandon and ReleaseMutex.
+ */
+static void MUTEX_Release( MUTEX *mutex )
+{
+ /* Remove the mutex from the thread list of owned mutexes */
+ if (mutex->next) mutex->next->prev = mutex->prev;
+ if (mutex->prev) mutex->prev->next = mutex->next;
+ else THREAD_Current()->mutex_list = &mutex->next->header;
+ mutex->next = mutex->prev = NULL;
+ mutex->owner = 0;
+ SYNC_WakeUp( &mutex->wait_queue, INFINITE32 );
+}
+
+
+/***********************************************************************
+ * MUTEX_Abandon
+ *
+ * Abandon a mutex.
+ */
+void MUTEX_Abandon( K32OBJ *obj )
+{
+ MUTEX *mutex = (MUTEX *)obj;
+ assert( obj->type == K32OBJ_MUTEX );
+ assert( mutex->count && (mutex->owner == GetCurrentThreadId()) );
+ mutex->count = 0;
+ mutex->abandoned = TRUE;
+ MUTEX_Release( mutex );
+}
+
+
+/***********************************************************************
* CreateMutex32A (KERNEL32.166)
*/
HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner,
@@ -52,18 +89,27 @@
{
/* Finish initializing it */
mutex->wait_queue = NULL;
+ mutex->abandoned = FALSE;
+ mutex->prev = NULL;
if (owner)
{
+ K32OBJ **list;
mutex->owner = GetCurrentThreadId();
mutex->count = 1;
+ /* Add the mutex in the thread list of owned mutexes */
+ list = &THREAD_Current()->mutex_list;
+ if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
+ *list = &mutex->header;
}
else
{
mutex->owner = 0;
mutex->count = 0;
+ mutex->next = NULL;
}
K32OBJ_DecCount( &mutex->header );
}
+ SetLastError(0); /* FIXME */
SYSTEM_UNLOCK();
return handle;
}
@@ -130,11 +176,7 @@
SetLastError( ERROR_NOT_OWNER );
return FALSE;
}
- if (!--mutex->count)
- {
- mutex->owner = 0;
- SYNC_WakeUp( &mutex->wait_queue, INFINITE32 );
- }
+ if (!--mutex->count) MUTEX_Release( mutex );
K32OBJ_DecCount( &mutex->header );
SYSTEM_UNLOCK();
return TRUE;
@@ -157,13 +199,25 @@
*
* Wait on this object has been satisfied.
*/
-static void MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 MUTEX_Satisfied( K32OBJ *obj, DWORD thread_id )
{
+ BOOL32 ret;
MUTEX *mutex = (MUTEX *)obj;
assert( obj->type == K32OBJ_MUTEX );
assert( !mutex->count || (mutex->owner == thread_id) );
mutex->owner = thread_id;
- mutex->count++;
+ if (!mutex->count++)
+ {
+ /* Add the mutex in the thread list of owned mutexes */
+ K32OBJ **list = &THREAD_ID_TO_THDB( thread_id )->mutex_list;
+ assert( !mutex->next );
+ if ((mutex->next = (MUTEX *)*list)) mutex->next->prev = mutex;
+ *list = &mutex->header;
+ mutex->prev = NULL;
+ }
+ ret = mutex->abandoned;
+ mutex->abandoned = FALSE;
+ return ret;
}
diff --git a/scheduler/process.c b/scheduler/process.c
index 225dd14..d42f3f3 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -18,15 +18,16 @@
#include "winerror.h"
#include "pe_image.h"
-PDB32 *pCurrentProcess = NULL;
-
#define HTABLE_SIZE 0x30 /* Handle table initial size */
#define HTABLE_INC 0x10 /* Handle table increment */
-#define BOOT_HTABLE_SIZE 10
+/* PDB <-> Process id conversion macros */
+#define PROCESS_OBFUSCATOR ((DWORD)0xdeadbeef)
+#define PROCESS_ID_TO_PDB(id) ((PDB32 *)((id) ^ PROCESS_OBFUSCATOR))
+#define PDB_TO_PROCESS_ID(pdb) ((DWORD)(pdb) ^ PROCESS_OBFUSCATOR)
static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id );
-static void PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id );
static void PROCESS_AddWait( K32OBJ *obj, DWORD thread_id );
static void PROCESS_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void PROCESS_Destroy( K32OBJ *obj );
@@ -40,7 +41,6 @@
PROCESS_Destroy /* destroy */
};
-static HANDLE_ENTRY boot_handles[BOOT_HTABLE_SIZE];
/***********************************************************************
* PROCESS_AllocHandleTable
@@ -79,83 +79,31 @@
/***********************************************************************
- * PROCESS_AllocBootHandle
- *
- * Allocate a handle from the boot table.
+ * PROCESS_Current
*/
-static HANDLE32 PROCESS_AllocBootHandle( K32OBJ *ptr, DWORD flags )
+PDB32 *PROCESS_Current(void)
{
- HANDLE32 h;
- SYSTEM_LOCK();
- for (h = 0; h < BOOT_HTABLE_SIZE; h++)
- if (!boot_handles[h].ptr) break;
- assert( h < BOOT_HTABLE_SIZE );
- K32OBJ_IncCount( ptr );
- boot_handles[h].flags = flags;
- boot_handles[h].ptr = ptr;
- SYSTEM_UNLOCK();
- return h + 1; /* Avoid handle 0 */
+ return THREAD_Current()->process;
}
/***********************************************************************
- * PROCESS_CloseBootHandle
+ * PROCESS_IdToPDB
*
- * Close a handle from the boot table.
+ * Convert a process id to a PDB, making sure it is valid.
*/
-static BOOL32 PROCESS_CloseBootHandle( HANDLE32 handle )
+PDB32 *PROCESS_IdToPDB( DWORD id )
{
- K32OBJ *ptr;
- HANDLE_ENTRY *entry = &boot_handles[handle - 1];
- assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
- SYSTEM_LOCK();
- assert( entry->ptr );
- ptr = entry->ptr;
- entry->flags = 0;
- entry->ptr = NULL;
- K32OBJ_DecCount( ptr );
- SYSTEM_UNLOCK();
- return TRUE;
-}
+ PDB32 *pdb;
-
-/***********************************************************************
- * PROCESS_GetBootObjPtr
- *
- * Get a handle ptr from the boot table.
- */
-static K32OBJ *PROCESS_GetBootObjPtr( HANDLE32 handle, K32OBJ_TYPE type )
-{
- K32OBJ *ptr;
-
- assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
- SYSTEM_LOCK();
- ptr = boot_handles[handle - 1].ptr;
- assert (ptr && (ptr->type == type));
- K32OBJ_IncCount( ptr );
- SYSTEM_UNLOCK();
- return ptr;
-}
-
-
-/***********************************************************************
- * PROCESS_SetBootObjPtr
- *
- * Set a handle ptr from the boot table.
- */
-static BOOL32 PROCESS_SetBootObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags)
-{
- K32OBJ *old_ptr;
-
- assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
- SYSTEM_LOCK();
- K32OBJ_IncCount( ptr );
- old_ptr = boot_handles[handle - 1].ptr;
- boot_handles[handle - 1].flags = flags;
- boot_handles[handle - 1].ptr = ptr;
- if (old_ptr) K32OBJ_DecCount( old_ptr );
- SYSTEM_UNLOCK();
- return TRUE;
+ if (!id) return PROCESS_Current();
+ pdb = PROCESS_ID_TO_PDB( id );
+ if (!K32OBJ_IsValid( &pdb->header, K32OBJ_PROCESS ))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return NULL;
+ }
+ return pdb;
}
@@ -168,18 +116,17 @@
{
HANDLE32 h;
HANDLE_ENTRY *entry;
+ PDB32 *pdb = PROCESS_Current();
assert( ptr );
- if (!pCurrentProcess) return PROCESS_AllocBootHandle( ptr, flags );
SYSTEM_LOCK();
K32OBJ_IncCount( ptr );
- entry = pCurrentProcess->handle_table->entries;
- for (h = 0; h < pCurrentProcess->handle_table->count; h++, entry++)
+ entry = pdb->handle_table->entries;
+ for (h = 0; h < pdb->handle_table->count; h++, entry++)
if (!entry->ptr) break;
- if ((h < pCurrentProcess->handle_table->count) ||
- PROCESS_GrowHandleTable( pCurrentProcess ))
+ if ((h < pdb->handle_table->count) || PROCESS_GrowHandleTable( pdb ))
{
- entry = &pCurrentProcess->handle_table->entries[h];
+ entry = &pdb->handle_table->entries[h];
entry->flags = flags;
entry->ptr = ptr;
SYSTEM_UNLOCK();
@@ -201,12 +148,13 @@
K32OBJ *PROCESS_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type )
{
K32OBJ *ptr = NULL;
- if (!pCurrentProcess) return PROCESS_GetBootObjPtr( handle, type );
+ PDB32 *pdb = PROCESS_Current();
+
SYSTEM_LOCK();
- if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
- ptr = pCurrentProcess->handle_table->entries[handle - 1].ptr;
- else if (handle == 0x7fffffff) ptr = &pCurrentProcess->header;
+ if ((handle > 0) && (handle <= pdb->handle_table->count))
+ ptr = pdb->handle_table->entries[handle - 1].ptr;
+ else if (handle == 0x7fffffff) ptr = &pdb->header;
if (ptr && ((type == K32OBJ_UNKNOWN) || (ptr->type == type)))
K32OBJ_IncCount( ptr );
@@ -228,12 +176,12 @@
{
BOOL32 ret = TRUE;
K32OBJ *old_ptr = NULL;
+ PDB32 *pdb = PROCESS_Current();
- if (!pCurrentProcess) return PROCESS_SetBootObjPtr( handle, ptr, flags );
SYSTEM_LOCK();
- if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
+ if ((handle > 0) && (handle <= pdb->handle_table->count))
{
- HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
+ HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
old_ptr = entry->ptr;
K32OBJ_IncCount( ptr );
entry->flags = flags;
@@ -257,12 +205,12 @@
{
BOOL32 ret = FALSE;
K32OBJ *ptr = NULL;
+ PDB32 *pdb = PROCESS_Current();
- if (!pCurrentProcess) return PROCESS_CloseBootHandle( handle );
SYSTEM_LOCK();
- if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
+ if ((handle > 0) && (handle <= pdb->handle_table->count))
{
- HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
+ HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
if ((ptr = entry->ptr))
{
entry->flags = 0;
@@ -334,17 +282,32 @@
/***********************************************************************
- * PROCESS_Create
+ * PROCESS_FreePDB
+ *
+ * Free a PDB and all associated storage.
*/
-PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line )
+static void PROCESS_FreePDB( PDB32 *pdb )
+{
+ pdb->header.type = K32OBJ_UNKNOWN;
+ if (pdb->heap) HeapDestroy( pdb->heap );
+ if (pdb->handle_table) HeapFree( pdb->system_heap, 0, pdb->handle_table );
+ if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
+ if (pdb->event) K32OBJ_DecCount( pdb->event );
+ DeleteCriticalSection( &pdb->crit_section );
+ HeapFree( SystemHeap, 0, pdb );
+}
+
+
+/***********************************************************************
+ * PROCESS_CreatePDB
+ *
+ * Allocate and fill a PDB structure.
+ */
+static PDB32 *PROCESS_CreatePDB( PDB32 *parent )
{
PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
- DWORD size, commit;
- NE_MODULE *pModule;
if (!pdb) return NULL;
- if (!(pModule = MODULE_GetPtr( pTask->hModule ))) return 0;
-
pdb->header.type = K32OBJ_PROCESS;
pdb->header.refcount = 1;
pdb->exit_code = 0x103; /* STILL_ACTIVE */
@@ -352,7 +315,7 @@
pdb->running_threads = 1;
pdb->ring0_threads = 1;
pdb->system_heap = SystemHeap;
- pdb->parent = pCurrentProcess;
+ pdb->parent = parent;
pdb->group = pdb;
pdb->priority = 8; /* Normal */
@@ -363,6 +326,46 @@
if (!(pdb->event = EVENT_Create( TRUE, FALSE ))) goto error;
if (!(pdb->load_done_evt = EVENT_Create( TRUE, FALSE ))) goto error;
+ /* Allocate the handle table */
+
+ if (!(pdb->handle_table = PROCESS_AllocHandleTable( pdb ))) goto error;
+ return pdb;
+
+error:
+ PROCESS_FreePDB( pdb );
+ return NULL;
+}
+
+
+/***********************************************************************
+ * PROCESS_Init
+ */
+BOOL32 PROCESS_Init(void)
+{
+ PDB32 *pdb;
+ THDB *thdb;
+
+ if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
+ if (!(thdb = THREAD_Create( pdb, 0, NULL, NULL ))) return FALSE;
+ SET_CUR_THREAD( thdb );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * PROCESS_Create
+ *
+ * Create a new process database and associated info.
+ */
+PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line )
+{
+ DWORD size, commit;
+ NE_MODULE *pModule;
+ PDB32 *pdb = PROCESS_CreatePDB( PROCESS_Current() );
+
+ if (!pdb) return NULL;
+ if (!(pModule = MODULE_GetPtr( pTask->hModule ))) return 0;
+
/* Create the heap */
if (pModule->module32)
@@ -380,18 +383,11 @@
if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
goto error;
- if (!(pdb->handle_table = PROCESS_AllocHandleTable( pdb ))) goto error;
if (!PROCESS_FillEnvDB( pdb, pTask, cmd_line )) goto error;
return pdb;
error:
- if (pdb->env_db) HeapFree( pdb->heap, 0, pdb->env_db );
- if (pdb->handle_table) HeapFree( pdb->system_heap, 0, pdb->handle_table );
- if (pdb->heap) HeapDestroy( pdb->heap );
- if (pdb->load_done_evt) K32OBJ_DecCount( pdb->load_done_evt );
- if (pdb->event) K32OBJ_DecCount( pdb->event );
- DeleteCriticalSection( &pdb->crit_section );
- HeapFree( SystemHeap, 0, pdb );
+ PROCESS_FreePDB( pdb );
return NULL;
}
@@ -412,7 +408,7 @@
*
* Wait on this object has been satisfied.
*/
-static void PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 PROCESS_Satisfied( K32OBJ *obj, DWORD thread_id )
{
PDB32 *pdb = (PDB32 *)obj;
assert( obj->type == K32OBJ_PROCESS );
@@ -462,13 +458,7 @@
/* Free everything */
ptr->type = K32OBJ_UNKNOWN;
- HeapFree( pdb->heap, 0, pdb->env_db );
- HeapFree( pdb->system_heap, 0, pdb->handle_table );
- HeapDestroy( pdb->heap );
- K32OBJ_DecCount( pdb->load_done_evt );
- K32OBJ_DecCount( pdb->event );
- DeleteCriticalSection( &pdb->crit_section );
- HeapFree( SystemHeap, 0, pdb );
+ PROCESS_FreePDB( pdb );
}
@@ -477,10 +467,15 @@
*/
void WINAPI ExitProcess( DWORD status )
{
- __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
+ PDB32 *pdb = PROCESS_Current();
+
+ SYSTEM_LOCK();
/* FIXME: should kill all running threads of this process */
- pCurrentProcess->exit_code = status;
- EVENT_Set( pCurrentProcess->event );
+ pdb->exit_code = status;
+ EVENT_Set( pdb->event );
+ SYSTEM_UNLOCK();
+
+ __RESTORE_ES; /* Necessary for Pietrek's showseh example program */
TASK_KillCurrentTask( status );
}
@@ -514,7 +509,8 @@
*/
DWORD WINAPI GetCurrentProcessId(void)
{
- return PDB_TO_PROCESS_ID(pCurrentProcess);
+ PDB32 *pdb = PROCESS_Current();
+ return PDB_TO_PROCESS_ID( pdb );
}
@@ -523,8 +519,8 @@
*/
LPSTR WINAPI GetEnvironmentStrings32A(void)
{
- assert( pCurrentProcess );
- return pCurrentProcess->env_db->environ;
+ PDB32 *pdb = PROCESS_Current();
+ return pdb->env_db->environ;
}
@@ -536,12 +532,12 @@
INT32 size;
LPWSTR ret, pW;
LPSTR pA;
+ PDB32 *pdb = PROCESS_Current();
- assert( pCurrentProcess );
- size = HeapSize( GetProcessHeap(), 0, pCurrentProcess->env_db->environ );
+ size = HeapSize( GetProcessHeap(), 0, pdb->env_db->environ );
if (!(ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
return NULL;
- pA = pCurrentProcess->env_db->environ;
+ pA = pdb->env_db->environ;
pW = ret;
while (*pA)
{
@@ -560,8 +556,8 @@
*/
BOOL32 WINAPI FreeEnvironmentStrings32A( LPSTR ptr )
{
- assert( pCurrentProcess );
- if (ptr != pCurrentProcess->env_db->environ)
+ PDB32 *pdb = PROCESS_Current();
+ if (ptr != pdb->env_db->environ)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
@@ -575,7 +571,6 @@
*/
BOOL32 WINAPI FreeEnvironmentStrings32W( LPWSTR ptr )
{
- assert( pCurrentProcess );
return HeapFree( GetProcessHeap(), 0, ptr );
}
@@ -588,8 +583,7 @@
LPSTR p;
INT32 len, res;
- assert( pCurrentProcess );
- p = pCurrentProcess->env_db->environ;
+ p = PROCESS_Current()->env_db->environ;
if (!name || !*name)
{
SetLastError( ERROR_INVALID_PARAMETER );
@@ -639,9 +633,9 @@
{
INT32 size, len, res;
LPSTR p, env, new_env;
+ PDB32 *pdb = PROCESS_Current();
- assert( pCurrentProcess );
- env = p = pCurrentProcess->env_db->environ;
+ env = p = pdb->env_db->environ;
/* Find a place to insert the string */
@@ -662,18 +656,16 @@
len = value ? strlen(name) + strlen(value) + 2 : 0;
if (!res) len -= strlen(p) + 1; /* The name already exists */
- size = pCurrentProcess->env_db->env_size + len;
+ size = pdb->env_db->env_size + len;
if (len < 0)
{
LPSTR next = p + strlen(p) + 1;
- memmove( next + len, next,
- pCurrentProcess->env_db->env_size - (next - env) );
+ memmove( next + len, next, pdb->env_db->env_size - (next - env) );
}
if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, size )))
return FALSE;
p = new_env + (p - env);
- if (len > 0)
- memmove( p + len, p, pCurrentProcess->env_db->env_size - (p-new_env) );
+ if (len > 0) memmove( p + len, p, pdb->env_db->env_size - (p-new_env) );
/* Set the new string */
@@ -683,8 +675,8 @@
strcat( p, "=" );
strcat( p, value );
}
- pCurrentProcess->env_db->env_size = size;
- pCurrentProcess->env_db->environ = new_env;
+ pdb->env_db->env_size = size;
+ pdb->env_db->environ = new_env;
return TRUE;
}
@@ -799,8 +791,8 @@
*/
HANDLE32 WINAPI GetProcessHeap(void)
{
- if (!pCurrentProcess) return SystemHeap; /* For the boot-up code */
- return pCurrentProcess->heap;
+ PDB32 *pdb = PROCESS_Current();
+ return pdb->heap ? pdb->heap : SystemHeap;
}
@@ -809,7 +801,7 @@
*/
LCID WINAPI GetThreadLocale(void)
{
- return pCurrentProcess->locale;
+ return PROCESS_Current()->locale;
}
@@ -890,23 +882,20 @@
{
HFILE32 hFile;
int fd;
+ PDB32 *pdb = PROCESS_Current();
- assert( pCurrentProcess );
switch(std_handle)
{
case STD_INPUT_HANDLE:
- if (pCurrentProcess->env_db->hStdin)
- return pCurrentProcess->env_db->hStdin;
+ if (pdb->env_db->hStdin) return pdb->env_db->hStdin;
fd = 0;
break;
case STD_OUTPUT_HANDLE:
- if (pCurrentProcess->env_db->hStdout)
- return pCurrentProcess->env_db->hStdout;
+ if (pdb->env_db->hStdout) return pdb->env_db->hStdout;
fd = 1;
break;
case STD_ERROR_HANDLE:
- if (pCurrentProcess->env_db->hStderr)
- return pCurrentProcess->env_db->hStderr;
+ if (pdb->env_db->hStderr) return pdb->env_db->hStderr;
fd = 2;
break;
default:
@@ -919,9 +908,9 @@
FILE_SetFileType( hFile, FILE_TYPE_CHAR );
switch(std_handle)
{
- case STD_INPUT_HANDLE: pCurrentProcess->env_db->hStdin=hFile; break;
- case STD_OUTPUT_HANDLE: pCurrentProcess->env_db->hStdout=hFile; break;
- case STD_ERROR_HANDLE: pCurrentProcess->env_db->hStderr=hFile; break;
+ case STD_INPUT_HANDLE: pdb->env_db->hStdin = hFile; break;
+ case STD_OUTPUT_HANDLE: pdb->env_db->hStdout = hFile; break;
+ case STD_ERROR_HANDLE: pdb->env_db->hStderr = hFile; break;
}
}
return hFile;
@@ -933,17 +922,17 @@
*/
BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle )
{
- assert( pCurrentProcess );
+ PDB32 *pdb = PROCESS_Current();
switch(std_handle)
{
case STD_INPUT_HANDLE:
- pCurrentProcess->env_db->hStdin = handle;
+ pdb->env_db->hStdin = handle;
return TRUE;
case STD_OUTPUT_HANDLE:
- pCurrentProcess->env_db->hStdout = handle;
+ pdb->env_db->hStdout = handle;
return TRUE;
case STD_ERROR_HANDLE:
- pCurrentProcess->env_db->hStderr = handle;
+ pdb->env_db->hStderr = handle;
return TRUE;
}
SetLastError( ERROR_INVALID_PARAMETER );
@@ -955,43 +944,22 @@
*/
DWORD WINAPI GetProcessVersion( DWORD processid )
{
- PDB32 *process;
TDB *pTask;
+ PDB32 *pdb = PROCESS_IdToPDB( processid );
- if (!processid) process = pCurrentProcess;
- else
- {
- process = PROCESS_ID_TO_PDB(processid);
- if (!K32OBJ_IsValid( &process->header, K32OBJ_PROCESS ))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return 0;
- }
- }
- pTask = (TDB*)GlobalLock16(process->task);
- if (!pTask)
- return 0;
+ if (!pdb) return 0;
+ if (!(pTask = (TDB *)GlobalLock16( pdb->task ))) return 0;
return (pTask->version&0xff) | (((pTask->version >>8) & 0xff)<<16);
}
/***********************************************************************
* GetProcessFlags (KERNEL32)
*/
-DWORD WINAPI GetProcessFlags(DWORD processid)
+DWORD WINAPI GetProcessFlags( DWORD processid )
{
- PDB32 *process;
-
- if (!processid) process = pCurrentProcess;
- else
- {
- process = PROCESS_ID_TO_PDB(processid);
- if (!K32OBJ_IsValid( &process->header, K32OBJ_PROCESS ))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return 0;
- }
- }
- return process->flags;
+ PDB32 *pdb = PROCESS_IdToPDB( processid );
+ if (!pdb) return 0;
+ return pdb->flags;
}
/***********************************************************************
diff --git a/scheduler/semaphore.c b/scheduler/semaphore.c
index d8c1535..d6cfd49 100644
--- a/scheduler/semaphore.c
+++ b/scheduler/semaphore.c
@@ -21,7 +21,7 @@
} SEMAPHORE;
static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id );
-static void SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_Destroy( K32OBJ *obj );
@@ -165,12 +165,13 @@
*
* Wait on this object has been satisfied.
*/
-static void SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id )
{
SEMAPHORE *sem = (SEMAPHORE *)obj;
assert( obj->type == K32OBJ_SEMAPHORE );
assert( sem->count > 0 );
sem->count--;
+ return FALSE; /* Not abandoned */
}
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 2000217..8577992 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -88,7 +88,8 @@
/* Wait satisfied: tell it to all objects */
wait->signaled = WAIT_OBJECT_0;
for (i = 0, ptr = wait->objs; i < wait->count; i++, ptr++)
- K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id );
+ if (K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id ))
+ wait->signaled = WAIT_ABANDONED_0;
SYSTEM_UNLOCK();
return TRUE;
}
@@ -100,7 +101,8 @@
{
/* Wait satisfied: tell it to the object */
wait->signaled = WAIT_OBJECT_0 + i;
- K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id );
+ if (K32OBJ_OPS( *ptr )->satisfied( *ptr, thread_id ))
+ wait->signaled = WAIT_ABANDONED_0 + i;
SYSTEM_UNLOCK();
return TRUE;
}
diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c
new file mode 100644
index 0000000..08c4dc3
--- /dev/null
+++ b/scheduler/sysdeps.c
@@ -0,0 +1,121 @@
+/*
+ * System-dependent scheduler support
+ *
+ * Copyright 1998 Alexandre Julliard
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "thread.h"
+
+#ifdef __linux__
+# ifdef HAVE_SCHED_H
+# include <sched.h>
+# endif
+# ifndef CLONE_VM
+# define CLONE_VM 0x00000100
+# define CLONE_FS 0x00000200
+# define CLONE_FILES 0x00000400
+# define CLONE_SIGHAND 0x00000800
+# define CLONE_PID 0x00001000
+/* If we didn't get the flags, we probably didn't get the prototype either */
+extern int clone( int (*fn)(void *arg), void *stack, int flags, void *arg );
+# endif /* CLONE_VM */
+#endif /* __linux__ */
+
+
+#ifdef __linux__
+/***********************************************************************
+ * __errno_location
+ *
+ * Get the per-thread errno location.
+ */
+int *__errno_location()
+{
+ static int static_errno;
+ THDB *thdb = THREAD_Current();
+ if (!thdb) return &static_errno;
+ return &thdb->thread_errno;
+}
+
+/***********************************************************************
+ * __h_errno_location
+ *
+ * Get the per-thread h_errno location.
+ */
+int *__h_errno_location()
+{
+ static int static_h_errno;
+ THDB *thdb = THREAD_Current();
+ if (!thdb) return &static_h_errno;
+ return &thdb->thread_h_errno;
+}
+
+/***********************************************************************
+ * SYSDEPS_StartThread
+ *
+ * Startup routine for a new thread.
+ */
+static void SYSDEPS_StartThread( THDB *thdb )
+{
+ LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
+ thdb->unix_pid = getpid();
+ SET_FS( thdb->teb_sel );
+ ExitThread( func( thdb->entry_arg ) );
+}
+#endif /* __linux__ */
+
+
+/***********************************************************************
+ * SYSDEPS_SpawnThread
+ *
+ * Start running a new thread.
+ * Return -1 on error, 0 if OK.
+ */
+int SYSDEPS_SpawnThread( THDB *thread )
+{
+#ifdef __linux__
+ if (clone( (int (*)(void *))SYSDEPS_StartThread, thread->teb.stack_top,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, thread ) < 0)
+ return -1;
+#else
+ fprintf( stderr, "CreateThread: stub\n" );
+#endif /* __linux__ */
+ return 0;
+}
+
+
+/***********************************************************************
+ * SYSDEPS_ExitThread
+ *
+ * Exit a running thread; must not return.
+ */
+void SYSDEPS_ExitThread(void)
+{
+ _exit( 0 );
+}
+
+
+/**********************************************************************
+ * NtCurrentTeb (NTDLL.89)
+ */
+TEB * WINAPI NtCurrentTeb(void)
+{
+#ifdef __i386__
+ TEB *teb;
+ WORD ds, fs;
+
+ /* Check if we have a current thread */
+ GET_DS( ds );
+ GET_FS( fs );
+ if (fs == ds) return NULL; /* FIXME: should be an assert */
+ /* Get the TEB self-pointer */
+ __asm__( ".byte 0x64\n\tmovl (%1),%0"
+ : "=r" (teb) : "r" (&((TEB *)0)->self) );
+ return teb;
+#else
+ if (!pCurrentThread) return NULL;
+ return &pCurrentThread->teb;
+#endif /* __i386__ */
+}
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 73959d0..984b89c 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -18,27 +18,12 @@
#include "debug.h"
#include "stddebug.h"
-#ifdef HAVE_CLONE
-# ifdef HAVE_SCHED_H
-# include <sched.h>
-# endif
-# ifndef CLONE_VM
-# define CLONE_VM 0x00000100
-# define CLONE_FS 0x00000200
-# define CLONE_FILES 0x00000400
-# define CLONE_SIGHAND 0x00000800
-# define CLONE_PID 0x00001000
-/* If we didn't get the flags, we probably didn't get the prototype either */
-extern int clone( int (*fn)(void *arg), void *stack, int flags, void *arg );
-# endif /* CLONE_VM */
-#endif /* HAVE_CLONE */
-
#ifndef __i386__
THDB *pCurrentThread;
#endif
static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id );
-static void THREAD_Satisfied( K32OBJ *obj, DWORD thread_id );
+static BOOL32 THREAD_Satisfied( K32OBJ *obj, DWORD thread_id );
static void THREAD_AddWait( K32OBJ *obj, DWORD thread_id );
static void THREAD_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void THREAD_Destroy( K32OBJ *obj );
@@ -73,28 +58,6 @@
}
-/**********************************************************************
- * NtCurrentTeb (NTDLL.89)
- */
-TEB * WINAPI NtCurrentTeb(void)
-{
-#ifdef __i386__
- TEB *teb;
- WORD ds, fs;
-
- /* Check if we have a current thread */
- GET_DS( ds );
- GET_FS( fs );
- if (fs == ds) return NULL; /* FIXME: should be an assert */
- __asm__( "movl %%fs:(24),%0" : "=r" (teb) );
- return teb;
-#else
- if (!pCurrentThread) return NULL;
- return &pCurrentThread->teb;
-#endif /* __i386__ */
-}
-
-
/***********************************************************************
* THREAD_Current
*
@@ -181,7 +144,6 @@
thdb->teb.self = &thdb->teb;
thdb->teb.tls_ptr = thdb->tls_array;
thdb->wait_list = &thdb->wait_struct;
- thdb->process2 = pdb;
thdb->exit_code = 0x103; /* STILL_ACTIVE */
thdb->entry_point = start_addr;
thdb->entry_arg = param;
@@ -234,20 +196,6 @@
/***********************************************************************
- * THREAD_Start
- *
- * Startup routine for a new thread.
- */
-static void THREAD_Start( THDB *thdb )
-{
- LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
- thdb->unix_pid = getpid();
- SET_FS( thdb->teb_sel );
- ExitThread( func( thdb->entry_arg ) );
-}
-
-
-/***********************************************************************
* THREAD_Signaled
*/
static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id )
@@ -263,7 +211,7 @@
*
* Wait on this object has been satisfied.
*/
-static void THREAD_Satisfied( K32OBJ *obj, DWORD thread_id )
+static BOOL32 THREAD_Satisfied( K32OBJ *obj, DWORD thread_id )
{
THDB *thdb = (THDB *)obj;
assert( obj->type == K32OBJ_THREAD );
@@ -336,26 +284,17 @@
DWORD flags, LPDWORD id )
{
HANDLE32 handle;
- THDB *thread = THREAD_Create( pCurrentProcess, stack, start, param );
+ THDB *thread = THREAD_Create( PROCESS_Current(), stack, start, param );
if (!thread) return INVALID_HANDLE_VALUE32;
handle = PROCESS_AllocHandle( &thread->header, 0 );
- if (handle == INVALID_HANDLE_VALUE32)
- {
- K32OBJ_DecCount( &thread->header );
- return INVALID_HANDLE_VALUE32;
- }
-#ifdef HAVE_CLONE
- if (clone( (int (*)(void *))THREAD_Start, thread->teb.stack_top,
- CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, thread ) < 0)
- {
- K32OBJ_DecCount( &thread->header );
- return INVALID_HANDLE_VALUE32;
- }
-#else
- fprintf( stderr, "CreateThread: stub\n" );
-#endif /* __linux__ */
+ if (handle == INVALID_HANDLE_VALUE32) goto error;
+ if (SYSDEPS_SpawnThread( thread ) == -1) goto error;
*id = THDB_TO_THREAD_ID( thread );
return handle;
+
+error:
+ K32OBJ_DecCount( &thread->header );
+ return INVALID_HANDLE_VALUE32;
}
@@ -370,12 +309,16 @@
SYSTEM_LOCK();
thdb->exit_code = code;
EVENT_Set( thdb->event );
+
+ /* Abandon all owned mutexes */
+ while (thdb->mutex_list) MUTEX_Abandon( thdb->mutex_list );
+
/* FIXME: should free the stack somehow */
K32OBJ_DecCount( &thdb->header );
/* Completely unlock the system lock just in case */
count = SYSTEM_LOCK_COUNT();
while (count--) SYSTEM_UNLOCK();
- _exit( 0 );
+ SYSDEPS_ExitThread();
}
diff --git a/tools/build.c b/tools/build.c
index ad4db74..1cc07e7 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -25,6 +25,12 @@
# define PREFIX
#endif
+#ifdef HAVE_ASM_STRING
+# define STRING ".string"
+#else
+# define STRING ".ascii"
+#endif
+
#if defined(__GNUC__) && !defined(__svr4__)
# define USE_STABS
#else
@@ -1240,7 +1246,7 @@
/* Output the DLL descriptor */
fprintf( outfile, "\t.text\n" );
- fprintf( outfile, "DLLName:\t.string \"%s\\0\"\n", DLLName );
+ fprintf( outfile, "DLLName:\t" STRING " \"%s\\0\"\n", DLLName );
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
@@ -1299,14 +1305,6 @@
{
int i, pos16, pos32;
- /* Save ebx first */
-
- fprintf( outfile, "\tpushl %%ebx\n" );
-
- /* Get the 32-bit stack pointer */
-
- fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%ebx\n" );
-
/* Copy the arguments */
pos16 = 6; /* skip bp and return address */
@@ -1355,10 +1353,6 @@
}
}
- /* Restore ebx */
-
- fprintf( outfile, "\tpopl %%ebx\n" );
-
return pos16 - 6; /* Return the size of the 16-bit args */
}
@@ -1370,18 +1364,8 @@
*/
static void BuildContext16( FILE *outfile )
{
- /* Save ebx first */
-
- fprintf( outfile, "\tpushl %%ebx\n" );
-
- /* Get the 32-bit stack pointer */
-
- fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%ebx\n" );
-
/* Store the registers */
- fprintf( outfile, "\tpopl %d(%%ebx)\n", /* Get ebx from stack*/
- CONTEXTOFFSET(Ebx) - sizeof(CONTEXT) );
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(Eax) - sizeof(CONTEXT) );
fprintf( outfile, "\tmovl %%ecx,%d(%%ebx)\n",
@@ -1393,6 +1377,9 @@
fprintf( outfile, "\tmovl %%edi,%d(%%ebx)\n",
CONTEXTOFFSET(Edi) - sizeof(CONTEXT) );
+ fprintf( outfile, "\tmovl -20(%%ebp),%%eax\n" ); /* Get %ebx from stack*/
+ fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
+ CONTEXTOFFSET(Ebx) - sizeof(CONTEXT) );
fprintf( outfile, "\tmovzwl -10(%%ebp),%%eax\n" ); /* Get %ds from stack*/
fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
CONTEXTOFFSET(SegDs) - sizeof(CONTEXT) );
@@ -1437,7 +1424,8 @@
{
/* Get the 32-bit stack pointer */
- fprintf( outfile, "\tmovl %%edx,%%ebx\n" );
+ fprintf( outfile, "\tleal -%d(%%ebp),%%ebx\n",
+ STRUCTOFFSET(STACK32FRAME,ebp) );
/* Remove everything up to the return address from the 16-bit stack */
@@ -1500,8 +1488,7 @@
*
* Added on the stack:
* (sp-4) long ebp
- * (sp-6) word saved previous sp
- * (sp-8) word saved previous ss
+ * (sp-8) long saved previous stack
*/
static void BuildCallFrom16Func( FILE *outfile, char *profile )
{
@@ -1544,16 +1531,28 @@
/* fprintf( outfile, "\tmovw %%es,-6(%%ebp)\n" ); */
fprintf( outfile, "\t.byte 0x66,0x8c,0x45,0xfa\n" );
+ /* Save %ebx */
+
+ fprintf( outfile, "\tpushl %%ebx\n" );
+
/* Restore 32-bit ds and es */
- fprintf( outfile, "\tpushl $0x%04x%04x\n", Data_Selector, Data_Selector );
- fprintf( outfile, "\t.byte 0x66\n\tpopl %%ds\n" );
- fprintf( outfile, "\t.byte 0x66\n\tpopl %%es\n" );
+ fprintf( outfile, "\tmovw $0x%04x,%%bx\n", Data_Selector );
+#ifdef __svr4__
+ fprintf( outfile, "\tdata16\n");
+#endif
+ fprintf( outfile, "\tmovw %%bx,%%ds\n" );
+#ifdef __svr4__
+ fprintf( outfile, "\tdata16\n");
+#endif
+ fprintf( outfile, "\tmovw %%bx,%%es\n" );
+ /* Get the 32-bit stack pointer */
+
+ fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%ebx\n" );
/* Save the 16-bit stack */
- fprintf( outfile, "\tpushl " PREFIX "IF1632_Saved16_ss_sp\n" );
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
#endif
@@ -1574,9 +1573,14 @@
if (!reg_func && short_ret)
fprintf( outfile, "\tmovl %%edx,-4(%%ebp)\n" );
+ /* Restore %ebx and store the 32-bit stack pointer instead */
+
+ fprintf( outfile, "\tmovl %%ebx,%%ebp\n" );
+ fprintf( outfile, "\tpopl %%ebx\n" );
+ fprintf( outfile, "\tpushl %%ebp\n" );
+
/* Switch to the 32-bit stack */
- fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%ebp\n" );
fprintf( outfile, "\tpushl %%ds\n" );
fprintf( outfile, "\tpopl %%ss\n" );
fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
@@ -1624,12 +1628,6 @@
fprintf( outfile, "\tpopl %%eax\n" );
}
- /* Restore the value of the saved 32-bit stack pointer */
-
- fprintf( outfile, "\tleal -%d(%%ebp),%%edx\n",
- STRUCTOFFSET(STACK32FRAME,ebp) );
- fprintf( outfile, "movl %%edx," PREFIX "CALLTO16_Saved32_esp\n" );
-
/* Restore the 16-bit stack */
#ifdef __svr4__
@@ -1637,7 +1635,7 @@
#endif
fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp+2,%%ss\n" );
fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp,%%sp\n" );
- fprintf( outfile, "\tpopl " PREFIX "IF1632_Saved16_ss_sp\n" );
+ fprintf( outfile, "\tpopl " PREFIX "CALLTO16_Saved32_esp\n" );
if (reg_func)
{
@@ -1722,8 +1720,8 @@
* Prototypes for the CallTo16 functions:
* extern WINAPI WORD CallTo16_word_xxx( FARPROC16 func, args... );
* extern WINAPI LONG CallTo16_long_xxx( FARPROC16 func, args... );
- * extern WINAPI void CallTo16_sreg_( const CONTEXT *context );
- * extern WINAPI void CallTo16_lreg_( const CONTEXT *context );
+ * extern WINAPI void CallTo16_sreg_( const CONTEXT *context, int nb_args );
+ * extern WINAPI void CallTo16_lreg_( const CONTEXT *context, int nb_args );
*/
static void BuildCallTo16Func( FILE *outfile, char *profile )
{
@@ -1782,11 +1780,6 @@
fprintf( outfile, "\tpushl %%esi\n" );
fprintf( outfile, "\tpushl %%edi\n" );
- /* Save the 32-bit stack */
-
- fprintf( outfile, "\tmovl %%esp," PREFIX "CALLTO16_Saved32_esp\n" );
- fprintf( outfile, "\tmovl %%ebp,%%ebx\n" );
-
/* Print debugging info */
if (debugging)
@@ -1800,21 +1793,23 @@
fprintf( outfile, "\tpopl %%eax\n" );
}
+ /* Save the 32-bit stack */
+
+ fprintf( outfile, "\tpushl " PREFIX "IF1632_Saved16_ss_sp\n" );
+ fprintf( outfile, "\tmovl %%esp," PREFIX "CALLTO16_Saved32_esp\n" );
+ fprintf( outfile, "\tmovl %%ebp,%%ebx\n" );
+
if (reg_func)
{
/* Switch to the 16-bit stack, saving the current %%esp, */
/* and adding the specified offset to the new sp */
- fprintf( outfile, "\tmovzwl " PREFIX "IF1632_Saved16_ss_sp,%%edx\n" );
- fprintf( outfile, "\tleal -4(%%edx),%%edx\n" );
- fprintf( outfile, "\tmovl 12(%%ebx),%%eax\n" ); /* Get the offset */
- fprintf( outfile, "\taddl %%edx,%%eax\n" );
+ fprintf( outfile, "\tmovzwl " PREFIX "IF1632_Saved16_ss_sp,%%eax\n" );
+ fprintf( outfile, "\tsubl 12(%%ebx),%%eax\n" ); /* Get the offset */
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
#endif
fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp+2,%%ss\n" );
- fprintf( outfile, "\txchgl %%esp,%%eax\n" );
- fprintf( outfile, "\t.byte 0x36\n" /* %ss: */ );
- fprintf( outfile, "\tmovl %%eax,0(%%edx)\n" );
+ fprintf( outfile, "\tmovl %%eax,%%esp\n" );
/* Get the registers. ebx is handled later on. */
@@ -1858,19 +1853,17 @@
{
int pos = 12; /* first argument position */
- /* Switch to the 16-bit stack, saving the current %%esp */
- fprintf( outfile, "\tmovl %%esp,%%eax\n" );
+ /* Switch to the 16-bit stack */
#ifdef __svr4__
fprintf( outfile,"\tdata16\n");
#endif
fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp+2,%%ss\n" );
fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp,%%sp\n" );
- fprintf( outfile, "\tpushl %%eax\n" );
/* Make %bp point to the previous stackframe (built by CallFrom16) */
fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
fprintf( outfile, "\tleal %d(%%ebp),%%ebp\n",
- STRUCTOFFSET(STACK16FRAME,bp) + 4 /* for saved %%esp */ );
+ STRUCTOFFSET(STACK16FRAME,bp) );
/* Transfer the arguments */
@@ -1931,8 +1924,6 @@
/* Remove the arguments just in case */
fprintf( outfile, PREFIX "CALLTO16_Ret_long:\n" );
- fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
- STRUCTOFFSET(STACK16FRAME,bp) + 4 /* for saved %%esp */ );
/* Put return value into %eax */
@@ -1943,7 +1934,6 @@
/* Restore 32-bit segment registers */
- fprintf( outfile, "\tpopl %%ecx\n" ); /* Get the saved %%esp */
fprintf( outfile, "\tmovw $0x%04x,%%bx\n", Data_Selector );
#ifdef __svr4__
fprintf( outfile, "\tdata16\n");
@@ -1960,7 +1950,8 @@
fprintf( outfile, "\tdata16\n");
#endif
fprintf( outfile, "\tmovw %%bx,%%ss\n" );
- fprintf( outfile, "\tmovl %%ecx,%%esp\n" );
+ fprintf( outfile, "\tmovl " PREFIX "CALLTO16_Saved32_esp,%%esp\n" );
+ fprintf( outfile, "\tpopl " PREFIX "IF1632_Saved16_ss_sp\n" );
/* Restore the 32-bit registers */
@@ -2216,8 +2207,8 @@
fprintf( outfile, "/* Argument strings */\n" );
for (i = 2; i < argc; i++)
{
- fprintf( outfile, "Profile_%s:\n", argv[i] );
- fprintf( outfile, "\t.string \"%s\\0\"\n", argv[i] + 5 );
+ fprintf( outfile, "Profile_%s:\t", argv[i] );
+ fprintf( outfile, STRING " \"%s\\0\"\n", argv[i] + 5 );
}
}
diff --git a/tools/ipcl b/tools/ipcl
index 7a066d5..8cb6901 100644
--- a/tools/ipcl
+++ b/tools/ipcl
@@ -7,7 +7,7 @@
$IPC_RMID=0;
$USER=$ENV{USER};
-do open_pipe(IPCS,"ipcs");
+open(IPCS,"ipcs|");
#
# The following part is OS dependant, it works under linux only.
@@ -60,33 +60,3 @@
foreach (@msq) {
msgctl($_, $IPC_RMID,0);
}
-
-exit(0);
-
-
-
-
-
-sub open_pipe {
- local($pid);
- local($handle,@params)=@_;
- pipe($handle,WRITE) || die "can't pipe";
-
- $pid=fork();
-
- die "can't fork" if ($pid<0);
- if ($pid>0) {
- # whe are in the parent
- close(WRITE);
- waitpid($pid,0) || print "$params[0] exits status=$? ",$? >> 8, "\n";
- } else {
- # we are in the son.
- open(STDOUT,">&WRITE");
- open(STDERR, ">&WRITE");
- close($handle);
- close(WRITE);
- exec(@params);
- exit(-1);
- }
-
-}
diff --git a/win32/environment.c b/win32/environment.c
index 65ad44d..0680d1e 100644
--- a/win32/environment.c
+++ b/win32/environment.c
@@ -13,7 +13,7 @@
#include "task.h"
#include "stddebug.h"
#include "debug.h"
-#include "process.h" /* for pCurrentProcess */
+#include "process.h" /* for PROCESS_Current() */
/***********************************************************************
@@ -21,7 +21,7 @@
*/
LPCSTR WINAPI GetCommandLine32A(void)
{
- return pCurrentProcess->env_db->cmd_line;
+ return PROCESS_Current()->env_db->cmd_line;
}
/***********************************************************************
diff --git a/win32/except.c b/win32/except.c
index 149d32f..0feae88 100644
--- a/win32/except.c
+++ b/win32/except.c
@@ -188,12 +188,13 @@
DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
{
char message[80];
+ PDB32 *pdb = PROCESS_Current();
/* FIXME: Should check if the process is being debugged */
- if (pCurrentProcess && pCurrentProcess->top_filter)
+ if (pdb->top_filter)
{
- DWORD ret = pCurrentProcess->top_filter( epointers );
+ DWORD ret = pdb->top_filter( epointers );
if (ret != EXCEPTION_CONTINUE_SEARCH) return ret;
}
@@ -213,7 +214,8 @@
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER filter )
{
- LPTOP_LEVEL_EXCEPTION_FILTER old = pCurrentProcess->top_filter;
- pCurrentProcess->top_filter = filter;
+ PDB32 *pdb = PROCESS_Current();
+ LPTOP_LEVEL_EXCEPTION_FILTER old = pdb->top_filter;
+ pdb->top_filter = filter;
return old;
}
diff --git a/win32/kernel32.c b/win32/kernel32.c
index 0a651c7..ea78c82 100644
--- a/win32/kernel32.c
+++ b/win32/kernel32.c
@@ -161,23 +161,22 @@
*/
VOID WINAPI QT_Thunk(CONTEXT *context)
{
- CONTEXT context16;
- DWORD argsize;
+ CONTEXT context16;
+ DWORD argsize;
- memcpy(&context16,context,sizeof(context16));
+ memcpy(&context16,context,sizeof(context16));
- CS_reg(&context16) = HIWORD(EDX_reg(context));
- IP_reg(&context16) = LOWORD(EDX_reg(context));
+ CS_reg(&context16) = HIWORD(EDX_reg(context));
+ IP_reg(&context16) = LOWORD(EDX_reg(context));
+ EBP_reg(&context16) = OFFSETOF(IF1632_Saved16_ss_sp)
+ + (WORD)&((STACK16FRAME*)0)->bp;
- argsize = EBP_reg(context)-ESP_reg(context)-0x44;
+ argsize = EBP_reg(context)-ESP_reg(context)-0x44;
- /* additional 4 bytes used by the relaycode for storing the stackptr */
- memcpy( ((LPBYTE)CURRENT_STACK16)-argsize-4,
- (LPBYTE)ESP_reg(context)+4,
- argsize
- );
- EAX_reg(context) = Callbacks->CallRegisterShortProc(&context16,
- -argsize);
+ memcpy( ((LPBYTE)CURRENT_STACK16)-argsize,
+ (LPBYTE)ESP_reg(context)+4, argsize );
+
+ EAX_reg(context) = Callbacks->CallRegisterShortProc( &context16, argsize );
}
@@ -569,7 +568,7 @@
*x++=0x66;*x++=0x52; /* pushl edx */
*x++=0xea;*(DWORD*)x=callback;x+=4; /* jmpf callback */
- *(PDB32**)(thunk+18) = pCurrentProcess;
+ *(PDB32**)(thunk+18) = PROCESS_Current();
sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
return (sel<<16)|0;
diff --git a/win32/newfns.c b/win32/newfns.c
index 1ef72e5..bc40e49 100644
--- a/win32/newfns.c
+++ b/win32/newfns.c
@@ -8,7 +8,10 @@
at a later date. */
#include <stdio.h>
+#include <sys/time.h>
+#include <unistd.h>
#include "windows.h"
+#include "winnt.h"
#include "winerror.h"
#include "stddebug.h"
#include "debug.h"
@@ -37,16 +40,18 @@
return TRUE;
}
+
/****************************************************************************
* QueryPerformanceCounter (KERNEL32.564)
*/
BOOL32 WINAPI QueryPerformanceCounter(LPLARGE_INTEGER counter)
{
- /* FIXME: don't know what are good values */
- counter->LowPart = 0;
- counter->HighPart = 0;
- /* FIXME: Set appropriate error */
- return FALSE;
+ struct timeval tv;
+
+ gettimeofday(&tv,NULL);
+ counter->LowPart = tv.tv_usec+tv.tv_sec*1000000;
+ counter->HighPart = 0;
+ return TRUE;
}
HANDLE32 WINAPI FindFirstChangeNotification32A(LPCSTR lpPathName,BOOL32 bWatchSubtree,DWORD dwNotifyFilter) {
@@ -66,11 +71,9 @@
*/
BOOL32 WINAPI QueryPerformanceFrequency(LPLARGE_INTEGER frequency)
{
- /* FIXME: don't know what are good values */
- frequency->LowPart = 0;
+ frequency->LowPart = 1000000;
frequency->HighPart = 0;
- /* FIXME: Set appropriate error */
- return FALSE;
+ return TRUE;
}
/****************************************************************************
diff --git a/win32/ordinals.c b/win32/ordinals.c
index 56d2f9f..a27fdd5 100644
--- a/win32/ordinals.c
+++ b/win32/ordinals.c
@@ -52,11 +52,7 @@
fprintf(stderr,"KERNEL32_18(%ld,%ld+0x38)\n",processid,action);
if (action>56)
return 0;
- if (!processid) {
- process=pCurrentProcess;
- /* check if valid process */
- } else
- process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */
+ if (!(process = PROCESS_IdToPDB( processid ))) return 0;
switch (action) {
case 0: /* return app compat flags */
pTask = (TDB*)GlobalLock16(process->task);
diff --git a/windows/clipboard.c b/windows/clipboard.c
index 7a262bd..a6a072e 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -871,13 +871,24 @@
/**************************************************************************
- * GetPriorityClipboardFormat32 (USER32
+ * GetPriorityClipboardFormat32 (USER32.279)
*/
INT32 WINAPI GetPriorityClipboardFormat32( UINT32 *lpPriorityList, INT32 nCount )
{
- fprintf( stderr, "GetPriorityClipboardFormat32(%p, %d): stub\n",
- lpPriorityList, nCount );
- return 0;
+ int Counter;
+
+ if(CountClipboardFormats32() == 0)
+ {
+ return 0;
+ }
+
+ for(Counter = 0; Counter <= nCount; Counter++)
+ {
+ if(IsClipboardFormatAvailable32(*(lpPriorityList+sizeof(INT32)*Counter)))
+ return *(lpPriorityList+sizeof(INT32)*Counter);
+ }
+
+ return -1;
}
diff --git a/windows/painting.c b/windows/painting.c
index eeb1c78..fba790b 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -340,6 +340,15 @@
if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+ /* restrict update region to client area (FIXME: correct?) */
+ if (wndPtr->hrgnUpdate)
+ {
+ HRGN32 clientRgn = CreateRectRgnIndirect32( &rectClient );
+ rgnNotEmpty = CombineRgn32( wndPtr->hrgnUpdate, clientRgn,
+ wndPtr->hrgnUpdate, RGN_AND );
+ DeleteObject32( clientRgn );
+ }
+
/* check for bogus update region */
if ( rgnNotEmpty == NULLREGION )
{
diff --git a/windows/win.c b/windows/win.c
index c8ac1c4..69f88b4 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -2128,7 +2128,7 @@
*/
BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
{
- THDB *tdb = (THDB*)id;
+ THDB *tdb = THREAD_ID_TO_THDB(id);
return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
}