From 0623a6f3cfa0938288f329396662a97ecd14ce9f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 18 Jan 1998 18:01:49 +0000 Subject: [PATCH] Release 980118 Sun Jan 18 17:05:58 1998 Alexandre Julliard * [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 * [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 * [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 * [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 to avoid parse error on Solaris. Sun Jan 4 15:38:07 1998 Andrew Taylor * [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 * [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. --- ANNOUNCE | 16 +- ChangeLog | 112 +- Make.rules.in | 2 +- configure | 187 ++- configure.in | 44 +- controls/menu.c | 2 +- debugger/break.c | 4 +- debugger/hash.c | 2 +- files/drive.c | 2 +- graphics/ddraw.c | 642 +++++--- graphics/metafiledrv/graphics.c | 15 + graphics/metafiledrv/init.c | 2 +- graphics/x11drv/clipping.c | 47 +- graphics/x11drv/graphics.c | 19 +- if1632/relay.c | 60 +- if1632/thunk.c | 5 +- include/acconfig.h | 12 + include/config.h.in | 15 +- include/ddraw.h | 13 +- include/dsound.h | 30 + include/k32obj.h | 2 +- include/metafile.h | 2 +- include/metafiledrv.h | 1 + include/options.h | 1 - include/process.h | 12 +- include/region.h | 377 ++++- include/stackframe.h | 51 +- include/thread.h | 19 +- include/version.h | 2 +- include/windows.h | 2 + loader/main.c | 10 +- loader/module.c | 2 +- loader/ne_image.c | 4 +- loader/pe_image.c | 12 +- loader/pe_resource.c | 2 +- loader/task.c | 39 +- memory/atom.c | 21 +- memory/global.c | 8 +- memory/selector.c | 3 +- memory/virtual.c | 4 +- misc/lstr.c | 22 +- misc/main.c | 7 - misc/port.c | 33 + misc/registry.c | 21 +- misc/ver.c | 7 +- misc/version.c | 8 +- msdos/int2f.c | 19 + multimedia/Makefile.in | 1 + multimedia/audio.c | 76 +- multimedia/dsound.c | 369 ++++- multimedia/mmio.c | 674 ++++++++ multimedia/mmsystem.c | 364 ----- objects/bitmap.c | 3 - objects/clipping.c | 5 +- objects/cursoricon.c | 13 + objects/dib.c | 5 + objects/metafile.c | 205 ++- objects/region.c | 2535 ++++++++++++++++++++++++++----- programs/notepad/En.rc | 16 +- programs/notepad/notepad.rc | 10 +- relay32/builtin32.c | 5 +- relay32/gdi32.spec | 2 +- relay32/relay386.c | 25 +- relay32/user32.spec | 2 +- relay32/wow32.spec | 10 +- scheduler/Makefile.in | 1 + scheduler/critsection.c | 13 +- scheduler/event.c | 5 +- scheduler/mutex.c | 80 +- scheduler/process.c | 326 ++-- scheduler/semaphore.c | 5 +- scheduler/synchro.c | 6 +- scheduler/sysdeps.c | 121 ++ scheduler/thread.c | 85 +- tools/build.c | 115 +- tools/ipcl | 32 +- win32/environment.c | 4 +- win32/except.c | 10 +- win32/kernel32.c | 27 +- win32/newfns.c | 21 +- win32/ordinals.c | 6 +- windows/clipboard.c | 19 +- windows/painting.c | 9 + windows/win.c | 2 +- 84 files changed, 5442 insertions(+), 1687 deletions(-) create mode 100644 multimedia/mmio.c create mode 100644 scheduler/sysdeps.c diff --git a/ANNOUNCE b/ANNOUNCE index aba47d4ebc1..e7555fe30d0 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 @@ Because of lags created by using mirror, this message may reach you before 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 57e6fb2fc30..65a51a78d0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,92 @@ +---------------------------------------------------------------------- +Sun Jan 18 17:05:58 1998 Alexandre Julliard + + * [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 + + * [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 + + * [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 + + * [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 to avoid + parse error on Solaris. + +Sun Jan 4 15:38:07 1998 Andrew Taylor + + * [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 + + * [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 @@ -149,6 +238,13 @@ Mon Dec 22 18:55:19 1997 Marcus Meissner + + * [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 @@ -1232,7 +1328,7 @@ Thu Aug 28 19:30:08 1997 Morten Welinder Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init, GetSysColor16, GetSysColor32. Add support for above colors. -Sun Aug 24 16:22:57 1997 Andrew Taylor +Sun Aug 24 16:22:57 1997 Andrew Taylor * [multimedia/mmsystem.c] Changed mmioDescend to use mmio functions for file I/O, neccessary @@ -1731,7 +1827,7 @@ Wed Jun 11 09:14:20 1997 Alex Korobka * [windows/mdi.c] [windows/win.c] Replaced WCL lists with WIN_BuildWinArray(). -Mon Jun 9 23:51:16 1997 Andrew Taylor +Mon Jun 9 23:51:16 1997 Andrew Taylor * [misc/error.c] [include/windows.h] [if1632/kernel.spec] Implemented LogParamError, LogError functions. @@ -1973,7 +2069,7 @@ Mon Apr 21 13:10:24 1997 Marcus Meissner +Sun Apr 20 17:12:30 1997 Andrew Taylor * [multimedia/audio.c] Fixed some regression bugs. @@ -2309,7 +2405,7 @@ Fri Feb 21 20:37:50 1997 Huw D M Davies * [controls/edit.c] Fix incorrect arg order in LOCAL_Alloc() call. -Fri Feb 21 18:19:17 1997 Andrew Taylor +Fri Feb 21 18:19:17 1997 Andrew Taylor * [multimedia/mmsystem.c] [multimedia/mcistring.c] Fixed bug related to device IDs returned by multimedia @@ -2351,7 +2447,7 @@ Fri Feb 14 00:24:39 1997 Alex Korobka * [msdos/dosmem.c] [memory/global.c] Some changes in DOS memory allocation. -Fri Feb 7 21:46:03 1997 Andrew Taylor +Fri Feb 7 21:46:03 1997 Andrew Taylor * [win32/security.c] Added SID manipulation functions. @@ -3020,7 +3116,7 @@ Sat Dec 7 12:07:07 1996 Andrew Lewycky * [windows/win.c] SetWindowWord(): call SetParent on GWW_HWNDPARENT. -Wed Dec 4 22:03:05 1996 Andrew Taylor +Wed Dec 4 22:03:05 1996 Andrew Taylor * [files/dos_fs.c] Check if buf is NULL before copying string in GetFullPathName32A(). @@ -6870,7 +6966,7 @@ Sat Dec 16 19:39:14 MET 1995 Steffen Moeller * [controls/edit.c] Almost rewrote EDIT_GetLineMsg. -Sat Dec 16 13:51:48 MST 1995 Andrew Taylor +Sat Dec 16 13:51:48 MST 1995 Andrew Taylor * [windows/mdi.c] Fixed MDITile() bug that occurs when 0 windows are present or all @@ -7883,7 +7979,7 @@ Sat Aug 19 01:31:23 1995 Graham Menhennitt * [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 5cc35b76e2b..0006fce46d8 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -18,7 +18,7 @@ SHELL = /bin/sh 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 20417c6d4f8..84d8791c135 100755 --- a/configure +++ b/configure @@ -1990,7 +1990,7 @@ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then 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 <&6 - ac_tr_lib=HAVE_LIB`echo Xxf86dga | sed -e 's/[^a-zA-Z0-9_]/_/g' \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` - cat >> confdefs.h <> 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 < +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 < +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 @@ if test "x${GCC}" = "xyes" 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 @@ else ac_cv_c_gcc_strength_bug="yes" else cat > conftest.$ac_ext <&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 @@ fi 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 @@ _ac_test: .long 0 EOF cat > conftest.$ac_ext <&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 @@ EOF 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 < conftest.$ac_ext <&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 <&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 @@ fi 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 <&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 @@ for ac_hdr in wctype.h 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 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 @@ fi 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 < #include @@ -2317,12 +2430,12 @@ EOF 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 <&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 @@ EOF 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 < #include @@ -2405,7 +2518,7 @@ else #include 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 @@ rm -f conftest* 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 @@ -2440,7 +2553,7 @@ fi 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 @@ -2461,7 +2574,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2472,7 +2585,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); 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 @@ EOF 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 < #if STDC_HEADERS diff --git a/configure.in b/configure.in index abf9119e213..83da896b3d6 100644 --- a/configure.in +++ b/configure.in @@ -51,7 +51,33 @@ AC_CHECK_LIB(i386,i386_set_ldt) 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 ],[ +/* 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 ],[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 @@ then 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 <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 d842f500db8..b332adec752 100644 --- a/debugger/break.c +++ b/debugger/break.c @@ -347,9 +347,7 @@ void DEBUG_AddModuleBreakpoints(void) 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 acf281f0905..ba874736ce1 100644 --- a/debugger/hash.c +++ b/debugger/hash.c @@ -803,7 +803,7 @@ static void DEBUG_LoadEntryPoints32( HMODULE32 hModule, const char *name ) 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 d5a8a86648e..7aca8b61a0f 100644 --- a/files/drive.c +++ b/files/drive.c @@ -949,7 +949,7 @@ BOOL32 WINAPI GetVolumeInformation32A( LPCSTR root, LPSTR label, 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 72486902bb6..d2fd0bd0fbf 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 #include #include +#include #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 @@ HRESULT WINAPI 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 @@ DSoundHelp(DWORD x,DWORD y,DWORD z) { #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;idwFourCC = 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 @@ static int _getpixelformat(LPDIRECTDRAW ddraw,LPDDPIXELFORMAT pf) { 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 int _getpixelformat(LPDIRECTDRAW ddraw,LPDDPIXELFORMAT pf) { 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 IDirectDrawSurface_Lock( 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 IDirectDrawSurface2_Lock( 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; + } +/* 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; } - while (!XF86DGAViewPortChanged(display,DefaultScreen(display),1)) { - } - fprintf(stderr,"flipped to new height %ld\n",flipto->fb_height); 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_BltBatch( 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 IDirectDrawSurface_Release(LPDIRECTDRAWSURFACE this) { } 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 ULONG WINAPI IDirectDrawSurface2_Release(LPDIRECTDRAWSURFACE2 this) { 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 @@ static HRESULT WINAPI IDirectDrawSurface_Initialize( 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 HRESULT WINAPI IDirectDrawSurface2_EnumAttachedSurfaces(LPDIRECTDRAWSURFA } 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 @@ static struct IDirectDrawSurface_VTable ddsvt = { 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<d.vpmask|=(1<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<d.vpmask|=(1<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 IDirectDraw_DuplicateSurface( 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<d.vpmask|=(1<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<d.vpmask|=(1<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;id.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 @@ static HRESULT WINAPI IDirectDraw_SetDisplayMode( 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 HRESULT WINAPI IDirectDraw2_GetCaps( 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 @@ static HRESULT WINAPI IDirectDraw_CreateClipper( 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 @@ static HRESULT WINAPI IDirectDrawPalette_SetEntries( 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;iref); } +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 @@ static HRESULT WINAPI IDirectDraw_CreatePalette( 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 HRESULT WINAPI IDirectDraw_WaitForVerticalBlank( } 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 @@ static IDirectDraw2_VTable dd2vt = { 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 @@ static HRESULT WINAPI IDirectDraw_EnumDisplayModes( 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 @@ static IDirectDraw_VTable ddvt = { 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 @@ HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN 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 @@ HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN (*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 f0fbc020e0e..1647a66dd62 100644 --- a/graphics/metafiledrv/graphics.c +++ b/graphics/metafiledrv/graphics.c @@ -188,3 +188,18 @@ MFDRV_ExtFloodFill( DC *dc, INT32 x, INT32 y, COLORREF color, UINT32 fillType ) { 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 f60fe08c521..c55832a71bf 100644 --- a/graphics/metafiledrv/init.c +++ b/graphics/metafiledrv/init.c @@ -38,7 +38,7 @@ static const DC_FUNCTIONS MFDRV_Funcs = 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 7645e6867ab..d6cbc086a30 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 @@ -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 ); - } - else /* Clip everything */ - { - XSetClipRectangles( display, dc->u.x.gc, 0, 0, NULL, 0, 0 ); + 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 + 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 d6e42e45a99..af3fd94e353 100644 --- a/graphics/x11drv/graphics.c +++ b/graphics/x11drv/graphics.c @@ -440,15 +440,20 @@ X11DRV_PaintRgn( DC *dc, HRGN32 hrgn ) 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 8e247ff0206..6e188bb708d 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -112,8 +112,25 @@ void RELAY_DebugCallFrom16( int func_type, char *args, 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 @@ void RELAY_DebugCallFrom16( int func_type, char *args, 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 @@ void RELAY_DebugCallTo16( int* stack, int nb_args ) 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 @@ void WINAPI Catch( CONTEXT *context ) 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 @@ void WINAPI Throw( CONTEXT *context ) 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 @@ static DWORD RELAY_CallProc32W(int Ex) 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 5bb6eba462c..88b0281f0ab 100644 --- a/if1632/thunk.c +++ b/if1632/thunk.c @@ -240,15 +240,14 @@ static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd, } } - 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 00d85cdad7f..e7ec75b83c8 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 40d489b1265..0f335ec033a 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 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 3197b85730c..26f72accdc3 100644 --- a/include/ddraw.h +++ b/include/ddraw.h @@ -20,6 +20,12 @@ typedef struct IDirectDrawPalette IDirectDrawPalette,*LPDIRECTDRAWPALETTE; 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 @@ typedef struct IDirectDraw_VTable { 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 @@ struct _directdrawdata { 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 @@ struct IDirectDrawSurface { LPDIRECTDRAWPALETTE palette; DWORD fb_height,lpitch,width,height; LPDIRECTDRAW ddraw; + LPDIRECTDRAWSURFACE backbuffer; }; #undef THIS #define THIS LPDIRECTDRAWSURFACE2 this @@ -885,6 +893,7 @@ struct IDirectDrawSurface2 { 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 61d042bb82e..f4d680172d3 100644 --- a/include/dsound.h +++ b/include/dsound.h @@ -14,6 +14,25 @@ DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20, 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 @@ typedef struct IDirectSoundBuffer IDirectSoundBuffer,*LPDIRECTSOUNDBUFFER,**LPLP #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 @@ typedef struct tagLPDIRECTSOUND_VTABLE struct IDirectSound { LPDIRECTSOUND_VTABLE lpvtbl; DWORD ref; + int nrofbuffers; + LPDIRECTSOUNDBUFFER *buffers; }; #undef THIS @@ -181,7 +207,11 @@ typedef struct tagLPDIRECTSOUNDBUFFER_VTABLE 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 afe3c94c1a6..5ac2a5e2380 100644 --- a/include/k32obj.h +++ b/include/k32obj.h @@ -44,7 +44,7 @@ typedef struct 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 b511fced2a9..c6747189284 100644 --- a/include/metafile.h +++ b/include/metafile.h @@ -36,6 +36,6 @@ BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width, 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 a8e67a91c3b..e89d09137cf 100644 --- a/include/metafiledrv.h +++ b/include/metafiledrv.h @@ -72,5 +72,6 @@ extern BOOL32 MFDRV_ExtFloodFill( struct tagDC *dc, INT32 x, INT32 y, 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 c68158e98c0..784614ce93f 100644 --- a/include/options.h +++ b/include/options.h @@ -59,7 +59,6 @@ struct options 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 ca0014f8116..21893dbeeaa 100644 --- a/include/process.h +++ b/include/process.h @@ -98,20 +98,12 @@ typedef struct _PDB32 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 d53546a9bc5..263379b2e37 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 e1cfa773994..1435bbb4d29 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 4e9b61f711a..361d16565e0 100644 --- a/include/thread.h +++ b/include/thread.h @@ -55,9 +55,9 @@ typedef struct _THDB 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 @@ typedef struct _THDB 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 THDB *THREAD_Current(void); 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 bb64ee6ea34..686a913dcaf 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 d9fe47dffec..43a00b8c15c 100644 --- a/include/windows.h +++ b/include/windows.h @@ -5689,6 +5689,7 @@ BOOL32 WINAPI ExitWindowsEx(UINT32,DWORD); 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 GetPrivateProfileSection32A(LPCSTR,LPSTR,INT32,LPCSTR); 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 b596be299e5..767eb10b89c 100644 --- a/loader/main.c +++ b/loader/main.c @@ -48,6 +48,7 @@ int __winelib = 1; /* Winelib run-time flag */ 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 @@ BOOL32 MAIN_KernelInit(void) 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 6cea6c5f200..831a001e52c 100644 --- a/loader/module.c +++ b/loader/module.c @@ -1437,7 +1437,7 @@ HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags) 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 98a8a9c4390..14278c887af 100644 --- a/loader/ne_image.c +++ b/loader/ne_image.c @@ -78,7 +78,7 @@ BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) 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 @@ BOOL32 NE_LoadAllSegments( NE_MODULE *pModule ) 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 043404dbd75..e3f31d47943 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -97,7 +97,7 @@ FARPROC32 PE_FindExportedFunction( HMODULE32 hModule, LPCSTR funcName) 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 @@ HMODULE32 PE_LoadLibraryEx32A (LPCSTR name, HFILE32 hFile, DWORD flags) { 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 @@ HMODULE32 PE_LoadLibraryEx32A (LPCSTR name, HFILE32 hFile, DWORD flags) { 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 @@ HINSTANCE16 PE_LoadModule( HFILE32 hFile, OFSTRUCT *ofs, LOADPARAMS* params ) (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 @@ void PE_InitTls(PDB32 *pdb) */ 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 4e4098cc0e7..60fa5b8b874 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 110a7995869..7c31fae08cb 100644 --- a/loader/task.c +++ b/loader/task.c @@ -56,7 +56,7 @@ static HGLOBAL16 hDOSEnvironment = 0; static HGLOBAL16 TASK_CreateDOSEnvironment(void); static void TASK_YieldToSystem(TDB*); -static THDB TASK_SystemTHDB; + /*********************************************************************** * TASK_Init */ @@ -64,8 +64,6 @@ BOOL32 TASK_Init(void) { 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 @@ static void TASK_CallToStart(void) 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 @@ static void TASK_CallToStart(void) 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 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, /* 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 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, /* 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 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, 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 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, 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 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, 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 @@ void TASK_Reschedule(void) 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 @@ void TASK_Reschedule(void) hCurrentTask = hTask; SET_CUR_THREAD( pNewTask->thdb ); - pCurrentProcess = pNewTask->thdb->process; IF1632_Saved16_ss_sp = pNewTask->ss_sp; } @@ -1197,7 +1194,7 @@ void WINAPI SwitchStackBack(void) /* 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 83d7a4c33c1..dc821620531 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 @@ ATOM WINAPI GlobalAddAtom16( SEGPTR str ) { 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 GlobalAddAtom32W( LPCWSTR str ) 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 @@ ATOM WINAPI GlobalFindAtom16( SEGPTR str ) { 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 @@ ATOM WINAPI GlobalFindAtom32W( LPCWSTR str ) 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 0830c140bf1..ecb6c953f37 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 @@ HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size, 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 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner, /* 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 @@ HGLOBAL16 WINAPI GlobalReAlloc16( HGLOBAL16 handle, DWORD size, UINT16 flags ) 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 410c0d5b7af..28c8a6177bd 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -182,7 +182,8 @@ void SELECTOR_FreeBlock( WORD sel, WORD count ) { 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 9ffde82d361..65f17d439b2 100644 --- a/memory/virtual.c +++ b/memory/virtual.c @@ -660,7 +660,7 @@ BOOL32 WINAPI VirtualProtectEx( HANDLE32 handle, LPVOID addr, DWORD size, 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 @@ BOOL32 WINAPI VirtualQueryEx( HANDLE32 handle, LPCVOID addr, 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 234ec0724ab..1e5452727a2 100644 --- a/misc/lstr.c +++ b/misc/lstr.c @@ -10,16 +10,7 @@ #include #include #include - -#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 @@ -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 cbc551b2938..ca68de18fc8 100644 --- a/misc/main.c +++ b/misc/main.c @@ -81,7 +81,6 @@ struct options Options = FALSE, FALSE, /* failReadOnly */ MODE_ENHANCED, /* Enhanced mode */ - FALSE, /* IPC enabled */ #ifdef DEFAULT_LANG DEFAULT_LANG, /* Default language */ #else @@ -99,7 +98,6 @@ static XrmOptionDescRec optionsTable[] = { "-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 @@ static XrmOptionDescRec optionsTable[] = " -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 @@ static void MAIN_ParseOptions( int *argc, char *argv[] ) 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 @@ BOOL32 MAIN_WineInit( int *argc, char *argv[] ) 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 f98a95181d2..657450e2ac5 100644 --- a/misc/port.c +++ b/misc/port.c @@ -57,3 +57,36 @@ const char *strerror( int err ) return sys_errlist[err]; } #endif /* HAVE_STRERROR */ + +#if !defined(HAVE_CLONE) && defined(__linux__) +#include +#include +#include +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 90e233cecdd..9aa04cece2f 100644 --- a/misc/registry.c +++ b/misc/registry.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "windows.h" #include "win.h" @@ -587,6 +588,11 @@ _find_or_add_value( LPKEYVALUE val=NULL; int i; + if (name && !*name) {/* empty string equals default (NULL) value */ + free(name); + name = NULL; + } + for (i=0;inrofvalues;i++) { val=lpkey->values+i; if (name==NULL) { @@ -711,7 +717,10 @@ _wine_read_USTRING(char *buf,LPWSTR *str) { } *ws = 0; ws = *str; - *str = strdupW(*str); + if (*ws) + *str = strdupW(*str); + else + *str = NULL; free(ws); return s; } @@ -1038,7 +1047,10 @@ _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) { 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 @@ DWORD WINAPI RegQueryValueEx32W( lpkey = lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; + if (lpszValueName && !*lpszValueName) + lpszValueName = NULL; if (lpszValueName==NULL) { for (i=0;inrofvalues;i++) if (lpkey->values[i].name==NULL) @@ -2726,9 +2740,8 @@ DWORD WINAPI RegEnumValue32W( 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 40c3241b0f6..c19e5f3390d 100644 --- a/misc/ver.c +++ b/misc/ver.c @@ -168,7 +168,7 @@ static int testFileExclusiveExistence( 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 @@ static int read_xx_header(HFILE32 lzfd) { 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 @@ DWORD WINAPI VerFindFile16( 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 dafa443c273..e62438e2e6e 100644 --- a/misc/version.c +++ b/misc/version.c @@ -114,17 +114,15 @@ static VERSION VERSION_GetVersion(void) 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 755e05bfa09..c8efcab1059 100644 --- a/msdos/int2f.c +++ b/msdos/int2f.c @@ -41,6 +41,25 @@ void WINAPI INT_Int2fHandler( CONTEXT *context ) 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 f4a288fd43e..cc7446dd24c 100644 --- a/multimedia/Makefile.in +++ b/multimedia/Makefile.in @@ -15,6 +15,7 @@ C_SRCS = \ midi.c \ mixer.c \ mmaux.c \ + mmio.c \ mmsystem.c \ time.c diff --git a/multimedia/audio.c b/multimedia/audio.c index 58d8365497b..8abae8c570e 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 -#elif __FreeBSD__ -#include -#endif - #include "stddebug.h" #include "debug.h" -#if defined(linux) || defined(__FreeBSD__) +#ifdef HAVE_OSS +#include + #define SOUND_DEV "/dev/dsp" #define MIXER_DEV "/dev/mixer" @@ -62,7 +57,7 @@ typedef struct { 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 @@ static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpPar 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 @@ static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS16 lpCaps, DWORD dwSize) #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 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam) return MMSYSERR_NOERROR; } -#endif /* linux || __FreeBSD__*/ - /************************************************************************** * wodMessage [sample driver] */ @@ -1223,7 +1216,6 @@ DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, { 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 @@ DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 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 @@ static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS16 lpCaps, DWORD dwSize) #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 @@ dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n", return MMSYSERR_NOERROR; } -#endif /* linux || __FreeBSD__ */ - /************************************************************************** * widMessage [sample driver] */ @@ -1698,7 +1683,6 @@ DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, { 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 @@ DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, dprintf_mciwave(stddeb,"widMessage // unknown message !\n"); } return MMSYSERR_NOTSUPPORTED; -#else - return MMSYSERR_NOTENABLED; -#endif } @@ -1740,7 +1721,6 @@ DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 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 @@ LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 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 5b3983b7fdc..fafa9599ff6 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 +#include +#include +#include +#include +#include +#include +#include +#include #include "windows.h" +#include "winerror.h" #include "interfaces.h" #include "mmsystem.h" #include "dsound.h" +#ifdef HAVE_OSS +#include +#include +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;iSetFormat(%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_SetFrequency( } 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;idsound->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 DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) { 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 @@ static HRESULT WINAPI IDirectSoundBuffer_GetStatus( 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 @@ static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = { IDirectSoundBuffer_Release, (void *)4, IDirectSoundBuffer_GetCurrentPosition, - (void *)6, + IDirectSoundBuffer_GetFormat, IDirectSoundBuffer_GetVolume, (void *)8, (void *)9, @@ -104,13 +292,13 @@ static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = { (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_SetCooperativeLevel( 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 @@ static struct tagLPDIRECTSOUND_VTABLE dsvt = { IDirectSound_Release, IDirectSound_CreateSoundBuffer, IDirectSound_GetCaps, - (void *)6, + IDirectSound_DuplicateSoundBuffer, IDirectSound_SetCooperativeLevel, (void *)8, (void *)9, @@ -168,10 +399,98 @@ static struct tagLPDIRECTSOUND_VTABLE dsvt = { (void *)11 }; -HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) { - fprintf(stderr,"DirectSoundCreate(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter); - *ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound)); - (*ppDS)->ref = 1; - (*ppDS)->lpvtbl = &dsvt; - return 0; +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;jbuffers[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)->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 00000000000..d140fe1c706 --- /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 +#include +#include +#include +#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 ad9d211689e..4f1e47cd8ec 100644 --- a/multimedia/mmsystem.c +++ b/multimedia/mmsystem.c @@ -3646,370 +3646,6 @@ DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage, return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2); } -/************************************************************************** - * 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] */ diff --git a/objects/bitmap.c b/objects/bitmap.c index 4092719c410..3290ae7e07b 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 d417c71e4af..7f9acb2e91d 100644 --- a/objects/clipping.c +++ b/objects/clipping.c @@ -505,6 +505,8 @@ INT16 WINAPI RestoreVisRgn( HDC16 hdc ) 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 @@ INT16 WINAPI RestoreVisRgn( HDC16 hdc ) 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 2ec3b5961bb..a7e77c4da70 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 @@ void WINAPI GetCursorPos16( POINT16 *pt ) { 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 0f1ef173121..89556249964 100644 --- a/objects/dib.c +++ b/objects/dib.c @@ -1420,6 +1420,8 @@ HBITMAP32 WINAPI CreateDIBSection32 (HDC32 hdc, BITMAPINFO *bmi, UINT32 usage, 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 @@ HBITMAP32 WINAPI CreateDIBSection32 (HDC32 hdc, BITMAPINFO *bmi, UINT32 usage, { /* 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 373c8515891..9fabc7c3e6f 100644 --- a/objects/metafile.c +++ b/objects/metafile.c @@ -8,6 +8,7 @@ #include #include +#include "windows.h" #include "gdi.h" #include "bitmap.h" #include "file.h" @@ -233,16 +234,15 @@ BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf) /****************************************************************** - * 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 @@ BOOL32 WINAPI PlayMetaFile32( HDC32 hdc, HMETAFILE32 hmf ) 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 @@ BOOL32 WINAPI PlayMetaFile32( HDC32 hdc, HMETAFILE32 hmf ) 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 @@ BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf, return TRUE; } +static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn ); /****************************************************************** * PlayMetaFileRecord16 (GDI.176) @@ -380,8 +381,9 @@ void WINAPI PlayMetaFileRecord16( HDC16 hdc, HANDLETABLE16 *ht, METARECORD *mr, 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 @@ void WINAPI PlayMetaFileRecord16( HDC16 hdc, HANDLETABLE16 *ht, METARECORD *mr, case META_SETSTRETCHBLTMODE: SetStretchBltMode16(hdc, *(mr->rdParam)); break; + case META_SETTEXTCOLOR: SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1))); break; @@ -732,23 +735,13 @@ void WINAPI PlayMetaFileRecord16( HDC16 hdc, HANDLETABLE16 *ht, METARECORD *mr, /* --- 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)), @@ -860,6 +853,79 @@ HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta ) return (HMETAFILE16)0; } +/****************************************************************** + * 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 * @@ -1389,3 +1455,88 @@ BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest, } +/****************************************************************** + * 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 c68686f08b7..a26cb967fb3 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 +/************************************************************************ + +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 #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 @@ INT16 WINAPI OffsetRgn16( HRGN16 hrgn, INT16 x, INT16 y ) return OffsetRgn32( hrgn, x, y ); } - /*********************************************************************** * OffsetRgn32 (GDI32.256) */ @@ -43,14 +195,24 @@ INT32 WINAPI OffsetRgn32( HRGN32 hrgn, INT32 x, INT32 y ) 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 @@ INT32 WINAPI OffsetRgn32( HRGN32 hrgn, INT32 x, INT32 y ) */ 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 @@ HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom) 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 @@ HRGN32 WINAPI CreateRectRgnIndirect32( const RECT32* rect ) * 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 @@ VOID WINAPI SetRectRgn16( HRGN16 hrgn, INT16 left, INT16 top, * 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 @@ VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top, 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 @@ VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top, * 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 @@ HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top, 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 @@ HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top, 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 @@ HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top, * 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 @@ HRGN16 WINAPI CreateEllipticRgn16( INT16 left, INT16 top, * 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 @@ HRGN32 WINAPI CreateEllipticRgn32( INT32 left, INT32 top, 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 @@ HRGN16 WINAPI CreateEllipticRgnIndirect16( const RECT16 *rect ) 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 @@ BOOL32 WINAPI PtInRegion32( HRGN32 hrgn, INT32 x, INT32 y ) 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 @@ BOOL32 WINAPI PtInRegion32( HRGN32 hrgn, INT32 x, INT32 y ) */ 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 @@ BOOL32 WINAPI RectInRegion32( HRGN32 hrgn, const RECT32 *rect ) 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 @@ BOOL16 WINAPI EqualRgn16( HRGN16 rgn1, HRGN16 rgn2 ) /*********************************************************************** * 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 @@ BOOL32 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y ) 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 @@ INT32 WINAPI CombineRgn32(HRGN32 hDest, HRGN32 hSrc1, HRGN32 hSrc2, INT32 mode) 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); - return 0; +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 e4ebc9ef67a..01b24aeb8ee 100644 --- a/programs/notepad/En.rc +++ b/programs/notepad/En.rc @@ -2,7 +2,7 @@ * Notepad (English resources) * * Copyright 1997 Marcel Baur - * FIXME: See TODO about how to fix weak translations. + * Proofread 1998 by David Lee Lambert */ #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 @@ memory." #include "notepad.rc" + + + + diff --git a/programs/notepad/notepad.rc b/programs/notepad/notepad.rc index c3d4748622d..5a438de868f 100644 --- a/programs/notepad/notepad.rc +++ b/programs/notepad/notepad.rc @@ -51,10 +51,12 @@ CONCAT(MENU_, LANGUAGE_ID) MENU 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 764acad4f80..01f9a7d3ed3 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -120,6 +120,7 @@ static HMODULE32 BUILTIN32_DoLoadModule( BUILTIN32_DLL *dll ) DEBUG_ENTRY_POINT *debug; REG_ENTRY_POINT *regs; PE_MODREF *pem; + PDB32 *pdb = PROCESS_Current(); INT32 i, size; BYTE *addr; @@ -278,8 +279,8 @@ static HMODULE32 BUILTIN32_DoLoadModule( BUILTIN32_DLL *dll ) 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 fad209fcc34..b6c5bea8007 100644 --- a/relay32/gdi32.spec +++ b/relay32/gdi32.spec @@ -98,7 +98,7 @@ type win32 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 752a582543e..1b5f706daf0 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 @@ int RELAY_CallFrom32( int ret_addr, ... ) { 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 ", args[i] ); + _dumpstr((unsigned char*)args[i]); } - else printf( "%08x \"%s\"", args[i], (char *)args[i] ); } else printf( "%08x", args[i] ); } diff --git a/relay32/user32.spec b/relay32/user32.spec index 06ce2b16254..5fdddb222e6 100644 --- a/relay32/user32.spec +++ b/relay32/user32.spec @@ -281,7 +281,7 @@ type win32 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 4a37728335c..c60e58ddbfa 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 632f0467f53..178d43ab526 100644 --- a/scheduler/Makefile.in +++ b/scheduler/Makefile.in @@ -13,6 +13,7 @@ C_SRCS = \ process.c \ semaphore.c \ synchro.c \ + sysdeps.c \ thread.c all: $(MODULE).o diff --git a/scheduler/critsection.c b/scheduler/critsection.c index 7f5c5b95cb8..dc91651b09b 100644 --- a/scheduler/critsection.c +++ b/scheduler/critsection.c @@ -28,9 +28,17 @@ typedef struct 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 @@ static BOOL32 CRIT_SECTION_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 4eb5e0c4dc5..0b578ba817b 100644 --- a/scheduler/event.c +++ b/scheduler/event.c @@ -21,7 +21,7 @@ typedef struct } 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 @@ static BOOL32 EVENT_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 737789a3caa..aebf9a6d6f3 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 ); @@ -36,6 +39,40 @@ const K32OBJ_OPS MUTEX_Ops = }; +/*********************************************************************** + * 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) */ @@ -52,18 +89,27 @@ HANDLE32 WINAPI CreateMutex32A( SECURITY_ATTRIBUTES *sa, BOOL32 owner, { /* 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 @@ BOOL32 WINAPI ReleaseMutex( HANDLE32 handle ) 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 @@ static BOOL32 MUTEX_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 225dd143457..d42f3f3c5e7 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 @@ const K32OBJ_OPS PROCESS_Ops = PROCESS_Destroy /* destroy */ }; -static HANDLE_ENTRY boot_handles[BOOT_HTABLE_SIZE]; /*********************************************************************** * PROCESS_AllocHandleTable @@ -79,83 +79,31 @@ static BOOL32 PROCESS_GrowHandleTable( PDB32 *process ) /*********************************************************************** - * 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 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags ) { 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 @@ HANDLE32 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags ) 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 PROCESS_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags ) { 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 WINAPI CloseHandle( HANDLE32 handle ) { 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 @@ error: /*********************************************************************** - * 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 @@ PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line ) 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 @@ PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line ) 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 @@ PDB32 *PROCESS_Create( TDB *pTask, LPCSTR cmd_line ) 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 @@ static BOOL32 PROCESS_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 @@ static void PROCESS_Destroy( K32OBJ *ptr ) /* 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 @@ static void PROCESS_Destroy( K32OBJ *ptr ) */ 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 @@ HANDLE32 WINAPI OpenProcess( DWORD access, BOOL32 inherit, DWORD id ) */ DWORD WINAPI GetCurrentProcessId(void) { - return PDB_TO_PROCESS_ID(pCurrentProcess); + PDB32 *pdb = PROCESS_Current(); + return PDB_TO_PROCESS_ID( pdb ); } @@ -523,8 +519,8 @@ DWORD WINAPI GetCurrentProcessId(void) */ LPSTR WINAPI GetEnvironmentStrings32A(void) { - assert( pCurrentProcess ); - return pCurrentProcess->env_db->environ; + PDB32 *pdb = PROCESS_Current(); + return pdb->env_db->environ; } @@ -536,12 +532,12 @@ LPWSTR WINAPI GetEnvironmentStrings32W(void) 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 @@ LPWSTR WINAPI GetEnvironmentStrings32W(void) */ 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 FreeEnvironmentStrings32A( LPSTR ptr ) */ BOOL32 WINAPI FreeEnvironmentStrings32W( LPWSTR ptr ) { - assert( pCurrentProcess ); return HeapFree( GetProcessHeap(), 0, ptr ); } @@ -588,8 +583,7 @@ DWORD WINAPI GetEnvironmentVariable32A( LPCSTR name, LPSTR value, DWORD size ) 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 @@ BOOL32 WINAPI SetEnvironmentVariable32A( LPCSTR name, LPCSTR value ) { 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 @@ BOOL32 WINAPI SetEnvironmentVariable32A( LPCSTR name, LPCSTR value ) 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 @@ BOOL32 WINAPI SetEnvironmentVariable32A( LPCSTR name, LPCSTR value ) 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 @@ DWORD WINAPI ExpandEnvironmentStrings32W( LPCWSTR src, LPWSTR dst, DWORD len) */ 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 @@ HANDLE32 WINAPI GetProcessHeap(void) */ LCID WINAPI GetThreadLocale(void) { - return pCurrentProcess->locale; + return PROCESS_Current()->locale; } @@ -890,23 +882,20 @@ HANDLE32 WINAPI GetStdHandle( DWORD std_handle ) { 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 @@ HANDLE32 WINAPI GetStdHandle( DWORD std_handle ) 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 @@ HANDLE32 WINAPI GetStdHandle( DWORD std_handle ) */ 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 @@ BOOL32 WINAPI SetStdHandle( DWORD std_handle, HANDLE32 handle ) */ 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 d8c1535a4eb..d6cfd49cc98 100644 --- a/scheduler/semaphore.c +++ b/scheduler/semaphore.c @@ -21,7 +21,7 @@ typedef struct } 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 @@ static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 20002179c8d..85779927678 100644 --- a/scheduler/synchro.c +++ b/scheduler/synchro.c @@ -88,7 +88,8 @@ static BOOL32 SYNC_CheckCondition( WAIT_STRUCT *wait, DWORD thread_id ) /* 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 @@ static BOOL32 SYNC_CheckCondition( WAIT_STRUCT *wait, DWORD thread_id ) { /* 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 00000000000..08c4dc370ec --- /dev/null +++ b/scheduler/sysdeps.c @@ -0,0 +1,121 @@ +/* + * System-dependent scheduler support + * + * Copyright 1998 Alexandre Julliard + */ + +#include +#include +#include +#include "thread.h" + +#ifdef __linux__ +# ifdef HAVE_SCHED_H +# include +# 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 73959d025ad..984b89c6fc1 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 -# 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 @@ static THDB *THREAD_GetPtr( HANDLE32 handle ) } -/********************************************************************** - * 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 *THREAD_Create( PDB32 *pdb, DWORD stack_size, 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; @@ -233,20 +195,6 @@ error: } -/*********************************************************************** - * 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 */ @@ -263,7 +211,7 @@ static BOOL32 THREAD_Signaled( K32OBJ *obj, DWORD thread_id ) * * 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 @@ HANDLE32 WINAPI CreateThread( LPSECURITY_ATTRIBUTES attribs, DWORD stack, 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 @@ void WINAPI ExitThread( DWORD code ) 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 ad4db7464de..1cc07e7c0e6 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 @@ static int BuildSpec16File( char * specfile, FILE *outfile ) /* 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 @@ static int TransferArgs16To32( FILE *outfile, char *args ) { 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 @@ static int TransferArgs16To32( FILE *outfile, char *args ) } } - /* Restore ebx */ - - fprintf( outfile, "\tpopl %%ebx\n" ); - return pos16 - 6; /* Return the size of the 16-bit args */ } @@ -1370,18 +1364,8 @@ static int TransferArgs16To32( FILE *outfile, char *args ) */ 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 @@ static void BuildContext16( FILE *outfile ) 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 @@ static void RestoreContext16( FILE *outfile ) { /* 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 @@ static void RestoreContext16( FILE *outfile ) * * 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 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile ) /* 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 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile ) 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 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile ) 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 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile ) #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 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile ) * 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 @@ static void BuildCallTo16Func( FILE *outfile, char *profile ) 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 @@ static void BuildCallTo16Func( FILE *outfile, char *profile ) 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 @@ static void BuildCallTo16Func( FILE *outfile, char *profile ) { 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 @@ static void BuildRet16Func( FILE *outfile ) /* 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 @@ static void BuildRet16Func( FILE *outfile ) /* 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 @@ static void BuildRet16Func( FILE *outfile ) 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 @@ static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[ 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 7a066d5ef3c..8cb69019025 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 (@sem) { 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 65ad44d4e15..0680d1ee8bd 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 149d32f6f1b..0feae88fd50 100644 --- a/win32/except.c +++ b/win32/except.c @@ -188,12 +188,13 @@ void EXC_RaiseException( CONTEXT *context ) 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 @@ DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers) 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 0a651c79e1f..ea78c82ee2d 100644 --- a/win32/kernel32.c +++ b/win32/kernel32.c @@ -161,23 +161,22 @@ UINT32 WINAPI ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16, */ 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 @@ AllocSLCallback(DWORD finalizer,DWORD callback) { *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 1ef72e5f02d..bc40e49c53a 100644 --- a/win32/newfns.c +++ b/win32/newfns.c @@ -8,7 +8,10 @@ at a later date. */ #include +#include +#include #include "windows.h" +#include "winnt.h" #include "winerror.h" #include "stddebug.h" #include "debug.h" @@ -37,16 +40,18 @@ BOOL32 WINAPI UTUnRegister(HMODULE32 hModule) 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 FindNextChangeNotification(HANDLE32 fcnhandle) { */ 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 56d2f9f3f6f..a27fdd57d37 100644 --- a/win32/ordinals.c +++ b/win32/ordinals.c @@ -52,11 +52,7 @@ DWORD WINAPI _KERNEL32_18(DWORD processid,DWORD action) 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 7a262bdd22d..a6a072e2f36 100644 --- a/windows/clipboard.c +++ b/windows/clipboard.c @@ -871,13 +871,24 @@ INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount) /************************************************************************** - * 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 eeb1c7867ce..fba790bde24 100644 --- a/windows/painting.c +++ b/windows/painting.c @@ -340,6 +340,15 @@ BOOL32 PAINT_RedrawWindow( HWND32 hwnd, const RECT32 *rectUpdate, 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 c8ac1c444ce..69f88b4effc 100644 --- a/windows/win.c +++ b/windows/win.c @@ -2128,7 +2128,7 @@ BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, */ 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); }