diff --git a/ANNOUNCE b/ANNOUNCE index a999ecdc744..38e3e596b2b 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,13 +1,15 @@ -This is release 961117 of Wine, the MS Windows emulator. This is still a +This is release 961201 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-961117: (see ChangeLog for details) - - More Win32 functions. - - OffiX-style drag and drop. +WHAT'S NEW with Wine-961201: (see ChangeLog for details) + - Better Winsock. + - Rewritten listboxes. + - Windows 3.1 registry loader. + - Improved keyboard support. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -16,10 +18,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-961117.tar.gz - ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-961117.tar.gz - ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-961117.tar.gz - ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-961117.tar.gz + ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-961201.tar.gz + ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-961201.tar.gz + ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-961201.tar.gz + ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-961201.tar.gz It should also be available from any site that mirrors tsx-11 or sunsite. diff --git a/ChangeLog b/ChangeLog index d848a918db8..0ef8d3345c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,109 @@ +---------------------------------------------------------------------- +Sat Nov 30 19:21:17 1996 Alexandre Julliard + + * [configure] + Re-generated with autoconf 2.11. Let me know if you have + problems. + + * [controls/listbox.c] [controls/oldlbox.c] + Listboxes rewritten from scratch. Moved old code still used by + comboboxes to oldlbox.c + + * [misc/registry.c] + Use temporary file when saving registry. + + * [windows/dialog.c] + Implemented Win32 version of DlgDirList() and DlgDirListComboBox(). + + * [windows/winproc.c] + Added translation for listbox Win32 messages. + +Sat Nov 30 21:00:00 Alex Korobka + + * [controls/widgets.c] [controls/button.c] + Fixed some incompatibilities with CTL3D DLL. + + * [windows/dialog.c] + Made dialog windows fit into the desktop. + + * [misc/winsock.c] [misc/winsock_async.c] + New Winsock engine. + + * [windows/message.c] + GetMessage() fixes. + + * [windows/queue.c] [windows/hook.c] [windows/win.c] + SetMessageQueue() fixes. + +Fri Nov 29 10:25:12 1996 Slaven Rezic + + * [objects/text.c] + DrawText16(): Fixed return value. + +Tue Nov 26 14:47:09 1996 Marcus Meissner + + * [files/profile.c] [*/*] + Added Win32 profile functions, updated to new naming standard. + + * [objects/font.c] [if1632/thunk.c] [include/windows.h] + Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and + structures. + + * [misc/ole2nls.c] [if1632/thunk.c] + Added EnumSystemLocales() (winhelp.exe). + + * [misc/registry.c] + Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no + + * [win32/file.c] + Partially fixed CreateFileMapping(), added UnmapViewOfFile(). + +Sat Nov 23 23:36:05 1996 Ronan Waide + + * [misc/shell.c] + Fixed some FIXMEs relating to ShellExec() and FindExecutable(). + + * [misc/main.c] + Implemented a few more of the SystemParametersInfo() cases. + +Tue Nov 19 01:24:34 1996 Philippe De Muyter + + * [include/keyboard.h] + New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c). + + * [include/windows.h] + New [VK_A, VK_Z] and [VK_0, VK9] macros. + + * [misc/keyboard.c] + Fixes in KeyTable and ToAscii. + + * [objects/font.c] + FONT_init : Give default value for MSWIN "system" font. + FONT_MatchFont : Do not try every size of a font family if the + family does not exist. + + * [windows/event.c] + lastEventChar hack removed. + KeyStateTable replaced by InputKeyStateTable (maintained in event.c) + and QueueKeyStateTable (maintained in message.c). + EVENT_key : Corrections to the extended bit setting. + + * [windows/message.c] [windows/keyboard.c] + Implementation of a new QueueKeyStateTable : table of key states + valid when messages are retrieved by GetMessage or PeekMessage, + and valid for TranslateMessage. + TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable + and ToAscii. + +Mon Nov 18 16:59:01 1996 Robert Pouliot + + * [graphics/Makefile.in] [graphics/wing.c] + [if1632/wing.spec] + Some functions for WinG support, mostly empty stubs. + + * [misc/crtdll.c] [if1632/crtdll.spec] + Many functions added to CRTDLL, mostly calls to Unix C library. + ---------------------------------------------------------------------- Sun Nov 17 15:01:45 1996 Alexandre Julliard diff --git a/Make.rules.in b/Make.rules.in index f8d1c909304..2599eda3d2f 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -59,7 +59,7 @@ OBJS = $(GEN_C_SRCS:.c=.o) $(C_SRCS:.c=.o) $(ASM_SRCS:.S=.o) $(EXTRA_OBJS) echo "#include \"windows.h\"" >winerctmp.c echo WINDOWS_H_ENDS_HERE >>winerctmp.c cat $< >>winerctmp.c - $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P winerctmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) -c -o $* -p $* + $(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P winerctmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $* $(RM) winerctmp.c diff --git a/configure b/configure index 6d3c83d9c6c..e6d67cf80e9 100755 --- a/configure +++ b/configure @@ -2,7 +2,7 @@ # From configure.in configure.in 1.00 # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.10-patched +# Generated automatically using autoconf version 2.11 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -58,6 +58,8 @@ mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 ac_prev= for ac_option @@ -339,7 +341,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.10-patched" + echo "configure generated by autoconf version 2.11" exit 0 ;; -with-* | --with-*) @@ -543,8 +545,6 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # We want these before the checks, so the checks can modify their values. -test -z "$CFLAGS" && CFLAGS="-g -O2" -test -z "$LDFLAGS" && LDFLAGS=-g test -z "$LDLIBS" && LDLIBS=-lm @@ -576,7 +576,8 @@ fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -set dummy ${MAKE-make}; ac_make=$2 +echo "configure:580: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -604,6 +605,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:609: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -632,6 +634,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:638: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -678,7 +681,42 @@ fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:686: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_cv_prog_cc_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_prog_cc_works=no +fi +rm -f conftest* + + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: Installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi + echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:720: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -687,7 +725,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:691: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:729: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -695,10 +733,14 @@ fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + if test $ac_cv_prog_gcc = yes; then GCC=yes - if test "${CFLAGS+set}" != set; then - echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:744: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -713,11 +755,12 @@ rm -f conftest* fi echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 - if test $ac_cv_prog_gcc_g = yes; then - CFLAGS="-g -O" - else - CFLAGS="-O" - fi + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" fi else GCC= @@ -725,6 +768,7 @@ else fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:772: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -739,33 +783,37 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:793: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:764: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi @@ -780,31 +828,12 @@ else fi echo "$ac_t""$CPP" 1>&6 -echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 -if test -d /etc/conf/kconfig.d && - grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 -then - echo "$ac_t""yes" 1>&6 - ISC=yes # If later tests want to check for ISC. - cat >> confdefs.h <<\EOF -#define _POSIX_SOURCE 1 -EOF - - if test "$GCC" = yes; then - CC="$CC -posix" - else - CC="$CC -Xp" - fi -else - echo "$ac_t""no" 1>&6 - ISC= -fi - # If we find X, set shell vars x_includes and x_libraries to the # paths, otherwise set no_x=yes. # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 +echo "configure:837: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -844,7 +873,9 @@ EOF ac_im_usrlibdir=$ac_im_libdir; break fi done - # Screen out bogus values from the imake configuration. + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. case "$ac_im_incroot" in /usr/include) ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; @@ -864,12 +895,12 @@ if test "$ac_x_includes" = NO; then # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:873: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:904: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -877,30 +908,32 @@ if test -z "$ac_err"; then ac_x_includes= else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* # Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in \ + /usr/X11/include \ /usr/X11R6/include \ /usr/X11R5/include \ /usr/X11R4/include \ \ + /usr/include/X11 \ /usr/include/X11R6 \ /usr/include/X11R5 \ /usr/include/X11R4 \ \ + /usr/local/X11/include \ /usr/local/X11R6/include \ /usr/local/X11R5/include \ /usr/local/X11R4/include \ \ + /usr/local/include/X11 \ /usr/local/include/X11R6 \ /usr/local/include/X11R5 \ /usr/local/include/X11R4 \ \ - /usr/X11/include \ - /usr/include/X11 \ - /usr/local/X11/include \ - /usr/local/include/X11 \ - \ /usr/X386/include \ /usr/x386/include \ /usr/XFree86/include/X11 \ @@ -936,45 +969,46 @@ if test "$ac_x_libraries" = NO; then ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:980: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. ac_x_libraries= else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$ac_save_LIBS" # First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ /usr/X11R6/lib \ /usr/X11R5/lib \ /usr/X11R4/lib \ \ + /usr/lib/X11 \ /usr/lib/X11R6 \ /usr/lib/X11R5 \ /usr/lib/X11R4 \ \ + /usr/local/X11/lib \ /usr/local/X11R6/lib \ /usr/local/X11R5/lib \ /usr/local/X11R4/lib \ \ + /usr/local/lib/X11 \ /usr/local/lib/X11R6 \ /usr/local/lib/X11R5 \ /usr/local/lib/X11R4 \ \ - /usr/X11/lib \ - /usr/lib/X11 \ - /usr/local/X11/lib \ - /usr/local/lib/X11 \ - \ /usr/X386/lib \ /usr/x386/lib \ /usr/XFree86/lib/X11 \ @@ -985,6 +1019,7 @@ for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ /usr/athena/lib \ /usr/local/x11r5/lib \ /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ \ /usr/openwin/lib \ /usr/openwin/share/lib \ @@ -1030,74 +1065,83 @@ fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. - X_CFLAGS="$X_CFLAGS -DX_DISPLAY_MISSING" + cat >> confdefs.h <<\EOF +#define X_DISPLAY_MISSING 1 +EOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi - # It would be nice to have a more robust check for the -R ld option than - # just checking for Solaris. # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" - if test "`(uname) 2>/dev/null`" = SunOS && - uname -r | grep '^5' >/dev/null; then - X_LIBS="$X_LIBS -R $x_libraries" - fi - fi - - # Check for libraries that X11R6 Xt/Xaw programs need. - - ac_save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -L$x_libraries" - # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to - # check for ICE first), but we must link in the order -lSM -lICE or - # we get undefined symbols. So assume we have SM if we have ICE. - # These have to be linked with before -lX11, unlike the other - # libraries we check for below, so use a different variable. - # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. - echo $ac_n "checking for -lICE""... $ac_c" 1>&6 -ac_lib_var=`echo ICE'_'IceConnectionNumber | tr './+\055' '__p_'` -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="-lICE $LIBS" -cat > conftest.$ac_ext </dev/null`" in + "SunOS 5"*) + echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 +echo "configure:1087: checking whether -R must be followed by a space" >&5 + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" + ac_R_nospace=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" + ac_R_nospace=no fi rm -f conftest* -LIBS="$ac_save_LIBS" -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" + if test $ac_R_nospace = yes; then + echo "$ac_t""no" 1>&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_R_space=yes else - echo "$ac_t""no" 1>&6 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_space=no fi +rm -f conftest* - LDFLAGS="$ac_save_LDFLAGS" + if test $ac_R_space = yes; then + echo "$ac_t""yes" 1>&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$ac_t""neither works" 1>&6 + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" @@ -1105,30 +1149,32 @@ fi # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X # libraries were built with DECnet support. And karl@cs.umb.edu says # the Alpha needs dnet_stub (dnet does not exist). - echo $ac_n "checking for -ldnet""... $ac_c" 1>&6 -ac_lib_var=`echo dnet'_'dnet_ntoa | tr './+\055' '__p_'` + echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 +echo "configure:1154: checking for dnet_ntoa in -ldnet" >&5 +ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` 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="-ldnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1144,30 +1190,32 @@ else fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then - echo $ac_n "checking for -ldnet_stub""... $ac_c" 1>&6 -ac_lib_var=`echo dnet_stub'_'dnet_ntoa | tr './+\055' '__p_'` + echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 +echo "configure:1195: checking for dnet_ntoa in -ldnet_stub" >&5 +ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` 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="-ldnet_stub $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1186,32 +1234,85 @@ fi # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. - # Not sure which flavor of 386 UNIX this is, but it seems harmless to - # check for it. - echo $ac_n "checking for -lnsl""... $ac_c" 1>&6 -ac_lib_var=`echo nsl'_'t_accept | tr './+\055' '__p_'` + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:1243: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1271: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_gethostbyname = no; then + echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:1292: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` 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="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1226,36 +1327,90 @@ else echo "$ac_t""no" 1>&6 fi + fi # lieder@skyler.mavd.honeywell.com says without -lsocket, - # socket/setsockopt and other routines are undefined under SCO ODT 2.0. - # But -lsocket is broken on IRIX, according to simon@lia.di.epfl.ch. - if test "`(uname) 2>/dev/null`" != IRIX; then - if test $ac_cv_lib_nsl_t_accept = no; then - echo $ac_n "checking for -lsocket""... $ac_c" 1>&6 -ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'` + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + echo $ac_n "checking for connect""... $ac_c" 1>&6 +echo "configure:1341: checking for connect" >&5 +if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +connect(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_connect=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_connect=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_connect = no; then + echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 +echo "configure:1390: checking for connect in -lsocket" >&5 +ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` 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="-lsocket $LIBS" +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1265,37 +1420,89 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - X_EXTRA_LIBS="$X_EXTRA_LIBS -lsocket" + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" else echo "$ac_t""no" 1>&6 fi - else - # If we found -lnsl, use it to check for -lsocket. -- AJ - echo $ac_n "checking for -lsocket""... $ac_c" 1>&6 -ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'` + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + echo $ac_n "checking for remove""... $ac_c" 1>&6 +echo "configure:1433: checking for remove" >&5 +if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +remove(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1461: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_remove=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_remove=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_remove = no; then + echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 +echo "configure:1482: checking for remove in -lposix" >&5 +ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` 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="-lsocket -lnsl $LIBS" +LIBS="-lposix $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1501: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1305,14 +1512,157 @@ LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 - X_EXTRA_LIBS="$X_EXTRA_LIBS -lsocket" + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo $ac_n "checking for shmat""... $ac_c" 1>&6 +echo "configure:1525: checking for shmat" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +shmat(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_shmat=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shmat=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_shmat = no; then + echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 +echo "configure:1574: checking for shmat in -lipc" >&5 +ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` +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="-lipc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" else echo "$ac_t""no" 1>&6 fi - fi fi fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 +echo "configure:1626: checking for IceConnectionNumber in -lICE" >&5 +ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` +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="-lICE $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +else + echo "$ac_t""no" 1>&6 +fi + + LDFLAGS="$ac_save_LDFLAGS" + fi for ac_prog in 'bison -y' byacc @@ -1320,6 +1670,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1674: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1351,6 +1702,7 @@ test -n "$YACC" || YACC="yacc" # Extract the first word of "flex", so it can be a program name with args. set dummy flex; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1706: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1382,30 +1734,32 @@ then flex*) ac_lib=fl ;; *) ac_lib=l ;; esac - echo $ac_n "checking for -l$ac_lib""... $ac_c" 1>&6 -ac_lib_var=`echo $ac_lib'_'yywrap | tr './+\055' '__p_'` + echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6 +echo "configure:1739: checking for yywrap in -l$ac_lib" >&5 +ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'` 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="-l$ac_lib $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1425,6 +1779,7 @@ fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1783: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1461,6 +1816,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1820: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1509,30 +1865,32 @@ test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -echo $ac_n "checking for -li386""... $ac_c" 1>&6 -ac_lib_var=`echo i386'_'i386_set_ldt | tr './+\055' '__p_'` +echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6 +echo "configure:1870: checking for i386_set_ldt in -li386" >&5 +ac_lib_var=`echo i386'_'i386_set_ldt | sed 'y%./+-%__p_%'` 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="-li386 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -1552,41 +1910,47 @@ fi if test "x${GCC}" = "xyes" then CFLAGS="$CFLAGS -Wall" - # If we cannot run a trivial program, we must be cross compiling. -echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6 + # If we cannot run a trivial program, we are probably using a cross compiler. +echo $ac_n "checking whether using a cross-compiler""... $ac_c" 1>&6 +echo "configure:1916: checking whether using a cross-compiler" >&5 if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_c_cross=yes else -cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } +{ (eval echo configure:1928: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } if test -s conftest && (./conftest; exit) 2>/dev/null; then ac_cv_c_cross=no else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_c_cross=yes fi -fi rm -fr conftest* fi +fi + echo "$ac_t""$ac_cv_c_cross" 1>&6 cross_compiling=$ac_cv_c_cross echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6 +echo "configure:1946: 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 if test "$cross_compiling" = yes; then ac_cv_c_gcc_strength_bug="yes" else -cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } +{ (eval echo configure:1965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } if test -s conftest && (./conftest; exit) 2>/dev/null; then ac_cv_c_gcc_strength_bug="no" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_c_gcc_strength_bug="yes" fi +rm -fr conftest* fi -rm -fr conftest* + fi echo "$ac_t""$ac_cv_c_gcc_strength_bug" 1>&6 @@ -1616,6 +1984,7 @@ fi echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6 +echo "configure:1988: 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 @@ -1627,18 +1996,19 @@ _ac_test: .long 0 EOF cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:2007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_c_extern_prefix="yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_extern_prefix="no" fi @@ -1660,11 +2030,12 @@ fi for ac_func in memmove tcgetattr usleep do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2034: 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; }; then +if { (eval echo configure:2062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi @@ -1711,11 +2083,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 +echo "configure:2087: 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 @@ -1766,15 +2139,15 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2143: 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:2197: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi @@ -1840,11 +2215,12 @@ EOF fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:2219: 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 @@ -1852,13 +2228,15 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1856: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2232: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi @@ -1867,7 +2245,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 @@ -1885,7 +2263,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 @@ -1905,8 +2283,8 @@ if test $ac_cv_header_stdc = yes; then if test "$cross_compiling" = yes; then : else -cat > conftest.$ac_ext < conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1917,14 +2295,18 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -{ (eval echo configure:1921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } +{ (eval echo configure:2299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } if test -s conftest && (./conftest; exit) 2>/dev/null; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_header_stdc=no fi -fi rm -fr conftest* +fi + fi fi @@ -1937,19 +2319,21 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:2323: 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 #include +#include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "size_t" >/dev/null 2>&1; then + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else @@ -1991,8 +2375,9 @@ cat > confcache <<\EOF EOF # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. +# HP-UX 10.01 sh prints single quotes around any value that contains spaces. (set) 2>&1 | - sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \ +sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)='*\([^']*\)'*/\1=\${\1='\2'}/p"\ >> confcache if cmp -s $cache_file confcache; then : @@ -2048,7 +2433,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.10-patched" + echo "$CONFIG_STATUS generated by autoconf version 2.11" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -2137,6 +2522,42 @@ s%@MAKE_RULES@%%g CEOF EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + cat >> $CONFIG_STATUS < $ac_file +" $ac_given_srcdir/$ac_file_in | eval "$ac_sed_cmds" > $ac_file fi; done -rm -f conftest.subs +rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. @@ -2240,7 +2662,13 @@ ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' -CONFIG_HEADERS=${CONFIG_HEADERS-"include/config.h"} +if test -z "$CONFIG_HEADERS"; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile]", defaulting infile="outfile.in". case "$ac_file" in @@ -2280,8 +2708,6 @@ EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. -# Maximum number of lines to put in a single here document. -ac_max_here_lines=12 rm -f conftest.tail while : diff --git a/configure.in b/configure.in index e96abccf380..8e49105d0f5 100644 --- a/configure.in +++ b/configure.in @@ -7,8 +7,6 @@ AC_CONFIG_HEADER(include/config.h) AC_CONFIG_AUX_DIR(tools) # We want these before the checks, so the checks can modify their values. -test -z "$CFLAGS" && CFLAGS="-g -O2" AC_SUBST(CFLAGS) -test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS) test -z "$LDLIBS" && LDLIBS=-lm AC_SUBST(LDLIBS) dnl **** Command-line arguments **** diff --git a/controls/Makefile.in b/controls/Makefile.in index 09188b5f1ba..7f7dff9cea3 100644 --- a/controls/Makefile.in +++ b/controls/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ edit.c \ listbox.c \ menu.c \ + oldlbox.c \ scroll.c \ static.c \ status.c \ diff --git a/controls/button.c b/controls/button.c index 3367a66b85d..1c4df7e5bbf 100644 --- a/controls/button.c +++ b/controls/button.c @@ -187,7 +187,8 @@ LRESULT ButtonWndProc(HWND32 hWnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam) case WM_KILLFOCUS: infoPtr->state &= ~BUTTON_HASFOCUS; - PAINT_BUTTON( wndPtr, style, ODA_FOCUS ); + PAINT_BUTTON( wndPtr, style, ODA_FOCUS ); + InvalidateRect16( hWnd, NULL, TRUE ); break; case WM_SYSCOLORCHANGE: @@ -369,57 +370,70 @@ void PB_PaintGrayOnGray(HDC32 hDC,HFONT32 hFont,RECT32 *rc,char *text) static void CB_Paint( WND *wndPtr, HDC32 hDC, WORD action ) { - RECT16 rc; + RECT16 rbox, rtext, client; HBRUSH16 hBrush; - int textlen, delta, x, y; - TEXTMETRIC16 tm; + int textlen, delta; BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra; - GetClientRect16(wndPtr->hwndSelf, &rc); + textlen = 0; + GetClientRect16(wndPtr->hwndSelf, &client); + rbox = rtext = client; if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont ); hBrush = BUTTON_SEND_CTLCOLOR( wndPtr, hDC ); - if (action == ODA_DRAWENTIRE) FillRect16( hDC, &rc, hBrush ); + if (wndPtr->dwStyle & BS_LEFTTEXT) + { + /* magic +4 is what CTL3D expects */ - GetTextMetrics16(hDC, &tm); - delta = (rc.bottom - rc.top - tm.tmHeight) >> 1; + rtext.right -= checkBoxWidth + 4; + rbox.left = rbox.right - checkBoxWidth; + } + else + { + rtext.left += checkBoxWidth + 4; + rbox.right = checkBoxWidth; + } /* Draw the check-box bitmap */ - x = y = 0; - if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth; - if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth; - if (((wndPtr->dwStyle & 0x0f) == BS_RADIOBUTTON) || - ((wndPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight; - else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight; - GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes, rc.left, rc.top + delta, - x, y, checkBoxWidth, checkBoxHeight ); - rc.left += checkBoxWidth + tm.tmAveCharWidth / 2; - if (!wndPtr->text) return; - textlen = strlen( wndPtr->text ); + if (wndPtr->text) textlen = strlen( wndPtr->text ); + if (action == ODA_DRAWENTIRE || action == ODA_SELECT) + { + int x = 0, y = 0; + delta = (rbox.bottom - rbox.top - checkBoxHeight) >> 1; - if (action == ODA_DRAWENTIRE) - { - if (wndPtr->dwStyle & WS_DISABLED) - SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) ); - DrawText16( hDC, wndPtr->text, textlen, &rc, - DT_SINGLELINE | DT_VCENTER | DT_NOCLIP ); + if (action == ODA_SELECT) FillRect16( hDC, &rbox, hBrush ); + else FillRect16( hDC, &client, hBrush ); + + if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth; + if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth; + if (((wndPtr->dwStyle & 0x0f) == BS_RADIOBUTTON) || + ((wndPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight; + else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight; + + GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes, rbox.left, rbox.top + delta, + x, y, checkBoxWidth, checkBoxHeight ); + if( textlen && action != ODA_SELECT ) + { + if (wndPtr->dwStyle & WS_DISABLED) + SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) ); + DrawText16( hDC, wndPtr->text, textlen, &rtext, + DT_SINGLELINE | DT_VCENTER ); + } } - + if ((action == ODA_FOCUS) || ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS))) { - RECT16 rect = { 0, 0, 0, 0 }; - DrawText16( hDC, wndPtr->text, textlen, &rect, - DT_SINGLELINE | DT_CALCRECT ); - if (delta > 1) - { - rc.top += delta - 1; - rc.bottom -= delta + 1; - } - rc.left--; - rc.right = rc.left + rect.right + 2; - DrawFocusRect16( hDC, &rc ); + /* again, this is what CTL3D expects */ + + DWORD tm = (textlen) ? GetTextExtent( hDC, wndPtr->text, textlen) : 0x00020002; + delta = (rtext.bottom - rtext.top - HIWORD(tm) - 1)/2; + + rbox.bottom = (rbox.top = rtext.top + delta - 1) + HIWORD(tm) + 2; + rbox.right = (rbox.left = --rtext.left) + LOWORD(tm) + 2; + IntersectRect16(&rbox, &rbox, &rtext); + DrawFocusRect16( hDC, &rbox ); } } diff --git a/controls/combo.c b/controls/combo.c index 43a368b22db..4c231f424f3 100644 --- a/controls/combo.c +++ b/controls/combo.c @@ -1233,68 +1233,3 @@ LRESULT ComboLBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam } return DefWindowProc16(hwnd, message, wParam, lParam); } - - -static INT32 COMBO_DlgDirList( HWND32 hDlg, LPARAM path, INT32 idCBox, - INT32 idStatic, UINT32 wType, BOOL32 unicode ) -{ - LRESULT res = 0; - - if (idCBox) - { - SendDlgItemMessage32A( hDlg, idCBox, CB_RESETCONTENT16, 0, 0 ); - if (unicode) - res = SendDlgItemMessage32W( hDlg, idCBox, CB_DIR16, wType, path ); - else - res = SendDlgItemMessage32A( hDlg, idCBox, CB_DIR16, wType, path ); - } - if (idStatic) - { - char temp[512] = "A:\\"; - int drive = DRIVE_GetCurrentDrive(); - temp[0] += drive; - lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 ); - AnsiLower( temp ); - SetDlgItemText32A( hDlg, idStatic, temp ); - } - return (res >= 0); -} - - -/*********************************************************************** - * DlgDirListComboBox16 (USER.195) - */ -INT16 DlgDirListComboBox16( HWND16 hDlg, SEGPTR path, INT16 idCBox, - INT16 idStatic, UINT16 wType ) -{ - dprintf_combo( stddeb,"DlgDirListComboBox16(%04x,%08x,%d,%d,%04x)\n", - hDlg, (UINT32)path, idCBox, idStatic, wType ); - return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox, - idStatic, wType, FALSE ); -} - - -/*********************************************************************** - * DlgDirListComboBox32A (USER32.143) - */ -INT32 DlgDirListComboBox32A( HWND32 hDlg, LPCSTR path, INT32 idCBox, - INT32 idStatic, UINT32 wType ) -{ - dprintf_combo( stddeb,"DlgDirListComboBox32A(%08x,'%s',%d,%d,%08X)\n", - hDlg, path, idCBox, idStatic, wType ); - return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox, - idStatic, wType, FALSE ); -} - - -/*********************************************************************** - * DlgDirListComboBox32W (USER32.144) - */ -INT32 DlgDirListComboBox32W( HWND32 hDlg, LPCWSTR path, INT32 idCBox, - INT32 idStatic, UINT32 wType ) -{ - dprintf_combo( stddeb,"DlgDirListComboBox32W(%08x,%p,%d,%d,%08X)\n", - hDlg, path, idCBox, idStatic, wType ); - return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox, - idStatic, wType, TRUE ); -} diff --git a/controls/desktop.c b/controls/desktop.c index 87cde85523c..b7458b957ca 100644 --- a/controls/desktop.c +++ b/controls/desktop.c @@ -173,7 +173,7 @@ LRESULT DesktopWndProc( HWND32 hwnd, UINT32 message, BOOL16 SetDeskPattern(void) { char buffer[100]; - GetProfileString( "desktop", "Pattern", "(None)", buffer, 100 ); + GetProfileString32A( "desktop", "Pattern", "(None)", buffer, 100 ); return DESKTOP_SetPattern( buffer ); } @@ -202,7 +202,7 @@ BOOL32 SetDeskWallPaper32( LPCSTR filename ) if (filename == (LPSTR)-1) { - GetProfileString( "desktop", "WallPaper", "(None)", buffer, 256 ); + GetProfileString32A( "desktop", "WallPaper", "(None)", buffer, 256 ); filename = buffer; } hdc = GetDC32( 0 ); @@ -210,7 +210,7 @@ BOOL32 SetDeskWallPaper32( LPCSTR filename ) ReleaseDC32( 0, hdc ); if (infoPtr->hbitmapWallPaper) DeleteObject32( infoPtr->hbitmapWallPaper ); infoPtr->hbitmapWallPaper = hbitmap; - infoPtr->fTileWallPaper = GetProfileInt( "desktop", "TileWallPaper", 0 ); + infoPtr->fTileWallPaper = GetProfileInt32A( "desktop", "TileWallPaper", 0 ); if (hbitmap) { BITMAP32 bmp; diff --git a/controls/listbox.c b/controls/listbox.c index a07645d390b..bad86a74c86 100644 --- a/controls/listbox.c +++ b/controls/listbox.c @@ -1,2269 +1,2393 @@ /* * Listbox controls - * - * Copyright Martin Ayotte, 1993 - * Constantine Sapuntzakis, 1995 - * Alex Korobka, 1995, 1996 - * + * + * Copyright 1996 Alexandre Julliard */ - /* - * FIXME: - * - proper scrolling for multicolumn style - * - anchor and caret for LBS_EXTENDEDSEL - * - proper selection with keyboard - * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style - * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles - */ - -#include -#include +#define NO_TRANSITION_TYPES /* This file is Win32-clean */ #include -#include +#include #include "windows.h" -#include "win.h" -#include "gdi.h" -#include "msdos.h" -#include "listbox.h" -#include "dos_fs.h" #include "drive.h" -#include "file.h" +#include "dos_fs.h" +#include "msdos.h" #include "heap.h" +#include "spy.h" +#include "win.h" #include "stddebug.h" #include "debug.h" -#include "xmalloc.h" -#define LIST_HEAP_ALLOC(lphl,f,size) \ - LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) ) -#define LIST_HEAP_FREE(lphl,handle) \ - LOCAL_Free( lphl->HeapSel, (handle) ) -#define LIST_HEAP_ADDR(lphl,handle) \ - ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL) +/* Unimplemented yet: + * - LBS_NOSEL + * - LBS_USETABSTOPS + * - Unicode + * - Locale handling + * - COMBOLBOX + */ -#define LIST_HEAP_SIZE 0x10000 +/* Items array granularity */ +#define LB_ARRAY_GRANULARITY 16 -#define LBMM_EDGE 4 /* distance inside box which is same as moving mouse - outside box, to trigger scrolling of LB */ +/* Scrolling timeout in ms */ +#define LB_SCROLL_TIMEOUT 50 -#define MATCH_SUBSTR 2 -#define MATCH_EXACT 1 -#define MATCH_NEAREST 0 +/* Listbox system timer id */ +#define LB_TIMER_ID 2 -static void ListBoxInitialize(LPHEADLIST lphl) +/* Item structure */ +typedef struct { - lphl->lpFirst = NULL; - lphl->ItemsCount = 0; - lphl->ItemsVisible = 0; - lphl->FirstVisible = 0; - lphl->ColumnsVisible = 1; - lphl->ItemsPerColumn = 0; - lphl->ItemFocused = -1; - lphl->PrevFocused = -1; -} + LPSTR str; /* Item text */ + BOOL32 selected; /* Is item selected? */ + UINT32 height; /* Item height (only for OWNERDRAWVARIABLE) */ + DWORD data; /* User data */ +} LB_ITEMDATA; -void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent) +/* Listbox structure */ +typedef struct { - LPHEADLIST lphl; - HDC32 hdc; + HANDLE32 heap; /* Heap for this listbox */ + HWND32 owner; /* Owner window */ + UINT32 style; /* Window style */ + INT32 width; /* Window width */ + INT32 height; /* Window height */ + LB_ITEMDATA *items; /* Array of items */ + INT32 nb_items; /* Number of items */ + INT32 top_item; /* Top visible item */ + INT32 selected_item; /* Selected item */ + INT32 focus_item; /* Item that has the focus */ + INT32 anchor_item; /* Anchor item for extended selection */ + INT32 item_height; /* Default item height */ + INT32 page_size; /* Items per listbox page */ + INT32 column_width; /* Column width for multi-column listboxes */ + INT32 horz_extent; /* Horizontal extent (0 if no hscroll) */ + INT32 horz_pos; /* Horizontal position */ + INT32 nb_tabs; /* Number of tabs in array */ + INT32 *tabs; /* Array of tabs */ + BOOL32 caret_on; /* Is caret on? */ + HFONT32 font; /* Current font */ + LCID locale; /* Current locale for string comparisons */ +} LB_DESCR; - lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST)); - SetWindowLong32A(hwnd, 0, (LONG)lphl); - ListBoxInitialize(lphl); - lphl->DrawCtlType = CtlType; - lphl->CtlID = GetWindowWord(hwnd,GWW_ID); - lphl->bRedrawFlag = TRUE; - lphl->iNumStops = 0; - lphl->TabStops = NULL; - lphl->hFont = GetStockObject32(SYSTEM_FONT); - lphl->hSelf = hwnd; - if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */ - /* LBS_SORT instead CBS_SORT e.g. */ - lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE))); - else - lphl->dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */ - lphl->hParent = parent; - lphl->StdItemHeight = 15; /* FIXME: should get the font height */ - lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE); - lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn; - /* create dummy hdc to set text height */ - if ((hdc = GetDC32(0))) - { - TEXTMETRIC16 tm; - GetTextMetrics16( hdc, &tm ); - lphl->StdItemHeight = tm.tmHeight; - dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n", - lphl->StdItemHeight); - ReleaseDC32( 0, hdc ); - } +#define IS_OWNERDRAW(descr) \ + ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) - if (lphl->OwnerDrawn) - { - LISTSTRUCT dummyls; - - lphl->needMeasure = TRUE; - dummyls.mis.CtlType = lphl->DrawCtlType; - dummyls.mis.CtlID = lphl->CtlID; - dummyls.mis.itemID = -1; - dummyls.mis.itemWidth = 0; /* ignored */ - dummyls.mis.itemData = 0; +#define HAS_STRINGS(descr) \ + (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS)) - ListBoxAskMeasure(lphl,&dummyls); - } +#define SEND_NOTIFICATION(wnd,descr,code) \ + (SendMessage32A( (descr)->owner, WM_COMMAND, \ + MAKEWPARAM( (wnd)->wIDmenu, (code) ), (wnd)->hwndSelf )) - lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE); - LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1); -} - -void DestroyListBoxStruct(LPHEADLIST lphl) +/* Current timer status */ +typedef enum { - /* XXX need to free lphl->Heap */ - GlobalFree16(lphl->HeapSel); - free(lphl); -} + LB_TIMER_NONE, + LB_TIMER_UP, + LB_TIMER_LEFT, + LB_TIMER_DOWN, + LB_TIMER_RIGHT +} TIMER_DIRECTION; -static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd) +static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE; + + +/*********************************************************************** + * LISTBOX_Dump + */ +void LISTBOX_Dump( WND *wnd ) { - return (LPHEADLIST)GetWindowLong32A(hwnd,0); -} + INT32 i; + LB_ITEMDATA *item; + LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra; -/* Send notification "code" as part of a WM_COMMAND-message if hwnd - has the LBS_NOTIFY style */ -void ListBoxSendNotification(LPHEADLIST lphl, WORD code) -{ - if (lphl->dwStyle & LBS_NOTIFY) - SendMessage32A( lphl->hParent, WM_COMMAND, - MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf ); -} - - -/* get the maximum value of lphl->FirstVisible */ -int ListMaxFirstVisible(LPHEADLIST lphl) -{ - int m = lphl->ItemsCount-lphl->ItemsVisible; - return (m < 0) ? 0 : m; -} - - -void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint) -{ - if (lphl->dwStyle & WS_VSCROLL) - SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE); - if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0)) - SetScrollRange32(hwnd, SB_HORZ, 1, lphl->ItemsVisible / - lphl->ItemsPerColumn + 1, TRUE); - - if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE ); -} - -/* Returns: 0 if nothing needs to be changed */ -/* 1 if FirstVisible changed */ - -int ListBoxScrollToFocus(LPHEADLIST lphl) -{ - short end; - - if (lphl->ItemsCount == 0) return 0; - if (lphl->ItemFocused == -1) return 0; - - end = lphl->FirstVisible + lphl->ItemsVisible - 1; - - if (lphl->ItemFocused < lphl->FirstVisible ) { - lphl->FirstVisible = lphl->ItemFocused; - return 1; - } else { - if (lphl->ItemFocused > end) { - WORD maxFirstVisible = ListMaxFirstVisible(lphl); - - lphl->FirstVisible = lphl->ItemFocused; - - if (lphl->FirstVisible > maxFirstVisible) { - lphl->FirstVisible = maxFirstVisible; - } - return 1; + printf( "Listbox:\n" ); + printf( "hwnd=%04x descr=%08x heap=%08x items=%d top=%d\n", + wnd->hwndSelf, (UINT32)descr, descr->heap, descr->nb_items, + descr->top_item ); + for (i = 0, item = descr->items; i < descr->nb_items; i++, item++) + { + printf( "%4d: %-40s %d %08lx %3d\n", + i, item->str, item->selected, item->data, item->height ); } - } - return 0; } -LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex) +/*********************************************************************** + * LISTBOX_GetCurrentPageSize + * + * Return the current page size + */ +static INT32 LISTBOX_GetCurrentPageSize( WND *wnd, LB_DESCR *descr ) { - LPLISTSTRUCT lpls; - UINT Count = 0; - - if (uIndex >= lphl->ItemsCount) return NULL; - - lpls = lphl->lpFirst; - while (Count++ < uIndex) lpls = lpls->lpNext; - return lpls; + INT32 i, height; + if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size; + for (i = descr->top_item, height = 0; i < descr->nb_items; i++) + { + if ((height += descr->items[i].height) > descr->height) break; + } + if (i == descr->top_item) return 1; + else return i - descr->top_item; } -void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls, - RECT16 *rect, WORD itemAction, WORD itemState) +/*********************************************************************** + * LISTBOX_GetMaxTopIndex + * + * Return the maximum possible index for the top of the listbox. + */ +static INT32 LISTBOX_GetMaxTopIndex( WND *wnd, LB_DESCR *descr ) { - if (lphl->OwnerDrawn) + INT32 max, page; + + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + page = descr->height; + for (max = descr->nb_items - 1; max >= 0; max--) + if ((page -= descr->items[max].height) < 0) break; + if (max < descr->nb_items - 1) max++; + } + else if (descr->style & LBS_MULTICOLUMN) + { + if ((page = descr->width / descr->column_width) < 1) page = 1; + max = (descr->nb_items + descr->page_size - 1) / descr->page_size; + max = (max - page) * descr->page_size; + } + else + { + max = descr->nb_items - descr->page_size; + } + if (max < 0) max = 0; + return max; +} + + +/*********************************************************************** + * LISTBOX_UpdateScroll + * + * Update the scrollbars. Should be called whenever the content + * of the listbox changes. + */ +static void LISTBOX_UpdateScroll( WND *wnd, LB_DESCR *descr ) +{ + SCROLLINFO info; + + if (descr->style & LBS_NOREDRAW) return; + info.cbSize = sizeof(info); + + if (descr->style & LBS_MULTICOLUMN) + { + info.nMin = 0; + info.nMax = (descr->nb_items - 1) / descr->page_size; + info.nPos = descr->top_item / descr->page_size; + info.nPage = descr->width / descr->column_width; + if (info.nPage < 1) info.nPage = 1; + info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + if (descr->style & LBS_DISABLENOSCROLL) + info.fMask |= SIF_DISABLENOSCROLL; + SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE ); + info.nMax = 0; + info.fMask = SIF_RANGE; + SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE ); + } + else + { + info.nMin = 0; + info.nMax = descr->nb_items - 1; + info.nPos = descr->top_item; + info.nPage = LISTBOX_GetCurrentPageSize( wnd, descr ); + info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + if (descr->style & LBS_DISABLENOSCROLL) + info.fMask |= SIF_DISABLENOSCROLL; + SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE ); + + if (descr->horz_extent) + { + info.nMin = 0; + info.nMax = descr->horz_extent - 1; + info.nPos = descr->horz_pos; + info.nPage = descr->width; + info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + if (descr->style & LBS_DISABLENOSCROLL) + info.fMask |= SIF_DISABLENOSCROLL; + SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE ); + } + } +} + + +/*********************************************************************** + * LISTBOX_SetTopItem + * + * Set the top item of the listbox, scrolling up or down if necessary. + */ +static LRESULT LISTBOX_SetTopItem( WND *wnd, LB_DESCR *descr, INT32 index, + BOOL32 scroll ) +{ + INT32 max = LISTBOX_GetMaxTopIndex( wnd, descr ); + if (index > max) index = max; + if (index < 0) index = 0; + if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size; + if (descr->top_item == index) return LB_OKAY; + if (descr->style & LBS_MULTICOLUMN) + { + INT32 diff = (descr->top_item - index) / descr->page_size * descr->column_width; + if (scroll && (abs(diff) < descr->width)) + ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL ); + else + scroll = FALSE; + } + else if (scroll) + { + INT32 diff; + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + INT32 i; + diff = 0; + if (index > descr->top_item) + { + for (i = index - 1; i >= descr->top_item; i--) + diff -= descr->items[i].height; + } + else + { + for (i = index; i < descr->top_item; i++) + diff += descr->items[i].height; + } + } + else + diff = (descr->top_item - index) * descr->item_height; + + if (abs(diff) < descr->height) + ScrollWindow32( wnd->hwndSelf, 0, diff, NULL, NULL ); + else + scroll = FALSE; + } + if (!scroll) InvalidateRect32( wnd->hwndSelf, NULL, TRUE ); + descr->top_item = index; + LISTBOX_UpdateScroll( wnd, descr ); + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_UpdatePage + * + * Update the page size. Should be called when the size of + * the client area or the item height changes. + */ +static void LISTBOX_UpdatePage( WND *wnd, LB_DESCR *descr ) +{ + INT32 page_size; + + if ((page_size = descr->height / descr->item_height) < 1) page_size = 1; + if (page_size == descr->page_size) return; + descr->page_size = page_size; + if (descr->style & LBS_MULTICOLUMN) + InvalidateRect32( wnd->hwndSelf, NULL, TRUE ); + LISTBOX_SetTopItem( wnd, descr, descr->top_item, FALSE ); +} + + +/*********************************************************************** + * LISTBOX_UpdateSize + * + * Update the size of the listbox. Should be called when the size of + * the client area changes. + */ +static void LISTBOX_UpdateSize( WND *wnd, LB_DESCR *descr ) +{ + RECT32 rect; + + GetClientRect32( wnd->hwndSelf, &rect ); + descr->width = rect.right - rect.left; + descr->height = rect.bottom - rect.top; + if (!(descr->style & LBS_NOINTEGRALHEIGHT)) + { + if ((descr->height > descr->item_height) && + (descr->height % descr->item_height)) + { + dprintf_listbox(stddeb, "Listbox %04x: changing height %d -> %d\n", + wnd->hwndSelf, descr->height, + descr->height - descr->height%descr->item_height ); + SetWindowPos( wnd->hwndSelf, 0, 0, 0, + wnd->rectWindow.right - wnd->rectWindow.left, + wnd->rectWindow.bottom - wnd->rectWindow.top - + (descr->height % descr->item_height), + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE ); + return; + } + } + dprintf_listbox( stddeb, "Listbox %04x: new size = %d,%d\n", + wnd->hwndSelf, descr->width, descr->height ); + LISTBOX_UpdatePage( wnd, descr ); + LISTBOX_UpdateScroll( wnd, descr ); +} + + +/*********************************************************************** + * LISTBOX_GetItemRect + * + * Get the rectangle enclosing an item, in listbox client coordinates. + * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error. + */ +static LRESULT LISTBOX_GetItemRect( WND *wnd, LB_DESCR *descr, INT32 index, + RECT32 *rect ) +{ + /* Index <= 0 is legal even on empty listboxes */ + if (index && (index >= descr->nb_items)) return -1; + SetRect32( rect, 0, 0, descr->width, descr->height ); + if (descr->style & LBS_MULTICOLUMN) + { + INT32 col = (index / descr->page_size) - + (descr->top_item / descr->page_size); + rect->left += col * descr->column_width; + rect->right = rect->left + descr->column_width; + rect->top += (index % descr->page_size) * descr->item_height; + rect->bottom = rect->top + descr->item_height; + } + else if (descr->style & LBS_OWNERDRAWVARIABLE) + { + INT32 i; + if (index < descr->top_item) + { + for (i = descr->top_item-1; i >= index; i--) + rect->top -= descr->items[i].height; + } + else + { + for (i = descr->top_item; i < index; i++) + rect->top += descr->items[i].height; + } + rect->bottom = rect->top + descr->items[index].height; + rect->right += descr->horz_pos; + } + else + { + rect->top += (index - descr->top_item) * descr->item_height; + rect->bottom = rect->top + descr->item_height; + rect->right += descr->horz_pos; + } + + return ((rect->left < descr->width) && (rect->right > 0) && + (rect->top < descr->height) && (rect->bottom > 0)); +} + + +/*********************************************************************** + * LISTBOX_GetItemFromPoint + * + * Return the item nearest from point (x,y) (in client coordinates). + */ +static INT32 LISTBOX_GetItemFromPoint( WND *wnd, LB_DESCR *descr, + INT32 x, INT32 y ) +{ + INT32 index = descr->top_item; + + if (!descr->nb_items) return -1; /* No items */ + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + INT32 pos = 0; + if (y >= 0) + { + while (index < descr->nb_items) + { + if ((pos += descr->items[index].height) > y) break; + index++; + } + } + else + { + while (index > 0) + { + index--; + if ((pos -= descr->items[index].height) <= y) break; + } + } + } + else if (descr->style & LBS_MULTICOLUMN) + { + if (y >= descr->item_height * descr->page_size) return -1; + if (y >= 0) index += y / descr->item_height; + if (x >= 0) index += (x / descr->column_width) * descr->page_size; + else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size; + } + else + { + index += (y / descr->item_height); + } + if (index < 0) return 0; + if (index >= descr->nb_items) return -1; + return index; +} + + +/*********************************************************************** + * LISTBOX_PaintItem + * + * Paint an item. + */ +static void LISTBOX_PaintItem( WND *wnd, LB_DESCR *descr, HDC32 hdc, + const RECT32 *rect, INT32 index, UINT32 action ) +{ + LB_ITEMDATA *item = NULL; + if (index < descr->nb_items) item = &descr->items[index]; + + if (IS_OWNERDRAW(descr)) { DRAWITEMSTRUCT32 dis; - - dis.CtlID = lpls->mis.CtlID; - dis.CtlType = lpls->mis.CtlType; - dis.itemID = lpls->mis.itemID; - dis.hDC = hdc; - dis.hwndItem = hwnd; - dis.itemData = lpls->mis.itemData; - dis.itemAction = itemAction; - dis.itemState = itemState; - CONV_RECT16TO32( rect, &dis.rcItem ); - SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis ); - return; - } - if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) { - int OldBkMode; - DWORD dwOldTextColor = 0; - - OldBkMode = SetBkMode(hdc, TRANSPARENT); - - if (itemState != 0) { - dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL); - FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH)); - } - - if (lphl->dwStyle & LBS_USETABSTOPS) { - TabbedTextOut(hdc, rect->left + 5, rect->top + 2, - (char *)lpls->itemText, strlen((char *)lpls->itemText), - lphl->iNumStops, lphl->TabStops, 0); - } else { - TextOut16(hdc, rect->left + 5, rect->top + 2, - (char *)lpls->itemText, strlen((char *)lpls->itemText)); - } - - if (itemState != 0) { - SetTextColor(hdc, dwOldTextColor); - } - - SetBkMode(hdc, OldBkMode); - } - else DrawFocusRect16(hdc, rect); -} - - -int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y) -{ - LPLISTSTRUCT lpls = lphl->lpFirst; - int i, j; - POINT16 point; - - point.x = X; point.y = Y; - if (lphl->ItemsCount == 0) return LB_ERR; - - for(i = 0; i < lphl->FirstVisible; i++) { - if (lpls == NULL) return LB_ERR; - lpls = lpls->lpNext; - } - for(j = 0; j < lphl->ItemsVisible; i++, j++) { - if (lpls == NULL) return LB_ERR; - if (PtInRect16(&lpls->itemRect,point)) { - return i; - } - lpls = lpls->lpNext; - } - dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n"); - return LB_ERR; -} - -BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls) -{ - /* called only for owner drawn listboxes */ - BOOL32 ret; - DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16); - if (!delItem) return FALSE; - - delItem->CtlType = lphl->DrawCtlType; - delItem->CtlID = lphl->CtlID; - delItem->itemID = lpls->mis.itemID; - delItem->hwndItem = lphl->hSelf; - delItem->itemData = lpls->mis.itemData; - - ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID, - (LPARAM)SEGPTR_GET(delItem) ); - SEGPTR_FREE(delItem); - return ret; -} - -void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls) -{ - MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16); - if (!lpmeasure) return; - *lpmeasure = lpls->mis; - lpmeasure->itemHeight = lphl->StdItemHeight; - SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID, - (LPARAM)SEGPTR_GET(lpmeasure) ); - - if (lphl->dwStyle & LBS_OWNERDRAWFIXED) - { - if (lpmeasure->itemHeight > lphl->StdItemHeight) - lphl->StdItemHeight = lpmeasure->itemHeight; - lpls->mis.itemHeight = lpmeasure->itemHeight; - } - SEGPTR_FREE(lpmeasure); -} - -/* -------------------- strings and item data ---------------------- */ - -LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id) -{ - LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT)); - - if (lplsnew == NULL) return NULL; - - lplsnew->itemState = 0; - lplsnew->mis.CtlType = lphl->DrawCtlType; - lplsnew->mis.CtlID = lphl->CtlID; - lplsnew->mis.itemID = id; - lplsnew->mis.itemHeight = lphl->StdItemHeight; - lplsnew->mis.itemWidth = 0; /* ignored */ - lplsnew->mis.itemData = 0; - SetRectEmpty16( &lplsnew->itemRect ); - - return lplsnew; -} - -int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch ) -{ - /* Do binary search for sorted listboxes. Linked list item storage sort of - * defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way... - * - * MATCH_NEAREST (0) - return position for insertion - for all styles - * MATCH_EXACT (1) - search for an item, return index or LB_ERR - * MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision - */ - - COMPAREITEMSTRUCT16 *itemCmp; - LPLISTSTRUCT currentItem = NULL; - LPCSTR matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL; - int head, pos = -1, tail, loop = 1; - short b = 0, s_length = 0; - - /* check if empty */ - - if( !lphl->ItemsCount ) - return (exactMatch)? LB_ERR: 0; - - /* set up variables */ - - if( exactMatch == MATCH_NEAREST ) - startItem = 0; - else if( ++startItem ) - { - loop = 2; - if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1; - } - - if( exactMatch == MATCH_SUBSTR && lphl->HasStrings ) - { - s_length = strlen( matchStr ); - if( !s_length ) return 0; /* head of the list - empty string */ - } - - head = startItem; tail = lphl->ItemsCount - 1; - - dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData ); - - if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0; - itemCmp->CtlType = lphl->DrawCtlType; - itemCmp->CtlID = lphl->CtlID; - itemCmp->hwndItem = lphl->hSelf; - - /* search from startItem */ - - while ( loop-- ) - { - while( head <= tail ) - { - pos = (tail + head)/2; - currentItem = ListBoxGetItem( lphl, pos ); - - if( lphl->HasStrings ) - { - b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length) - : lstrcmpi32A( currentItem->itemText, matchStr); - } - else - { - itemCmp->itemID1 = pos; - itemCmp->itemData1 = currentItem->mis.itemData; - itemCmp->itemID2 = -1; - itemCmp->itemData2 = matchData; - - b = SendMessage16( lphl->hParent, WM_COMPAREITEM, - (WPARAM16)lphl->CtlID, - (LPARAM)SEGPTR_GET(itemCmp) ); - } - - if( b == 0 ) - { - SEGPTR_FREE(itemCmp); - return pos; /* found exact match */ - } - else - if( b < 0 ) head = ++pos; - else - if( b > 0 ) tail = pos - 1; - } - - /* reset to search from the first item */ - head = 0; tail = startItem - 1; - } - - dprintf_listbox(stddeb,"\t-> pos = %i\n", pos ); - SEGPTR_FREE(itemCmp); - - /* if we got here match is not exact */ - - if( pos < 0 ) pos = 0; - else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount; - - return (exactMatch)? LB_ERR: pos; -} - -int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr) -{ - LPLISTSTRUCT *lppls, lplsnew, lpls; - HANDLE16 hStr; - LPSTR str; - UINT Count; - - dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr); - - if (!newstr) return -1; - - if (uIndex == (UINT)-1) - uIndex = lphl->ItemsCount; - - lppls = &lphl->lpFirst; - for(Count = 0; Count < uIndex; Count++) { - if (*lppls == NULL) return LB_ERR; - lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext; - } - - lplsnew = ListBoxCreateItem(lphl, Count); - - if (lplsnew == NULL) { - fprintf(stdnimp,"ListBoxInsertString() out of memory !\n"); - return LB_ERRSPACE; - } - - lplsnew->lpNext = *lppls; - *lppls = lplsnew; - lphl->ItemsCount++; - - hStr = 0; - if (lphl->HasStrings) { - dprintf_listbox(stddeb," string: %s\n", newstr); - hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1); - str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr); - if (str == NULL) return LB_ERRSPACE; - strcpy(str, newstr); - lplsnew->itemText = str; - /* I'm not so sure about the next one */ - lplsnew->mis.itemData = 0; - } else { - lplsnew->itemText = NULL; - lplsnew->mis.itemData = (DWORD)newstr; - } - - lplsnew->mis.itemID = uIndex; - lplsnew->hData = hStr; - - /* adjust the itemID field of the following entries */ - for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) { - lpls->mis.itemID++; - } - - if (lphl->needMeasure) { - ListBoxAskMeasure(lphl, lplsnew); - } - - dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount); - return uIndex; -} - - -int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData) -{ - UINT pos = (UINT) -1; - LPCSTR newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData; - - if ( lphl->dwStyle & LBS_SORT ) - pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST ); - - return ListBoxInsertString(lphl, pos, newstr); -} - - -int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr) -{ - LPLISTSTRUCT lpls; - - if (!OutStr) { - dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n"); - return 0; - } - *OutStr = '\0'; - lpls = ListBoxGetItem (lphl, uIndex); - if (lpls == NULL) return LB_ERR; - - if (!lphl->HasStrings) { - *((long *)OutStr) = lpls->mis.itemData; - return 4; - } - - strcpy(OutStr, lpls->itemText); - return strlen(OutStr); -} - - -DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex) -{ - LPLISTSTRUCT lpls; - - lpls = ListBoxGetItem (lphl, uIndex); - if (lpls == NULL) return LB_ERR; - return lpls->mis.itemData; -} - - -int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData) -{ - LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex); - - if (lpls == NULL) return LB_ERR; - lpls->mis.itemData = ItemData; - return 1; -} - - -int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex) -{ - LPLISTSTRUCT lpls, lpls2; - UINT Count; - - if (uIndex >= lphl->ItemsCount) return LB_ERR; - - lpls = lphl->lpFirst; - if (lpls == NULL) return LB_ERR; - - if (uIndex == 0) - { - if( lphl->OwnerDrawn ) - lbDeleteItemNotify( lphl, lpls); - lphl->lpFirst = lpls->lpNext; - } - else - { - LPLISTSTRUCT lpls2 = NULL; - for(Count = 0; Count < uIndex; Count++) { - if (lpls->lpNext == NULL) return LB_ERR; - - lpls2 = lpls; - lpls = (LPLISTSTRUCT)lpls->lpNext; - } - if( lphl->OwnerDrawn ) - lbDeleteItemNotify( lphl, lpls); - lpls2->lpNext = lpls->lpNext; - } - - /* adjust the itemID field of the following entries */ - for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) { - lpls2->mis.itemID--; - } - - lphl->ItemsCount--; - - if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData); - free(lpls); - - return lphl->ItemsCount; -} - -int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match) -{ - /* match is either MATCH_SUBSTR or MATCH_EXACT */ - - LPLISTSTRUCT lpls; - UINT Count; - UINT First = nFirst + 1; - int s_length = 0; - LPSTR lpMatchStr = (LPSTR)MatchStr; - - if (First > lphl->ItemsCount) return LB_ERR; - - if (lphl->dwStyle & LBS_SORT ) - return ListBoxAskCompare( lphl, nFirst, MatchStr, match ); - - if (lphl->HasStrings ) - { - lpMatchStr = PTR_SEG_TO_LIN(MatchStr); - - if( match == MATCH_SUBSTR ) - { - s_length = strlen(lpMatchStr); - if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR; - } - } - - lpls = ListBoxGetItem(lphl, First); - Count = 0; - while(lpls != NULL) - { - if (lphl->HasStrings) - { - if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length) - : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count; + dis.CtlType = ODT_LISTBOX; + dis.CtlID = wnd->wIDmenu; + dis.hwndItem = wnd->hwndSelf; + dis.itemAction = action; + dis.hDC = hdc; + dis.itemID = index; + dis.itemState = 0; + if (item && item->selected) dis.itemState |= ODS_SELECTED; + if ((descr->focus_item == index) && + (descr->caret_on) && + (GetFocus32() == wnd->hwndSelf)) dis.itemState |= ODS_FOCUS; + if (wnd->dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED; + dis.itemData = item ? item->data : 0; + dis.rcItem = *rect; + dprintf_listbox( stddeb, "Listbox %04x: drawitem %d (%s) action=%02x " + "state=%02x rect=%d,%d-%d,%d\n", + wnd->hwndSelf, index, item ? item->str : "", action, + dis.itemState, rect->left, rect->top, + rect->right, rect->bottom ); + SendMessage32A(descr->owner, WM_DRAWITEM, wnd->wIDmenu, (LPARAM)&dis); } else - if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count; - - lpls = lpls->lpNext; - Count++; - } - - /* Start over at top */ - Count = 0; - lpls = lphl->lpFirst; - - while (Count < First) - { - if (lphl->HasStrings) { - if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length) - : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count; + if (action == ODA_FOCUS) + { + DrawFocusRect32( hdc, rect ); + return; + } + if (item && item->selected) + { + SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) ); + SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) ); + } + else + { + SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) ); + if (wnd->dwStyle & WS_DISABLED) + SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) ); + else + SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) ); + } + dprintf_listbox( stddeb, "Listbox %04x: painting %d (%s) action=%02x" + "rect=%d,%d-%d,%d\n", + wnd->hwndSelf, index, item ? item->str : "", action, + rect->left, rect->top, rect->right, rect->bottom ); + /* FIXME: check LBS_USETABSTOPS style */ + if (item) + ExtTextOut32A( hdc, rect->left + 1, rect->top + 1, + ETO_OPAQUE | ETO_CLIPPED, rect, item->str, + strlen(item->str), NULL ); + else + ExtTextOut32A( hdc, rect->left + 1, rect->top + 1, + ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL ); + if ((descr->focus_item == index) && + (descr->caret_on) && + (GetFocus32() == wnd->hwndSelf)) DrawFocusRect32( hdc, rect ); } - else - if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count; - - lpls = lpls->lpNext; - Count++; - } - - return LB_ERR; } -int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr) + +/*********************************************************************** + * LISTBOX_SetRedraw + * + * Change the redraw flag. + */ +static void LISTBOX_SetRedraw( WND *wnd, LB_DESCR *descr, BOOL32 on ) { - return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR ); -} - -int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr) -{ - return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT ); -} - -int ListBoxResetContent(LPHEADLIST lphl) -{ - LPLISTSTRUCT lpls; - int i; - - if (lphl->ItemsCount == 0) return 0; - - dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n", - lphl->ItemsCount); - - for(i = 0; i < lphl->ItemsCount; i++) { - lpls = lphl->lpFirst; - if (lpls == NULL) return LB_ERR; - - if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls); - - lphl->lpFirst = lpls->lpNext; - if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData); - free(lpls); + if (on) + { + if (!(descr->style & LBS_NOREDRAW)) return; + descr->style &= ~LBS_NOREDRAW; + LISTBOX_UpdateScroll( wnd, descr ); } - ListBoxInitialize(lphl); + else descr->style |= LBS_NOREDRAW; +} + +/*********************************************************************** + * LISTBOX_RepaintItem + * + * Repaint a single item synchronously. + */ +static void LISTBOX_RepaintItem( WND *wnd, LB_DESCR *descr, INT32 index, + UINT32 action ) +{ + HDC32 hdc; + RECT32 rect; + + if (descr->style & LBS_NOREDRAW) return; + if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return; + if ((hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE ))) + { + HFONT32 oldFont = 0; + if (descr->font) oldFont = SelectObject32( hdc, descr->font ); + SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL ); + LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action ); + if (oldFont) SelectObject32( hdc, oldFont ); + ReleaseDC32( wnd->hwndSelf, hdc ); + } +} + + +/*********************************************************************** + * LISTBOX_InitStorage + */ +static LRESULT LISTBOX_InitStorage( WND *wnd, LB_DESCR *descr, INT32 nb_items, + DWORD bytes ) +{ + LB_ITEMDATA *item; + + nb_items += LB_ARRAY_GRANULARITY - 1; + nb_items -= (nb_items % LB_ARRAY_GRANULARITY); + if (descr->items) + nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item); + if (!(item = HeapReAlloc( descr->heap, 0, descr->items, + nb_items * sizeof(LB_ITEMDATA) ))) + { + SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE ); + return LB_ERRSPACE; + } + descr->items = item; + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetTabStops + */ +static BOOL32 LISTBOX_SetTabStops( WND *wnd, LB_DESCR *descr, INT32 count, + LPINT32 tabs, BOOL32 short_ints ) +{ + if (!(descr->style & LBS_USETABSTOPS)) return TRUE; + if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs ); + if (!(descr->nb_tabs = count)) + { + descr->tabs = NULL; + return TRUE; + } + /* FIXME: count = 1 */ + if (!(descr->tabs = (INT32 *)HeapAlloc( descr->heap, 0, + descr->nb_tabs * sizeof(INT32) ))) + return FALSE; + if (short_ints) + { + INT32 i; + LPINT16 p = (LPINT16)tabs; + for (i = 0; i < descr->nb_tabs; i++) descr->tabs[i] = *p++; + } + else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT32) ); + /* FIXME: repaint the window? */ return TRUE; } -/* --------------------- selection ------------------------- */ -int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex) +/*********************************************************************** + * LISTBOX_GetText + */ +static LRESULT LISTBOX_GetText( WND *wnd, LB_DESCR *descr, INT32 index, + LPSTR buffer ) { - LPLISTSTRUCT lpls; - - /* use ListBoxSetSel instead */ - if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0; - - /* unselect previous item */ - if (lphl->ItemFocused != -1) { - lphl->PrevFocused = lphl->ItemFocused; - lpls = ListBoxGetItem(lphl, lphl->ItemFocused); - if (lpls == 0) return LB_ERR; - lpls->itemState = 0; - } - - if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount)) - { - lphl->ItemFocused = wIndex; - lpls = ListBoxGetItem(lphl, wIndex); - if (lpls == 0) return LB_ERR; - lpls->itemState = ODS_SELECTED | ODS_FOCUS; - - return 0; - } - - return LB_ERR; -} - - -int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state) -{ - LPLISTSTRUCT lpls; - int n = 0; - - if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) - return LB_ERR; - - if (wIndex == (UINT)-1) { - for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) { - if( lpls->itemState & ODS_SELECTED) n++; - lpls->itemState = state? lpls->itemState | ODS_SELECTED - : lpls->itemState & ~ODS_SELECTED; + if ((index < 0) || (index >= descr->nb_items)) return LB_ERR; + if (HAS_STRINGS(descr)) + { + lstrcpy32A( buffer, descr->items[index].str ); + return strlen(buffer); + } + else + { + memcpy( buffer, &descr->items[index].data, sizeof(DWORD) ); + return sizeof(DWORD); } - return n; - } - - if (wIndex >= lphl->ItemsCount) return LB_ERR; - - lpls = ListBoxGetItem(lphl, wIndex); - lpls->itemState = state? lpls->itemState | ODS_SELECTED - : lpls->itemState & ~ODS_SELECTED; - - return 0; } -int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex) +/*********************************************************************** + * LISTBOX_FindStringPos + * + * Find the nearest string located before a given string in sort order. + * If 'exact' is TRUE, return an error if we don't get an exact match. + */ +static INT32 LISTBOX_FindStringPos( WND *wnd, LB_DESCR *descr, LPCSTR str, + BOOL32 exact ) { - LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex); + INT32 index, min, max, res = -1; - if (lpls == NULL) return LB_ERR; - return lpls->itemState & ODS_SELECTED; + if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */ + min = 0; + max = descr->nb_items; + while (min != max) + { + index = (min + max) / 2; + if (HAS_STRINGS(descr)) + res = lstrcmpi32A( descr->items[index].str, str ); + else + { + COMPAREITEMSTRUCT32 cis; + cis.CtlType = ODT_LISTBOX; + cis.CtlID = wnd->wIDmenu; + cis.hwndItem = wnd->hwndSelf; + cis.itemID1 = index; + cis.itemData1 = descr->items[index].data; + cis.itemID2 = -1; + cis.itemData2 = (DWORD)str; + cis.dwLocaleId = descr->locale; + res = SendMessage32A( descr->owner, WM_COMPAREITEM, + wnd->wIDmenu, (LPARAM)&cis ); + } + if (!res) return index; + if (res > 0) max = index; + else min = index + 1; + } + return exact ? -1 : max; } -/* ------------------------- dir listing ------------------------ */ -LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec) +/*********************************************************************** + * LISTBOX_FindFileStrPos + * + * Find the nearest string located before a given string in directory + * sort order (i.e. first files, then directories, then drives). + */ +static INT32 LISTBOX_FindFileStrPos( WND *wnd, LB_DESCR *descr, LPCSTR str ) { - char mask[13]; - char* temp = NULL; - const char* ptr; - int skip, count; - LONG ret; - DOS_DIRENT entry; + INT32 min, max, res = -1; + + if (!HAS_STRINGS(descr)) + return LISTBOX_FindStringPos( wnd, descr, str, FALSE ); + min = 0; + max = descr->nb_items; + while (min != max) + { + INT32 index = (min + max) / 2; + const char *p = descr->items[index].str; + if (*p == '[') /* drive or directory */ + { + if (*str != '[') res = -1; + else if (p[1] == '-') /* drive */ + { + if (str[1] == '-') res = str[2] - p[2]; + else res = -1; + } + else /* directory */ + { + if (str[1] == '-') res = 1; + else res = lstrcmpi32A( str, p ); + } + } + else /* filename */ + { + if (*str == '[') res = 1; + else res = lstrcmpi32A( str, p ); + } + if (!res) return index; + if (res < 0) max = index; + else min = index + 1; + } + return max; +} + + +/*********************************************************************** + * LISTBOX_FindString + * + * Find the item beginning with a given string. + */ +static INT32 LISTBOX_FindString( WND *wnd, LB_DESCR *descr, INT32 start, + LPCSTR str, BOOL32 exact ) +{ + INT32 i; + LB_ITEMDATA *item; + + if (start >= descr->nb_items) start = -1; + item = descr->items + start + 1; + if (HAS_STRINGS(descr)) + { + if (exact) + { + for (i = start + 1; i < descr->nb_items; i++, item++) + if (!lstrcmpi32A( str, item->str )) return i; + for (i = 0, item = descr->items; i <= start; i++, item++) + if (!lstrcmpi32A( str, item->str )) return i; + } + else + { + /* Special case for drives and directories: ignore prefix */ +#define CHECK_DRIVE(item) \ + if ((item)->str[0] == '[') \ + { \ + if (!lstrncmpi32A( str, (item)->str+1, len )) return i; \ + if (((item)->str[1] == '-') && !lstrncmpi32A(str,(item)->str+2,len)) \ + return i; \ + } + + INT32 len = strlen(str); + for (i = start + 1; i < descr->nb_items; i++, item++) + { + if (!lstrncmpi32A( str, item->str, len )) return i; + CHECK_DRIVE(item); + } + for (i = 0, item = descr->items; i <= start; i++, item++) + { + if (!lstrncmpi32A( str, item->str, len )) return i; + CHECK_DRIVE(item); + } +#undef CHECK_DRIVE + } + } + else + { + if (exact && (descr->style & LBS_SORT)) + /* If sorted, use a WM_COMPAREITEM binary search */ + return LISTBOX_FindStringPos( wnd, descr, str, TRUE ); + + /* Otherwise use a linear search */ + for (i = start + 1; i < descr->nb_items; i++, item++) + if (item->data == (DWORD)str) return i; + for (i = 0, item = descr->items; i <= start; i++, item++) + if (item->data == (DWORD)str) return i; + } + return LB_ERR; +} + + +/*********************************************************************** + * LISTBOX_GetSelCount + */ +static LRESULT LISTBOX_GetSelCount( WND *wnd, LB_DESCR *descr ) +{ + INT32 i, count; + LB_ITEMDATA *item = descr->items; + + if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR; + for (i = count = 0; i < descr->nb_items; i++, item++) + if (item->selected) count++; + return count; +} + + +/*********************************************************************** + * LISTBOX_GetSelItems16 + */ +static LRESULT LISTBOX_GetSelItems16( WND *wnd, LB_DESCR *descr, INT16 max, + LPINT16 array ) +{ + INT32 i, count; + LB_ITEMDATA *item = descr->items; + + if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR; + for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++) + if (item->selected) array[count++] = (INT16)i; + return count; +} + + +/*********************************************************************** + * LISTBOX_GetSelItems32 + */ +static LRESULT LISTBOX_GetSelItems32( WND *wnd, LB_DESCR *descr, INT32 max, + LPINT32 array ) +{ + INT32 i, count; + LB_ITEMDATA *item = descr->items; + + if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR; + for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++) + if (item->selected) array[count++] = i; + return count; +} + + +/*********************************************************************** + * LISTBOX_Paint + */ +static LRESULT LISTBOX_Paint( WND *wnd, LB_DESCR *descr, HDC32 hdc ) +{ + INT32 i, col_pos = descr->page_size - 1; + RECT32 rect; + HFONT32 oldFont = 0; + + SetRect32( &rect, 0, 0, descr->width, descr->height ); + if (descr->style & LBS_NOREDRAW) return 0; + if (descr->style & LBS_MULTICOLUMN) + rect.right = rect.left + descr->column_width; + else if (descr->horz_pos) + { + SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL ); + rect.right += descr->horz_pos; + } + + if (descr->font) oldFont = SelectObject32( hdc, descr->font ); + + if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on && + (GetFocus32() == wnd->hwndSelf)) + { + /* Special case for empty listbox: paint focus rect */ + rect.bottom = rect.top + descr->item_height; + LISTBOX_PaintItem( wnd, descr, hdc, &rect, descr->focus_item, + ODA_DRAWENTIRE ); + rect.top = rect.bottom; + } + + for (i = descr->top_item; i < descr->nb_items; i++) + { + if (!(descr->style & LBS_OWNERDRAWVARIABLE)) + rect.bottom = rect.top + descr->item_height; + else + rect.bottom = rect.top + descr->items[i].height; + + LISTBOX_PaintItem( wnd, descr, hdc, &rect, i, ODA_DRAWENTIRE ); + rect.top = rect.bottom; + + if ((descr->style & LBS_MULTICOLUMN) && !col_pos) + { + if (!IS_OWNERDRAW(descr)) + { + /* Clear the bottom of the column */ + SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) ); + if (rect.top < descr->height) + { + rect.bottom = descr->height; + ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED, + &rect, NULL, 0, NULL ); + } + } + + /* Go to the next column */ + rect.left += descr->column_width; + rect.right += descr->column_width; + rect.top = 0; + col_pos = descr->page_size - 1; + } + else + { + col_pos--; + if (rect.top >= descr->height) break; + } + } + + if (!IS_OWNERDRAW(descr)) + { + /* Clear the remainder of the client area */ + SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) ); + if (rect.top < descr->height) + { + rect.bottom = descr->height; + ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED, + &rect, NULL, 0, NULL ); + } + if (rect.right < descr->width) + { + rect.left = rect.right; + rect.right = descr->width; + rect.top = 0; + rect.bottom = descr->height; + ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED, + &rect, NULL, 0, NULL ); + } + } + if (oldFont) SelectObject32( hdc, oldFont ); + return 0; +} + + +/*********************************************************************** + * LISTBOX_InvalidateItems + * + * Invalidate all items from a given item. If the specified item is not + * visible, nothing happens. + */ +static void LISTBOX_InvalidateItems( WND *wnd, LB_DESCR *descr, INT32 index ) +{ + RECT32 rect; + + if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) == 1) + { + rect.bottom = descr->height; + InvalidateRect32( wnd->hwndSelf, &rect, TRUE ); + if (descr->style & LBS_MULTICOLUMN) + { + /* Repaint the other columns */ + rect.left = rect.right; + rect.right = descr->width; + rect.top = 0; + InvalidateRect32( wnd->hwndSelf, &rect, TRUE ); + } + } +} + + +/*********************************************************************** + * LISTBOX_GetItemHeight + */ +static LRESULT LISTBOX_GetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index ) +{ + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + if ((index < 0) || (index >= descr->nb_items)) return LB_ERR; + return descr->items[index].height; + } + else return descr->item_height; +} + + +/*********************************************************************** + * LISTBOX_SetItemHeight + */ +static LRESULT LISTBOX_SetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index, + UINT32 height ) +{ + if (!height) height = 1; + + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + if ((index < 0) || (index >= descr->nb_items)) return LB_ERR; + dprintf_listbox( stddeb, "Listbox %04x: item %d height = %d\n", + wnd->hwndSelf, index, height ); + descr->items[index].height = height; + LISTBOX_UpdateScroll( wnd, descr ); + LISTBOX_InvalidateItems( wnd, descr, index ); + } + else if (height != descr->item_height) + { + dprintf_listbox( stddeb, "Listbox %04x: new height = %d\n", + wnd->hwndSelf, height ); + descr->item_height = height; + LISTBOX_UpdatePage( wnd, descr ); + LISTBOX_UpdateScroll( wnd, descr ); + InvalidateRect32( wnd->hwndSelf, 0, TRUE ); + } + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetHorizontalPos + */ +static void LISTBOX_SetHorizontalPos( WND *wnd, LB_DESCR *descr, INT32 pos ) +{ + INT32 diff; + + if (pos > descr->horz_extent - descr->width) + pos = descr->horz_extent - descr->width; + if (pos < 0) pos = 0; + if (!(diff = descr->horz_pos - pos)) return; + dprintf_listbox( stddeb, "Listbox %04x: new horz pos = %d\n", + wnd->hwndSelf, pos ); + descr->horz_pos = pos; + LISTBOX_UpdateScroll( wnd, descr ); + if (abs(diff) < descr->width) + ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL ); + else + InvalidateRect32( wnd->hwndSelf, NULL, TRUE ); +} + + +/*********************************************************************** + * LISTBOX_SetHorizontalExtent + */ +static LRESULT LISTBOX_SetHorizontalExtent( WND *wnd, LB_DESCR *descr, + UINT32 extent ) +{ + if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN)) + return LB_OKAY; + if (extent <= 0) extent = 1; + if (extent == descr->horz_extent) return LB_OKAY; + dprintf_listbox( stddeb, "Listbox %04x: new horz extent = %d\n", + wnd->hwndSelf, extent ); + descr->horz_extent = extent; + if (descr->horz_pos > extent - descr->width) + LISTBOX_SetHorizontalPos( wnd, descr, extent - descr->width ); + else + LISTBOX_UpdateScroll( wnd, descr ); + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetColumnWidth + */ +static LRESULT LISTBOX_SetColumnWidth( WND *wnd, LB_DESCR *descr, UINT32 width) +{ + width += 2; /* For left and right margin */ + if (width == descr->column_width) return LB_OKAY; + dprintf_listbox( stddeb, "Listbox %04x: new column width = %d\n", + wnd->hwndSelf, width ); + descr->column_width = width; + LISTBOX_UpdatePage( wnd, descr ); + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetFont + * + * Returns the item height. + */ +static INT32 LISTBOX_SetFont( WND *wnd, LB_DESCR *descr, HFONT32 font ) +{ + HDC32 hdc; + HFONT32 oldFont = 0; + TEXTMETRIC32A tm; + + descr->font = font; + + if (!(hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE ))) + { + fprintf( stderr, "LISTBOX_SetFont: unable to get DC\n" ); + return 16; + } + if (font) oldFont = SelectObject32( hdc, font ); + GetTextMetrics32A( hdc, &tm ); + if (oldFont) SelectObject32( hdc, oldFont ); + ReleaseDC32( wnd->hwndSelf, hdc ); + if (!IS_OWNERDRAW(descr)) + LISTBOX_SetItemHeight( wnd, descr, 0, tm.tmHeight + 2 ); + return tm.tmHeight + 2; +} + + +/*********************************************************************** + * LISTBOX_MakeItemVisible + * + * Make sure that a given item is partially or fully visible. + */ +static void LISTBOX_MakeItemVisible( WND *wnd, LB_DESCR *descr, INT32 index, + BOOL32 fully ) +{ + INT32 top; + + if (index <= descr->top_item) top = index; + else if (descr->style & LBS_MULTICOLUMN) + { + INT32 cols = descr->width; + if (!fully) cols += descr->column_width - 1; + if (cols >= descr->column_width) cols /= descr->column_width; + else cols = 1; + if (index < descr->top_item + (descr->page_size * cols)) return; + top = index - descr->page_size * (cols - 1); + } + else if (descr->style & LBS_OWNERDRAWVARIABLE) + { + INT32 height = fully ? descr->items[index].height : 1; + for (top = index; top > descr->top_item; top--) + if ((height += descr->items[top-1].height) > descr->height) break; + } + else + { + if (index < descr->top_item + descr->page_size) return; + if (!fully && (index == descr->top_item + descr->page_size) && + (descr->height > (descr->page_size * descr->item_height))) return; + top = index - descr->page_size + 1; + } + LISTBOX_SetTopItem( wnd, descr, top, TRUE ); +} + + +/*********************************************************************** + * LISTBOX_SelectItemRange + * + * Select a range of items. Should only be used on a MULTIPLESEL listbox. + */ +static LRESULT LISTBOX_SelectItemRange( WND *wnd, LB_DESCR *descr, INT32 first, + INT32 last, BOOL32 on ) +{ + INT32 i; + + /* A few sanity checks */ + + if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR; + if (last == -1) last = descr->nb_items - 1; + if ((first < 0) || (first >= descr->nb_items)) return LB_ERR; + if ((last < 0) || (last >= descr->nb_items)) return LB_ERR; + /* selected_item reflects last selected/unselected item on multiple sel */ + descr->selected_item = last; + + if (on) /* Turn selection on */ + { + for (i = first; i <= last; i++) + { + if (descr->items[i].selected) continue; + descr->items[i].selected = TRUE; + LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT ); + } + } + else /* Turn selection off */ + { + for (i = first; i <= last; i++) + { + if (!descr->items[i].selected) continue; + descr->items[i].selected = FALSE; + LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT ); + } + } + if (descr->style & LBS_NOTIFY) + SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE ); + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetCaretIndex + */ +static LRESULT LISTBOX_SetCaretIndex( WND *wnd, LB_DESCR *descr, INT32 index, + BOOL32 fully_visible ) +{ + INT32 oldfocus = descr->focus_item; + + if ((index < -1) || (index >= descr->nb_items)) return LB_ERR; + if (index == oldfocus) return LB_OKAY; + descr->focus_item = index; + if ((oldfocus != -1) && descr->caret_on && (GetFocus32() == wnd->hwndSelf)) + LISTBOX_RepaintItem( wnd, descr, oldfocus, ODA_FOCUS ); + if (index != -1) + { + LISTBOX_MakeItemVisible( wnd, descr, index, fully_visible ); + if (descr->caret_on && (GetFocus32() == wnd->hwndSelf)) + LISTBOX_RepaintItem( wnd, descr, index, ODA_FOCUS ); + } + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_SetSelection + */ +static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT32 index, + BOOL32 on, BOOL32 send_notify ) +{ + if ((index < -1) || (index >= descr->nb_items)) return LB_ERR; + if (descr->style & LBS_MULTIPLESEL) + { + if (index == -1) /* Select all items */ + return LISTBOX_SelectItemRange( wnd, descr, 0, -1, on ); + else /* Only one item */ + return LISTBOX_SelectItemRange( wnd, descr, index, index, on ); + } + else + { + INT32 oldsel = descr->selected_item; + if (index == oldsel) return LB_OKAY; + if (oldsel != -1) descr->items[oldsel].selected = FALSE; + if (index != -1) descr->items[index].selected = TRUE; + descr->selected_item = index; +/* FIXME if (index != -1) LISTBOX_MakeItemVisible( wnd, descr, index );*/ + if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT); + if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT ); + if (send_notify) SEND_NOTIFICATION( wnd, descr, + (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL ); + } + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_MoveCaret + * + * Change the caret position and extend the selection to the new caret. + */ +static void LISTBOX_MoveCaret( WND *wnd, LB_DESCR *descr, INT32 index, + BOOL32 fully_visible ) +{ + LISTBOX_SetCaretIndex( wnd, descr, index, fully_visible ); + if (descr->style & LBS_EXTENDEDSEL) + { + if (descr->anchor_item != -1) + { + INT32 first = MIN( descr->focus_item, descr->anchor_item ); + INT32 last = MAX( descr->focus_item, descr->anchor_item ); + if (first > 0) + LISTBOX_SelectItemRange( wnd, descr, 0, first - 1, FALSE ); + LISTBOX_SelectItemRange( wnd, descr, first, last, TRUE ); + LISTBOX_SelectItemRange( wnd, descr, last + 1, -1, FALSE ); + } + } + else if (!(descr->style & LBS_MULTIPLESEL) && (descr->selected_item != -1)) + { + /* Set selection to new caret item */ + LISTBOX_SetSelection( wnd, descr, index, TRUE, + (descr->style & LBS_NOTIFY) != 0 ); + } +} + + +/*********************************************************************** + * LISTBOX_InsertItem + */ +static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT32 index, + LPSTR str, DWORD data ) +{ + LB_ITEMDATA *item; + INT32 max_items; + + if (index == -1) index = descr->nb_items; + else if ((index < 0) || (index > descr->nb_items)) return LB_ERR; + if (!descr->items) max_items = 0; + else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item); + if (descr->nb_items == max_items) + { + /* We need to grow the array */ + max_items += LB_ARRAY_GRANULARITY; + if (!(item = HeapReAlloc( descr->heap, 0, descr->items, + max_items * sizeof(LB_ITEMDATA) ))) + { + SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE ); + return LB_ERRSPACE; + } + descr->items = item; + } + + /* Insert the item structure */ + + item = &descr->items[index]; + if (index < descr->nb_items) + RtlMoveMemory( item + 1, item, + (descr->nb_items - index) * sizeof(LB_ITEMDATA) ); + item->str = str; + item->data = data; + item->height = 0; + item->selected = FALSE; + descr->nb_items++; + + /* Get item height */ + + if (descr->style & LBS_OWNERDRAWVARIABLE) + { + MEASUREITEMSTRUCT32 mis; + mis.CtlType = ODT_LISTBOX; + mis.CtlID = wnd->wIDmenu; + mis.itemID = index; + mis.itemData = descr->items[index].data; + mis.itemHeight = descr->item_height; + SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu, + (LPARAM)&mis ); + item->height = mis.itemHeight ? mis.itemHeight : 1; + dprintf_listbox( stddeb, "Listbox %04x: measure item %d (%s) = %d\n", + wnd->hwndSelf, index, str ? str : "", item->height ); + } + + /* Repaint the items */ + + LISTBOX_UpdateScroll( wnd, descr ); + LISTBOX_InvalidateItems( wnd, descr, index ); + + /* Move selection and focused item */ + + if (index <= descr->selected_item) descr->selected_item++; + if (index <= descr->focus_item) + { + descr->focus_item++; + LISTBOX_MoveCaret( wnd, descr, descr->focus_item - 1, FALSE ); + } + + /* If listbox was empty, set focus to the first item */ + + if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE ); + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_InsertString + */ +static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT32 index, + LPCSTR str ) +{ + LPSTR new_str = NULL; + DWORD data = 0; + LRESULT ret; + + if (HAS_STRINGS(descr)) + { + if (!(new_str = HEAP_strdupA( descr->heap, 0, str ))) + { + SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE ); + return LB_ERRSPACE; + } + } + else data = (DWORD)str; + + if (index == -1) index = descr->nb_items; + if ((ret = LISTBOX_InsertItem( wnd, descr, index, new_str, data )) != 0) + { + if (new_str) HeapFree( descr->heap, 0, new_str ); + return ret; + } + + dprintf_listbox( stddeb, "Listbox %04x: added item %d '%s'\n", + wnd->hwndSelf, index, HAS_STRINGS(descr) ? new_str : "" ); + return index; +} + + +/*********************************************************************** + * LISTBOX_DeleteItem + * + * Delete the content of an item. 'index' must be a valid index. + */ +static void LISTBOX_DeleteItem( WND *wnd, LB_DESCR *descr, INT32 index ) +{ + /* Note: Win 3.1 only sends DELETEITEM on owner-draw items, + * while Win95 sends it for all items with user data. + * It's probably better to send it too often than not + * often enough, so this is what we do here. + */ + if (IS_OWNERDRAW(descr) || descr->items[index].data) + { + DELETEITEMSTRUCT32 dis; + dis.CtlType = ODT_LISTBOX; + dis.CtlID = wnd->wIDmenu; + dis.itemID = index; + dis.hwndItem = wnd->hwndSelf; + dis.itemData = descr->items[index].data; + SendMessage32A( wnd->hwndSelf, WM_DELETEITEM, wnd->wIDmenu, + (LPARAM)&dis ); + } + if (HAS_STRINGS(descr) && descr->items[index].str) + HeapFree( descr->heap, 0, descr->items[index].str ); +} + + +/*********************************************************************** + * LISTBOX_RemoveItem + * + * Remove an item from the listbox and delete its content. + */ +static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT32 index ) +{ + LB_ITEMDATA *item; + INT32 max_items; + + if (index == -1) index = descr->nb_items - 1; + else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR; + LISTBOX_DeleteItem( wnd, descr, index ); + + /* Remove the item */ + + item = &descr->items[index]; + if (index < descr->nb_items-1) + RtlMoveMemory( item, item + 1, + (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) ); + descr->nb_items--; + if (descr->anchor_item == descr->nb_items) descr->anchor_item--; + + /* Shrink the item array if possible */ + + max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA); + if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY) + { + max_items -= LB_ARRAY_GRANULARITY; + item = HeapReAlloc( descr->heap, 0, descr->items, + max_items * sizeof(LB_ITEMDATA) ); + if (item) descr->items = item; + } + + /* Repaint the items */ + + LISTBOX_UpdateScroll( wnd, descr ); + LISTBOX_InvalidateItems( wnd, descr, index ); + + /* Move selection and focused item */ + + if (index <= descr->selected_item) descr->selected_item--; + if (index <= descr->focus_item) + { + descr->focus_item--; + LISTBOX_MoveCaret( wnd, descr, descr->focus_item + 1, FALSE ); + } + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_ResetContent + */ +static void LISTBOX_ResetContent( WND *wnd, LB_DESCR *descr ) +{ + INT32 i; + + for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( wnd, descr, i ); + if (descr->items) HeapFree( descr->heap, 0, descr->items ); + descr->nb_items = 0; + descr->top_item = 0; + descr->selected_item = -1; + descr->focus_item = 0; + descr->anchor_item = -1; + descr->items = NULL; + LISTBOX_UpdateScroll( wnd, descr ); + InvalidateRect32( wnd->hwndSelf, NULL, TRUE ); +} + + +/*********************************************************************** + * LISTBOX_SetCount + */ +static LRESULT LISTBOX_SetCount( WND *wnd, LB_DESCR *descr, INT32 count ) +{ + LRESULT ret; + + if (HAS_STRINGS(descr)) return LB_ERR; + /* FIXME: this is far from optimal... */ + if (count > descr->nb_items) + { + while (count > descr->nb_items) + if ((ret = LISTBOX_InsertString( wnd, descr, -1, 0 )) < 0) + return ret; + } + else if (count < descr->nb_items) + { + while (count < descr->nb_items) + if ((ret = LISTBOX_RemoveItem( wnd, descr, -1 )) < 0) + return ret; + } + return LB_OKAY; +} + + +/*********************************************************************** + * LISTBOX_Directory + */ +LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT32 attrib, + LPCSTR filespec, BOOL32 long_names ) +{ + char mask[13]; + const char *ptr; char *path, *p; + int count, skip, pos; + LRESULT ret; + DOS_DIRENT entry; + + /* FIXME: should use FindFirstFile/FindNextFile */ - dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib); if (!filespec) return LB_ERR; if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR; - path = xstrdup(ptr); + path = HEAP_strdupA( SystemHeap, 0, ptr ); p = strrchr( path, '/' ); *p++ = '\0'; - if (!(ptr = DOSFS_ToDosFCBFormat( p )) || - !(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) ) + if (!(ptr = DOSFS_ToDosFCBFormat( p ))) { - free( path ); + HeapFree( SystemHeap, 0, path ); return LB_ERR; } - strcpy( mask, ptr ); - dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask); - - skip = ret = 0; + skip = 0; + ret = LB_OKAY; attrib &= ~FA_LABEL; while ((count = DOSFS_FindNext( path, mask, NULL, 0, attrib, skip, &entry )) > 0) { + char buffer[260]; skip += count; if (entry.attr & FA_DIRECTORY) { - if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". ")) - { - sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) ); - AnsiLower( temp ); - if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; - } + if (!(attrib & DDL_DIRECTORY) || !strcmp(entry.name,". ")) + continue; + if (long_names) sprintf( buffer, "[%s]", entry.unixname ); + else sprintf( buffer, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) ); } else /* not a directory */ { - if (!(attrib & DDL_EXCLUSIVE) || - ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) == + if ((attrib & DDL_EXCLUSIVE) && + ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) != (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)))) - { - strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) ); - AnsiLower( temp ); - if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; - } + continue; + if (long_names) strcpy( buffer, entry.unixname ); + else strcpy( buffer, DOSFS_ToDosDTAFormat( entry.name ) ); } - - dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp); + if (!long_names) AnsiLower( buffer ); + pos = LISTBOX_FindFileStrPos( wnd, descr, buffer ); + if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0) + break; } - if (attrib & DDL_DRIVES) + + if ((ret == LB_OKAY) && (attrib & DDL_DRIVES)) { - int x; - DWORD oldstyle = lphl->dwStyle; - - lphl->dwStyle &= ~LBS_SORT; - strcpy( temp, "[-a-]" ); - for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++) + char buffer[] = "[-a-]"; + int drive; + for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++) { - if (DRIVE_IsValid(x)) - if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; + if (!DRIVE_IsValid(drive)) continue; + if ((ret = LISTBOX_InsertString( wnd, descr, -1, buffer )) < 0) + break; } - lphl->dwStyle = oldstyle; } - free( path ); - SEGPTR_FREE( temp ); - + HeapFree( SystemHeap, 0, path ); return ret; } -/* ------------------------- dimensions ------------------------- */ -int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect) +/*********************************************************************** + * LISTBOX_HandleVScroll + */ +static LRESULT LISTBOX_HandleVScroll( WND *wnd, LB_DESCR *descr, + WPARAM32 wParam, LPARAM lParam ) { - LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex); + SCROLLINFO info; - dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls); - if (lpls == NULL) - { - if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE) - return LB_ERR; - else + if (descr->style & LBS_MULTICOLUMN) return 0; + switch(LOWORD(wParam)) { - GetClientRect16(lphl->hSelf,lprect); - lprect->bottom=lphl->StdItemHeight; - if (lprect->right<0) lprect->right=0; + case SB_LINEUP: + LISTBOX_SetTopItem( wnd, descr, descr->top_item - 1, TRUE ); + break; + case SB_LINEDOWN: + LISTBOX_SetTopItem( wnd, descr, descr->top_item + 1, TRUE ); + break; + case SB_PAGEUP: + LISTBOX_SetTopItem( wnd, descr, descr->top_item - + LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE ); + break; + case SB_PAGEDOWN: + LISTBOX_SetTopItem( wnd, descr, descr->top_item + + LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE ); + break; + case SB_THUMBPOSITION: + LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam), TRUE ); + break; + case SB_THUMBTRACK: + info.cbSize = sizeof(info); + info.fMask = SIF_TRACKPOS; + GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info ); + LISTBOX_SetTopItem( wnd, descr, info.nTrackPos, TRUE ); + break; + case SB_TOP: + LISTBOX_SetTopItem( wnd, descr, 0, TRUE ); + break; + case SB_BOTTOM: + LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE ); + break; } - } - else - *lprect = lpls->itemRect; - dprintf_listbox(stddeb," = %d,%d %d,%d\n", lprect->left,lprect->top, - lprect->right,lprect->bottom); - return 0; -} - - -int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height) -{ - LPLISTSTRUCT lpls; - - if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) { - lphl->StdItemHeight = (short)height; return 0; - } - - lpls = ListBoxGetItem(lphl, wIndex); - if (lpls == NULL) return LB_ERR; - - lpls->mis.itemHeight = height; - return 0; -} - -/* -------------------------- string search ------------------------ */ - -int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar) -{ - LPLISTSTRUCT lpls; - UINT count,first; - - if ((char)wChar < ' ') return LB_ERR; - if (!lphl->HasStrings) return LB_ERR; - - lpls = lphl->lpFirst; - - for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) { - if (tolower(*lpls->itemText) == tolower((char)wChar)) break; - } - if (lpls == NULL) return LB_ERR; - first = count; - for(; lpls != NULL; lpls = lpls->lpNext, count++) { - if (*lpls->itemText != (char)wChar) - break; - if ((short) count > lphl->ItemFocused) - return count; - } - return first; -} - -/*********************************************************************** - * LBCreate - */ -static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl; - LONG dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); - RECT16 rect; - - CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent16(hwnd)); - lphl = ListBoxGetStorageHeader(hwnd); - dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n", - lphl, HIWORD(dwStyle), LOWORD(dwStyle)); - - GetClientRect16(hwnd,&rect); - lphl->ColumnsWidth = rect.right - rect.left; - - if (dwStyle & WS_VSCROLL) - SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE); - if (dwStyle & WS_HSCROLL) - SetScrollRange32(hwnd, SB_HORZ, 1, 1, TRUE); - - return 0; } /*********************************************************************** - * LBDestroy + * LISTBOX_HandleHScroll */ -static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT LISTBOX_HandleHScroll( WND *wnd, LB_DESCR *descr, + WPARAM32 wParam, LPARAM lParam ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); + SCROLLINFO info; + INT32 page; - ListBoxResetContent(lphl); - - DestroyListBoxStruct(lphl); - dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl); - return 0; -} - - -/*********************************************************************** - * LBNCCalcSize - */ -static LONG LBNCCalcSize(HWND hwnd, WORD wParam, LONG lParam) -{ - LONG ret = DefWindowProc16(hwnd, WM_NCCALCSIZE, wParam, lParam); - - return (GetWindowLong32A(hwnd,GWL_STYLE) & LBS_MULTICOLUMN)? WVR_VREDRAW : ret; -} - - -/*********************************************************************** - * LBVScroll - */ -static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - int y; - - dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n", - wParam, lParam); - y = lphl->FirstVisible; - - switch(wParam) { - case SB_LINEUP: - if (lphl->FirstVisible > 0) - lphl->FirstVisible--; - break; - - case SB_LINEDOWN: - lphl->FirstVisible++; - break; - - case SB_PAGEUP: - if (lphl->FirstVisible > lphl->ItemsVisible) { - lphl->FirstVisible -= lphl->ItemsVisible; - } else { - lphl->FirstVisible = 0; + if (descr->style & LBS_MULTICOLUMN) + { + switch(LOWORD(wParam)) + { + case SB_LINELEFT: + LISTBOX_SetTopItem( wnd, descr, descr->top_item-descr->page_size, + TRUE ); + break; + case SB_LINERIGHT: + LISTBOX_SetTopItem( wnd, descr, descr->top_item+descr->page_size, + TRUE ); + break; + case SB_PAGELEFT: + page = descr->width / descr->column_width; + if (page < 1) page = 1; + LISTBOX_SetTopItem( wnd, descr, + descr->top_item - page * descr->page_size, TRUE ); + break; + case SB_PAGERIGHT: + page = descr->width / descr->column_width; + if (page < 1) page = 1; + LISTBOX_SetTopItem( wnd, descr, + descr->top_item + page * descr->page_size, TRUE ); + break; + case SB_THUMBPOSITION: + LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam)*descr->page_size, + TRUE ); + break; + case SB_THUMBTRACK: + info.cbSize = sizeof(info); + info.fMask = SIF_TRACKPOS; + GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info ); + LISTBOX_SetTopItem( wnd, descr, info.nTrackPos*descr->page_size, + TRUE ); + break; + case SB_LEFT: + LISTBOX_SetTopItem( wnd, descr, 0, TRUE ); + break; + case SB_RIGHT: + LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE ); + break; + } } - break; - - case SB_PAGEDOWN: - lphl->FirstVisible += lphl->ItemsVisible; - break; - - case SB_THUMBTRACK: - lphl->FirstVisible = LOWORD(lParam); - break; - } - - if (lphl->FirstVisible > ListMaxFirstVisible(lphl)) - lphl->FirstVisible = ListMaxFirstVisible(lphl); - - if (y != lphl->FirstVisible) { - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - InvalidateRect32( hwnd, NULL, TRUE ); - } - return 0; + else if (descr->horz_extent) + { + switch(LOWORD(wParam)) + { + case SB_LINELEFT: + LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos - 1 ); + break; + case SB_LINERIGHT: + LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos + 1 ); + break; + case SB_PAGELEFT: + LISTBOX_SetHorizontalPos( wnd, descr, + descr->horz_pos - descr->width ); + break; + case SB_PAGERIGHT: + LISTBOX_SetHorizontalPos( wnd, descr, + descr->horz_pos + descr->width ); + break; + case SB_THUMBPOSITION: + LISTBOX_SetHorizontalPos( wnd, descr, HIWORD(wParam) ); + break; + case SB_THUMBTRACK: + info.cbSize = sizeof(info); + info.fMask = SIF_TRACKPOS; + GetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info ); + LISTBOX_SetHorizontalPos( wnd, descr, info.nTrackPos ); + break; + case SB_LEFT: + LISTBOX_SetHorizontalPos( wnd, descr, 0 ); + break; + case SB_RIGHT: + LISTBOX_SetHorizontalPos( wnd, descr, + descr->horz_extent - descr->width ); + break; + } + } + return 0; } + /*********************************************************************** - * LBHScroll + * LISTBOX_HandleLButtonDown */ -static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT LISTBOX_HandleLButtonDown( WND *wnd, LB_DESCR *descr, + WPARAM32 wParam, INT32 x, INT32 y ) { - LPHEADLIST lphl; - int y; - - dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n", - wParam, lParam); - lphl = ListBoxGetStorageHeader(hwnd); - y = lphl->FirstVisible; - switch(wParam) { - case SB_LINEUP: - if (lphl->FirstVisible > lphl->ItemsPerColumn) { - lphl->FirstVisible -= lphl->ItemsPerColumn; - } else { - lphl->FirstVisible = 0; + INT32 index = LISTBOX_GetItemFromPoint( wnd, descr, x, y ); + dprintf_listbox( stddeb, "Listbox %04x: lbuttondown %d,%d item %d\n", + wnd->hwndSelf, x, y, index ); + if (!descr->caret_on && (GetFocus32() == wnd->hwndSelf)) return 0; + if (index != -1) + { + if (descr->style & LBS_EXTENDEDSEL) + { + if (!(wParam & MK_SHIFT)) descr->anchor_item = index; + if (wParam & MK_CONTROL) + { + LISTBOX_SetCaretIndex( wnd, descr, index, FALSE ); + LISTBOX_SetSelection( wnd, descr, index, + !descr->items[index].selected, + (descr->style & LBS_NOTIFY) != 0 ); + } + else LISTBOX_MoveCaret( wnd, descr, index, FALSE ); + } + else + { + LISTBOX_MoveCaret( wnd, descr, index, FALSE ); + LISTBOX_SetSelection( wnd, descr, index, + (!(descr->style & LBS_MULTIPLESEL) || + !descr->items[index].selected), + (descr->style & LBS_NOTIFY) != 0 ); + } } - break; - case SB_LINEDOWN: - lphl->FirstVisible += lphl->ItemsPerColumn; - break; - case SB_PAGEUP: - if (lphl->ItemsPerColumn != 0) { - int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn; - if (lphl->FirstVisible > lbsub) { - lphl->FirstVisible -= lbsub; - } else { - lphl->FirstVisible = 0; - } + SetFocus32( wnd->hwndSelf ); + SetCapture32( wnd->hwndSelf ); + if (index != -1) + { + if (descr->style & LBS_NOTIFY) + SendMessage32A( descr->owner, WM_LBTRACKPOINT, index, + MAKELPARAM( x, y ) ); + if (wnd->dwExStyle & WS_EX_DRAGDETECT) + { + POINT16 pt = { x, y }; + if (DragDetect( wnd->hwndSelf, pt )) + SendMessage32A( descr->owner, WM_BEGINDRAG, 0, 0 ); + } } - break; - case SB_PAGEDOWN: - if (lphl->ItemsPerColumn != 0) - lphl->FirstVisible += lphl->ItemsVisible / - lphl->ItemsPerColumn * lphl->ItemsPerColumn; - break; - case SB_THUMBTRACK: - lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam); - break; - } - if (lphl->FirstVisible > ListMaxFirstVisible(lphl)) - lphl->FirstVisible = ListMaxFirstVisible(lphl); - - if (lphl->ItemsPerColumn != 0) { - lphl->FirstVisible = lphl->FirstVisible / - lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1; - if (y != lphl->FirstVisible) { - SetScrollPos32(hwnd, SB_HORZ, lphl->FirstVisible / - lphl->ItemsPerColumn + 1, TRUE); - InvalidateRect32( hwnd, NULL, TRUE ); - } - } - return 0; + return 0; } -/*********************************************************************** - * LBLButtonDown - */ -static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - WORD wRet; - int y,n; - RECT16 rectsel; - - SetFocus32(hwnd); - SetCapture32(hwnd); - - lphl->PrevFocused = lphl->ItemFocused; - - y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam)); - - if (y == -1) return 0; - - if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR ) - if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) ) - return 0; - - - switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) - { - case LBS_MULTIPLESEL: - lphl->ItemFocused = y; - wRet = ListBoxGetSel(lphl, y); - ListBoxSetSel(lphl, y, !wRet); - break; - case LBS_EXTENDEDSEL: - /* should handle extended mode here and in kbd handler - */ - - if ( lphl->PrevFocused != y && y!= LB_ERR) - { - LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y ); - n = ListBoxSetSel(lphl,-1,FALSE); - - lpls->itemState = ODS_FOCUS | ODS_SELECTED; - - if( n > 1 && n != LB_ERR ) - InvalidateRect32( hwnd,NULL,TRUE ); - } - else - return 0; - - break; - case 0: - if( y!=lphl->ItemFocused ) - ListBoxSetCurSel(lphl, y); - else - return 0; - break; - default: - fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n"); - return 0; - } - - /* invalidate changed items */ - if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused ) - { - ListBoxGetItemRect(lphl, y, &rectsel); - InvalidateRect16( hwnd, &rectsel, TRUE ); - } - if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused ) - { - ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel); - InvalidateRect16( hwnd, &rectsel, TRUE ); - } - - if (GetWindowLong32A(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT) - if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) ) - SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L); - return 0; -} /*********************************************************************** - * LBLButtonUp - */ -static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - if (GetCapture32() == hwnd) ReleaseCapture(); - - if (lphl->PrevFocused != lphl->ItemFocused) - ListBoxSendNotification(lphl, LBN_SELCHANGE); - - return 0; -} - -/*********************************************************************** - * LBRButtonUp - */ -static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID), - MAKELONG(hwnd, LBN_DBLCLK)); - return 0; -} - -/*********************************************************************** - * LBMouseMove - */ -static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - int y,redraw_prev = 0; - int iRet; - RECT16 rect, rectsel; /* XXX Broken */ - - dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam)); - if ((wParam & MK_LBUTTON) != 0) { - y = SHIWORD(lParam); - if (y < LBMM_EDGE) { - if (lphl->FirstVisible > 0) { - lphl->FirstVisible--; - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - InvalidateRect32( hwnd, NULL, TRUE ); - return 0; - } - } - GetClientRect16(hwnd, &rect); - if (y >= (rect.bottom-LBMM_EDGE)) { - if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) { - lphl->FirstVisible++; - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - InvalidateRect32( hwnd, NULL, TRUE ); - return 0; - } - } - if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) { - if ((y < rectsel.top) || (y > rectsel.bottom)) { - iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam)); - if (iRet == lphl->ItemFocused || iRet == -1) { - return 0; - } - if (lphl->dwStyle & LBS_MULTIPLESEL) { - lphl->ItemFocused = iRet; - ListBoxSendNotification(lphl, LBN_SELCHANGE); - } else if ( lphl->dwStyle & LBS_EXTENDEDSEL ) - { - /* Fixme: extended selection mode */ - ListBoxSetSel( lphl, lphl->ItemFocused, 0); - lphl->PrevFocused = lphl->ItemFocused; - lphl->ItemFocused = iRet; - ListBoxSetSel( lphl, iRet, TRUE); - redraw_prev = 1; - } - else - { - ListBoxSetCurSel(lphl, (WORD)iRet); - redraw_prev = 1; - } - if( lphl->PrevFocused!=-1 && redraw_prev ) - { - ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel); - InvalidateRect16( hwnd, &rectsel, TRUE ); - } - ListBoxGetItemRect(lphl, iRet, &rectsel); - InvalidateRect16( hwnd, &rectsel, TRUE ); - } - } - } - - return 0; - } - -/*********************************************************************** - * LBKeyDown + * LISTBOX_HandleTimer * - * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL + * Handle scrolling upon a timer event. + * Return TRUE if scrolling should continue. */ -static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT LISTBOX_HandleTimer( WND *wnd, LB_DESCR *descr, + INT32 index, TIMER_DIRECTION dir ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - WORD newFocused = 0xFFFF; - RECT16 rect; - - ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect); - switch(wParam) + switch(dir) { - case VK_HOME: - case VK_END: - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_PRIOR: - case VK_NEXT: - if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT ) - { - newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM, - wParam,MAKELPARAM(lphl->ItemFocused,hwnd)); - if ( newFocused == 0xFFFE ) return 0L; - } - if ( newFocused == 0xFFFF ) - { - newFocused = lphl->ItemFocused; - - /* nested switch */ - switch(wParam) - { - case VK_HOME: - newFocused = 0; - break; - case VK_END: - newFocused = lphl->ItemsCount - 1; - break; - case VK_LEFT: - if (lphl->dwStyle & LBS_MULTICOLUMN) { - if (newFocused >= lphl->ItemsPerColumn) { - newFocused -= lphl->ItemsPerColumn; - } else { - newFocused = 0; - } - } - break; - case VK_UP: - if (newFocused > 0) newFocused--; - break; - case VK_RIGHT: - if (lphl->dwStyle & LBS_MULTICOLUMN) - newFocused += lphl->ItemsPerColumn; - break; - case VK_DOWN: - newFocused++; - break; - case VK_PRIOR: - if (newFocused > lphl->ItemsVisible) - newFocused -= lphl->ItemsVisible; - else newFocused = 0; - break; - case VK_NEXT: - newFocused += lphl->ItemsVisible; - break; - default: - return 0; - } - /* end of nested switch */ - } - break; - case VK_SPACE: - if (lphl->dwStyle & LBS_MULTIPLESEL) - { - WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused); - ListBoxSetSel(lphl, lphl->ItemFocused, !wRet); - } - return 0; - - /* chars are handled in LBChar */ - default: - return 0; + case LB_TIMER_UP: + if (descr->top_item) index = descr->top_item - 1; + else index = 0; + break; + case LB_TIMER_LEFT: + if (descr->top_item) index -= descr->page_size; + break; + case LB_TIMER_DOWN: + index = descr->top_item + LISTBOX_GetCurrentPageSize( wnd, descr ); + if (index >= descr->nb_items) index = descr->nb_items - 1; + break; + case LB_TIMER_RIGHT: + if (index + descr->page_size < descr->nb_items) + index += descr->page_size; + break; + case LB_TIMER_NONE: + break; } + if (index == descr->focus_item) return FALSE; + LISTBOX_MoveCaret( wnd, descr, index, FALSE ); + return TRUE; +} - /* at this point newFocused is set up */ - if (newFocused >= lphl->ItemsCount) - newFocused = lphl->ItemsCount - 1; - - if (!(lphl->dwStyle & LBS_MULTIPLESEL)) - { - ListBoxSetCurSel(lphl, newFocused); - ListBoxSendNotification(lphl, LBN_SELCHANGE); - } - - lphl->ItemFocused = newFocused; - - if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle & - (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ) - InvalidateRect32( hwnd, NULL, TRUE ); - else +/*********************************************************************** + * LISTBOX_HandleSystemTimer + * + * WM_SYSTIMER handler. + */ +static LRESULT LISTBOX_HandleSystemTimer( WND *wnd, LB_DESCR *descr ) +{ + if (!LISTBOX_HandleTimer( wnd, descr, descr->focus_item, LISTBOX_Timer )) { - InvalidateRect16( hwnd, &rect, TRUE ); - if( newFocused < 0x8000 ) - { - ListBoxGetItemRect(lphl, newFocused, &rect); - InvalidateRect16( hwnd, &rect, TRUE ); - } + KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID ); + LISTBOX_Timer = LB_TIMER_NONE; } - - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - - return 0; -} - -/*********************************************************************** - * LBChar - */ -static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - WORD newFocused = 0xFFFF; - - if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings)) - { - newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM, - wParam,MAKELPARAM(lphl->ItemFocused,hwnd)); - if ( newFocused == 0xFFFE ) return 0L; - } - - if (newFocused == 0xFFFF ) - newFocused = ListBoxFindNextMatch(lphl, wParam); - - if (newFocused == (WORD)LB_ERR) return 0; - - if (newFocused >= lphl->ItemsCount) - newFocused = lphl->ItemsCount - 1; - - if (!(lphl->dwStyle & LBS_MULTIPLESEL)) - { - ListBoxSetCurSel(lphl, newFocused); - ListBoxSendNotification(lphl, LBN_SELCHANGE); - } - - lphl->ItemFocused = newFocused; - ListBoxScrollToFocus(lphl); - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - - InvalidateRect32( hwnd, NULL, TRUE ); - - return 0; -} - -/*********************************************************************** - * LBSetRedraw - */ -static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n", - hwnd, wParam); - lphl->bRedrawFlag = wParam; - - return 0; -} - -/*********************************************************************** - * LBSetFont - */ -static LONG LBSetFont(HWND hwnd, WPARAM16 wParam, LPARAM lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - HDC32 hdc; - - if (wParam == 0) - lphl->hFont = GetStockObject32(SYSTEM_FONT); - else - lphl->hFont = (HFONT16)wParam; - - /* a new font means possible new text height */ - /* does this mean the height of each entry must be separately changed? */ - /* or are we guaranteed to get a LBSetFont before the first insert/add? */ - if ((hdc = GetDC32(0))) - { - TEXTMETRIC16 tm; - GetTextMetrics16( hdc, &tm ); - lphl->StdItemHeight = tm.tmHeight; - dprintf_listbox(stddeb,"LBSetFont: new font %d with height %d\n", - lphl->hFont, lphl->StdItemHeight); - ReleaseDC32( 0, hdc ); - } - - return 0; -} - -/*********************************************************************** - * LBPaint - */ -static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls; - PAINTSTRUCT16 ps; - HBRUSH16 hBrush; - HFONT32 hOldFont; - HDC16 hdc = BeginPaint16( hwnd, &ps ); - DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC); - RECT16 rect, paintRect, scratchRect; - int i, top, height, maxwidth, ipc; - - top = 0; - - if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) { - EndPaint16(hwnd, &ps); return 0; - } - - GetRgnBox16(dc->w.hGCClipRgn,&paintRect); - GetClientRect16(hwnd, &rect); - IntersectRect16(&paintRect,&rect,&paintRect); - - hOldFont = SelectObject32(hdc, lphl->hFont); - - hBrush = (HBRUSH16)SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX, - (WPARAM32)hdc, (LPARAM)hwnd); - if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH); - - FillRect16(hdc, &rect, hBrush); - - maxwidth = rect.right; - if (lphl->dwStyle & LBS_MULTICOLUMN) { - rect.right = lphl->ColumnsWidth; - } - lpls = lphl->lpFirst; - - lphl->ItemsVisible = 0; - lphl->ItemsPerColumn = ipc = 0; - - for(i = 0; i < lphl->ItemsCount; i++) { - if (lpls == NULL) break; - - if (i >= lphl->FirstVisible) { - height = lpls->mis.itemHeight; - - if (top > (rect.bottom-height+1)) { - if (lphl->dwStyle & LBS_MULTICOLUMN) { - lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc); - ipc = 0; - top = 0; - rect.left += lphl->ColumnsWidth; - rect.right += lphl->ColumnsWidth; - if (rect.left > maxwidth) break; - } else { - break; - } - } - - lpls->itemRect.top = top; - lpls->itemRect.bottom = top + height; - lpls->itemRect.left = rect.left; - lpls->itemRect.right = rect.right; - - if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) ) - { - dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n", - rect.left,top,rect.right,top+height,lpls->itemState); - - if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus32() == hwnd) - { - ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, - lpls->itemState & ~ODS_FOCUS); - ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, - lpls->itemState & ~ODS_FOCUS); - ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState); - } - else - ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, - lpls->itemState); - } - - top += height; - lphl->ItemsVisible++; - ipc++; - } - - lpls = lpls->lpNext; - } - ListBoxUpdateWindow(hwnd,lphl,FALSE); - SelectObject32(hdc,hOldFont); - EndPaint16( hwnd, &ps ); - return 0; } + /*********************************************************************** - * LBSetFocus + * LISTBOX_HandleMouseMove + * + * WM_MOUSEMOVE handler. */ -static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam) +static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr, + INT32 x, INT32 y ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); + INT32 index; + TIMER_DIRECTION dir; - dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd); - if(!(lphl->dwStyle & LBS_MULTIPLESEL) ) - if( lphl->ItemsCount && lphl->ItemFocused != -1) - { - HDC32 hDC = GetDC32(hwnd); - HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont); - LPLISTSTRUCT lpls; - - lpls = ListBoxGetItem(lphl,lphl->ItemFocused); - lpls->itemState |= ODS_FOCUS; - - ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState); - SelectObject32(hDC, hOldFont); - ReleaseDC32(hwnd,hDC); - } - - ListBoxSendNotification(lphl, LBN_SETFOCUS); - - return 0; -} - -/*********************************************************************** - * LBKillFocus - */ -static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd); - if (!(lphl->dwStyle & LBS_MULTIPLESEL)) - { - if( lphl->ItemsCount ) - if( lphl->ItemFocused != -1 ) - { - HDC32 hDC = GetDC32(hwnd); - HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont); - LPLISTSTRUCT lpls; - - lpls = ListBoxGetItem(lphl,lphl->ItemFocused); - lpls->itemState &= ~ODS_FOCUS; - - ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState); - SelectObject32(hDC, hOldFont); - ReleaseDC32(hwnd,hDC); - } - else - dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n"); - } - else - InvalidateRect32( hwnd, NULL, TRUE ); - - ListBoxSendNotification(lphl, LBN_KILLFOCUS); - - return 0; -} - -/*********************************************************************** - * LBResetContent - */ -static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n"); - ListBoxResetContent(lphl); - ListBoxUpdateWindow(hwnd, lphl, TRUE); - return 0; -} - -/*********************************************************************** - * LBDir - */ -static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam) -{ - LONG ret; - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - dprintf_listbox(stddeb,"ListBox LB_DIR !\n"); - - ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam)); - ListBoxUpdateWindow(hwnd, lphl, TRUE); - return ret; -} - -/*********************************************************************** - * LBAddString - */ -static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam) -{ - WORD wRet; - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - wRet = ListBoxAddString(lphl, (SEGPTR)lParam); - - ListBoxUpdateWindow(hwnd,lphl,TRUE); - return wRet; -} - -/*********************************************************************** - * LBGetText - */ -static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam) -{ - LONG wRet; - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - dprintf_listbox(stddeb, "LB_GETTEXT wParam=%d\n",wParam); - wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam)); - - return wRet; -} - -/*********************************************************************** - * LBInsertString - */ -static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam) -{ - WORD wRet; - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - if (lphl->HasStrings) - wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam)); - else - wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam); - - ListBoxUpdateWindow(hwnd,lphl,TRUE); - return wRet; -} - -/*********************************************************************** - * LBDeleteString - */ -static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LONG lRet = ListBoxDeleteString(lphl,wParam); - - ListBoxUpdateWindow(hwnd,lphl,TRUE); - return lRet; -} - -/*********************************************************************** - * LBFindString - */ -static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR); -} - -/*********************************************************************** - * LBFindStringExact - */ -static LONG LBFindStringExact(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_EXACT); -} - -/*********************************************************************** - * LBGetCaretIndex - */ -static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - return lphl->ItemFocused; -} - -/*********************************************************************** - * LBGetCount - */ -static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl; - - lphl = ListBoxGetStorageHeader(hwnd); - return lphl->ItemsCount; -} - -/*********************************************************************** - * LBGetCurSel - */ -static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl; - - lphl = ListBoxGetStorageHeader(hwnd); - dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n", - lphl->ItemFocused); - return lphl->ItemFocused; -} - -/*********************************************************************** - * LBGetHorizontalExtent - */ -static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam) -{ - return 0; -} - -/*********************************************************************** - * LBGetItemHeight - */ -static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam); - - if (lpls == NULL) return LB_ERR; - return lpls->mis.itemHeight; -} - -/*********************************************************************** - * LBGetItemRect - */ -static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam)); -} - -/*********************************************************************** - * LBGetSel - */ -static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - int iSel = ListBoxGetSel(lphl, wParam); - - dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel); - - return (iSel)? 1 : 0; -} - -/*********************************************************************** - * LBGetSelCount - */ -static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls; - int cnt = 0; - int items = 0; - - if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) - return LB_ERR; - - for( lpls = lphl->lpFirst; - lpls; - lpls = lpls->lpNext ) - { - items++; - if (lpls->itemState ) - cnt++; - } - - return cnt; -} - -/*********************************************************************** - * LBGetSelItems - */ -static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls; - int cnt, idx; - int *lpItems = PTR_SEG_TO_LIN(lParam); - - if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) - return LB_ERR; - - if (wParam == 0) return 0; - - lpls = lphl->lpFirst; - cnt = 0; idx = 0; - - while (lpls != NULL) { - if (lpls->itemState > 0) lpItems[cnt++] = idx; - - if (cnt == wParam) break; - idx++; - lpls = lpls->lpNext; - } - - return cnt; -} - -/*********************************************************************** - * LBGetTextLen - */ -static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam); - - if (lpls == NULL || !lphl->HasStrings) return LB_ERR; - return strlen(lpls->itemText); -} - -/*********************************************************************** - * LBGetDlgCode - */ -static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam) -{ - return DLGC_WANTARROWS | DLGC_WANTCHARS; -} - -/*********************************************************************** - * LBGetTopIndex - */ -static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - return lphl->FirstVisible; -} - - -/*********************************************************************** - * LBSelectString - */ -static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - INT iRet; - - iRet = lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR); - - if( iRet != LB_ERR) + if (descr->style & LBS_MULTICOLUMN) { - if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) - ListBoxSetSel(lphl,iRet,TRUE); - else - ListBoxSetCurSel(lphl,iRet); + if (y < 0) y = 0; + else if (y >= descr->item_height * descr->page_size) + y = descr->item_height * descr->page_size - 1; - lphl->ItemFocused = iRet; - InvalidateRect32( hwnd, 0, TRUE ); + if (x < 0) + { + dir = LB_TIMER_LEFT; + x = 0; + } + else if (x >= descr->width) + { + dir = LB_TIMER_RIGHT; + x = descr->width - 1; + } + else dir = LB_TIMER_NONE; /* inside */ } - return iRet; + else + { + if (y < 0) dir = LB_TIMER_UP; /* above */ + else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */ + else dir = LB_TIMER_NONE; /* inside */ + } + + index = LISTBOX_GetItemFromPoint( wnd, descr, x, y ); + if (index == -1) index = descr->focus_item; + if (!LISTBOX_HandleTimer( wnd, descr, index, dir )) dir = LB_TIMER_NONE; + + /* Start/stop the system timer */ + + if (dir != LB_TIMER_NONE) + SetSystemTimer32( wnd->hwndSelf, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL); + else if (LISTBOX_Timer != LB_TIMER_NONE) + KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID ); + LISTBOX_Timer = dir; } + /*********************************************************************** - * LBSelItemRange + * LISTBOX_HandleKeyDown */ -static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, + WPARAM32 wParam ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - LPLISTSTRUCT lpls; - WORD cnt; - WORD first = LOWORD(lParam); - WORD last = HIWORD(lParam); - BOOL select = wParam; - - if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) - return LB_ERR; - - if (first >= lphl->ItemsCount || - last >= lphl->ItemsCount) return LB_ERR; - - lpls = lphl->lpFirst; - cnt = 0; - - while (lpls != NULL) { - if (cnt++ >= first) - lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0; - - if (cnt > last) - break; - - lpls = lpls->lpNext; - } - - return 0; + INT32 caret = -1; + if (descr->style & LBS_WANTKEYBOARDINPUT) + { + caret = SendMessage32A( descr->owner, WM_VKEYTOITEM, + MAKEWPARAM(LOWORD(wParam), descr->focus_item), + wnd->hwndSelf ); + if (caret == -2) return 0; + } + if (caret == -1) switch(wParam) + { + case VK_LEFT: + if (descr->style & LBS_MULTICOLUMN) + { + if (descr->focus_item >= descr->page_size) + caret = descr->focus_item - descr->page_size; + break; + } + /* fall through */ + case VK_UP: + caret = descr->focus_item - 1; + if (caret < 0) caret = 0; + break; + case VK_RIGHT: + if (descr->style & LBS_MULTICOLUMN) + { + if (descr->focus_item + descr->page_size < descr->nb_items) + caret = descr->focus_item + descr->page_size; + break; + } + /* fall through */ + case VK_DOWN: + caret = descr->focus_item + 1; + if (caret >= descr->nb_items) caret = descr->nb_items - 1; + break; + case VK_PRIOR: + if (descr->style & LBS_MULTICOLUMN) + { + INT32 page = descr->width / descr->column_width; + if (page < 1) page = 1; + caret = descr->focus_item - (page * descr->page_size) + 1; + } + else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(wnd,descr)+1; + if (caret < 0) caret = 0; + break; + case VK_NEXT: + if (descr->style & LBS_MULTICOLUMN) + { + INT32 page = descr->width / descr->column_width; + if (page < 1) page = 1; + caret = descr->focus_item + (page * descr->page_size) - 1; + } + else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(wnd,descr)-1; + if (caret >= descr->nb_items) caret = descr->nb_items - 1; + break; + case VK_HOME: + caret = 0; + break; + case VK_END: + caret = descr->nb_items - 1; + break; + case VK_SPACE: + if (descr->style & LBS_EXTENDEDSEL) + { + if (!(GetKeyState(VK_SHIFT) & 0x8000)) + descr->anchor_item = descr->focus_item; + LISTBOX_MoveCaret( wnd, descr, descr->focus_item, TRUE ); + } + else if (descr->style & LBS_MULTIPLESEL) + LISTBOX_SetSelection( wnd, descr, descr->focus_item, + !descr->items[descr->focus_item].selected, + (descr->style & LBS_NOTIFY) != 0 ); + break; + } + if (caret >= 0) + { + if ((descr->style & LBS_EXTENDEDSEL) && + !(GetKeyState( VK_SHIFT ) & 0x8000)) + descr->anchor_item = caret; + LISTBOX_MoveCaret( wnd, descr, caret, TRUE ); + } + return 0; } + /*********************************************************************** - * LBSetCaretIndex + * LISTBOX_HandleChar */ -static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr, + WPARAM32 wParam ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - int i; + INT32 index; + char str[2] = { wParam & 0xff, '\0' }; - if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0; - - dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam); - - if (wParam >= lphl->ItemsCount) return LB_ERR; - - lphl->ItemFocused = wParam; - i = ListBoxScrollToFocus (lphl); - - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - if(i) - InvalidateRect32( hwnd, NULL, TRUE ); - - return 1; + index = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE ); + if (index != LB_ERR) LISTBOX_MoveCaret( wnd, descr, index, TRUE ); + return 0; } -/*********************************************************************** - * LBSetColumnWidth - */ -static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - lphl->ColumnsWidth = wParam; - InvalidateRect32( hwnd, NULL, TRUE ); - return 0; -} /*********************************************************************** - * LBSetHorizontalExtent + * LISTBOX_Create */ -static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam) +static BOOL32 LISTBOX_Create( WND *wnd ) { - return 0; -} + LB_DESCR *descr; + MEASUREITEMSTRUCT32 mis; + RECT32 rect; -/*********************************************************************** - * LBGetItemData - */ -static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam); - return ListBoxGetItemData(lphl, wParam); -} + if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) ))) + return FALSE; + if (!(descr->heap = HeapCreate( 0, 0x10000, 0 ))) + { + HeapFree( GetProcessHeap(), 0, descr ); + return FALSE; + } + GetClientRect32( wnd->hwndSelf, &rect ); + descr->owner = GetParent32( wnd->hwndSelf ); + descr->style = wnd->dwStyle; + descr->width = rect.right - rect.left; + descr->height = rect.bottom - rect.top; + descr->items = NULL; + descr->nb_items = 0; + descr->top_item = 0; + descr->selected_item = -1; + descr->focus_item = 0; + descr->anchor_item = -1; + descr->item_height = 1; + descr->page_size = 1; + descr->column_width = 150; + descr->horz_extent = (wnd->dwStyle & WS_HSCROLL) ? 1 : 0; + descr->horz_pos = 0; + descr->nb_tabs = 0; + descr->tabs = NULL; + descr->caret_on = TRUE; + descr->font = 0; + descr->locale = 0; /* FIXME */ -/*********************************************************************** - * LBSetItemData - */ -static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - dprintf_listbox(stddeb, "LB_SETITEMDATA wParam=%x lParam=%lx\n", wParam, lParam); - return ListBoxSetItemData(lphl, wParam, lParam); -} + *(LB_DESCR **)wnd->wExtra = descr; -/*********************************************************************** - * LBSetTabStops - */ -static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl; + if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL; + if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE; + if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT; + descr->item_height = LISTBOX_SetFont( wnd, descr, 0 ); - lphl = ListBoxGetStorageHeader(hwnd); + if (descr->style & LBS_OWNERDRAWFIXED) + { + mis.CtlType = ODT_LISTBOX; + mis.CtlID = wnd->wIDmenu; + mis.itemID = 0; + mis.itemWidth = 0; + mis.itemData = 0; + mis.itemHeight = descr->item_height; + SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu, + (LPARAM)&mis ); + descr->item_height = mis.itemHeight ? mis.itemHeight : 1; + } - if (lphl->TabStops != NULL) { - lphl->iNumStops = 0; - free (lphl->TabStops); - } - - lphl->TabStops = malloc (wParam * sizeof (short)); - if (lphl->TabStops) { - lphl->iNumStops = wParam; - memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short)); return TRUE; - } - - return FALSE; } + /*********************************************************************** - * LBSetCurSel + * LISTBOX_Destroy */ -static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam) +static BOOL32 LISTBOX_Destroy( WND *wnd, LB_DESCR *descr ) { - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - WORD wRet; - - dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", - wParam); - - wRet = ListBoxSetCurSel(lphl, wParam); - - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - InvalidateRect32( hwnd, NULL, TRUE ); - - return wRet; -} - -/*********************************************************************** - * LBSetSel - */ -static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - RECT16 rect; - int iRet; - - dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam); - - iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam); - - if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE ); - else if( iRet != LB_ERR ) - { - if( lphl->dwStyle & LBS_EXTENDEDSEL && - lphl->ItemFocused != LOWORD(lParam) ) - { - ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect); - InvalidateRect16( hwnd, &rect, TRUE ); - lphl->ItemFocused = LOWORD(lParam); - } - ListBoxGetItemRect(lphl,LOWORD(lParam),&rect); - InvalidateRect16( hwnd, &rect, TRUE ); - } - - return (iRet == (WORD)LB_ERR)? LB_ERR: 0; -} - -/*********************************************************************** - * LBSetTopIndex - */ -static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n", - wParam); - lphl->FirstVisible = wParam; - SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE); - - InvalidateRect32( hwnd, NULL, TRUE ); - - return 0; -} - -/*********************************************************************** - * LBSetItemHeight - */ -static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam) -{ - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - WORD wRet; - - dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam); - wRet = ListBoxSetItemHeight(lphl, wParam, lParam); - InvalidateRect32( hwnd, NULL, TRUE ); - return wRet; -} - -/*********************************************************************** - * LBPassToParent - */ -static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam) -{ - WND* ptrWnd = WIN_FindWndPtr(hwnd); - - if( ptrWnd ) - if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */ - ptrWnd->parent ) - return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam); - return 0; -} - -/*********************************************************************** - * ListBoxWndProc - */ -LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam) -{ - switch (message) { - case WM_CREATE: return LBCreate(hwnd, wParam, lParam); - case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam); - case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam); - case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam); - case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam); - case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam); - case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam); - case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam); - case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam); - case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam); - case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam); - case WM_CHAR: return LBChar(hwnd, wParam, lParam); - case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam); - case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam); - case WM_PAINT: return LBPaint(hwnd, wParam, lParam); - case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam); - case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam); - case WM_NCCALCSIZE: return LBNCCalcSize(hwnd, wParam, lParam); - case LB_RESETCONTENT16: return LBResetContent(hwnd, wParam, lParam); - case LB_DIR16: return LBDir(hwnd, wParam, lParam); - case LB_ADDSTRING16: return LBAddString(hwnd, wParam, lParam); - case LB_INSERTSTRING16: return LBInsertString(hwnd, wParam, lParam); - case LB_DELETESTRING16: return LBDeleteString(hwnd, wParam, lParam); - case LB_FINDSTRING16: return LBFindString(hwnd, wParam, lParam); - case LB_FINDSTRINGEXACT16: return LBFindStringExact(hwnd, wParam, lParam); - case LB_GETCARETINDEX16: return LBGetCaretIndex(hwnd, wParam, lParam); - case LB_GETCOUNT16: return LBGetCount(hwnd, wParam, lParam); - case LB_GETCURSEL16: return LBGetCurSel(hwnd, wParam, lParam); - case LB_GETHORIZONTALEXTENT16: return LBGetHorizontalExtent(hwnd, wParam, lParam); - case LB_GETITEMDATA16: return LBGetItemData(hwnd, wParam, lParam); - case LB_GETITEMHEIGHT16: return LBGetItemHeight(hwnd, wParam, lParam); - case LB_GETITEMRECT16: return LBGetItemRect(hwnd, wParam, lParam); - case LB_GETSEL16: return LBGetSel(hwnd, wParam, lParam); - case LB_GETSELCOUNT16: return LBGetSelCount(hwnd, wParam, lParam); - case LB_GETSELITEMS16: return LBGetSelItems(hwnd, wParam, lParam); - case LB_GETTEXT16: return LBGetText(hwnd, wParam, lParam); - case LB_GETTEXTLEN16: return LBGetTextLen(hwnd, wParam, lParam); - case LB_GETTOPINDEX16: return LBGetTopIndex(hwnd, wParam, lParam); - case LB_SELECTSTRING16: return LBSelectString(hwnd, wParam, lParam); - case LB_SELITEMRANGE16: return LBSelItemRange(hwnd, wParam, lParam); - case LB_SETCARETINDEX16: return LBSetCaretIndex(hwnd, wParam, lParam); - case LB_SETCOLUMNWIDTH16: return LBSetColumnWidth(hwnd, wParam, lParam); - case LB_SETHORIZONTALEXTENT16: return LBSetHorizontalExtent(hwnd, wParam, lParam); - case LB_SETITEMDATA16: return LBSetItemData(hwnd, wParam, lParam); - case LB_SETTABSTOPS16: return LBSetTabStops(hwnd, wParam, lParam); - case LB_SETCURSEL16: return LBSetCurSel(hwnd, wParam, lParam); - case LB_SETSEL16: return LBSetSel(hwnd, wParam, lParam); - case LB_SETTOPINDEX16: return LBSetTopIndex(hwnd, wParam, lParam); - case LB_SETITEMHEIGHT16: return LBSetItemHeight(hwnd, wParam, lParam); - - case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam); - - /* these will have to be implemented for proper LBS_EXTENDEDSEL - - * - * anchor item is an item that with caret (focused) item defines a - * range of currently selected items when listbox is in the extended - * selection mode. - */ - case LB_SETANCHORINDEX16: return LB_SETANCHORINDEX16; /* that's what Windows returns */ - case LB_GETANCHORINDEX16: return 0; - - case WM_DROPOBJECT: - case WM_QUERYDROPOBJECT: - case WM_DRAGSELECT: - case WM_DRAGMOVE: - { - LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam); - LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd); - - lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x, - lpDragInfo->pt.y); - - return LBPassToParent(hwnd, message, wParam, lParam); - } - } - - return DefWindowProc16(hwnd, message, wParam, lParam); -} - - -/********************************************************************** - * DlgDirList (USER.100) - */ -INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib ) -{ - char *filespec = (char *)PTR_SEG_TO_LIN( spec ); - int drive; - HWND hwnd; - -#define SENDMSG(msg,wparam,lparam) \ - ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \ - : SendMessage16( hwnd, msg, wparam, lparam )) - - dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n", - hDlg, filespec ? filespec : "NULL", - idLBox, idStatic, attrib ); - - if (filespec && filespec[0] && (filespec[1] == ':')) - { - drive = toupper( filespec[0] ) - 'A'; - filespec += 2; - if (!DRIVE_SetCurrentDrive( drive )) return FALSE; - } - else drive = DRIVE_GetCurrentDrive(); - - if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0)) - { - char mask[20]; - - if (!filespec || !filespec[0]) strcpy( mask, "*.*" ); - else - { - /* If the path exists and is a directory, chdir to it */ - if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" ); - else - { - char *p, *p2; - p = filespec; - if ((p2 = strrchr( p, '\\' ))) p = p2 + 1; - if ((p2 = strrchr( p, '/' ))) p = p2 + 1; - lstrcpyn32A( mask, p, sizeof(mask) ); - if (p != filespec) - { - p[-1] = '\0'; - if (!DRIVE_Chdir( drive, filespec )) return FALSE; - } - } - } - - strcpy( (char *)PTR_SEG_TO_LIN(spec), mask ); - - dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n", - 'A' + drive, DRIVE_GetDosCwd(drive), mask); - - SENDMSG( LB_RESETCONTENT16, 0, 0 ); - if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE)) - { - char *temp; - if (SENDMSG( LB_DIR16, attrib & ~(DDL_DIRECTORY | DDL_DRIVES), - (LPARAM)spec ) == LB_ERR) return FALSE; - if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE; - strcpy( temp, "*.*" ); - /* FIXME: this won't work with PostMessage(), as temp will */ - /* have been freed by the time we do a DispatchMessage(). */ - if (SENDMSG( LB_DIR16, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE, - (LPARAM)SEGPTR_GET(temp) ) == LB_ERR) - { - SEGPTR_FREE(temp); - return FALSE; - } - SEGPTR_FREE(temp); - } - else - { - if (SENDMSG( LB_DIR16, attrib, (LPARAM)spec) == LB_ERR) return FALSE; - } - } - - if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0)) - { - char temp[512]; - int drive = DRIVE_GetCurrentDrive(); - strcpy( temp, "A:\\" ); - temp[0] += drive; - lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 ); - AnsiLower( temp ); - /* Can't use PostMessage() here, because the string is on the stack */ - SetDlgItemText32A( hDlg, idStatic, temp ); - } + LISTBOX_ResetContent( wnd, descr ); + HeapDestroy( descr->heap ); + HeapFree( GetProcessHeap(), 0, descr ); + *(LB_DESCR **)wnd->wExtra = NULL; return TRUE; -#undef SENDMSG +} + + +/*********************************************************************** + * ListBoxWndProc + */ +LRESULT ListBoxWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam) +{ + LRESULT ret; + LB_DESCR *descr; + WND *wnd = WIN_FindWndPtr( hwnd ); + + if (!wnd) return 0; + if (!(descr = *(LB_DESCR **)wnd->wExtra)) + { + if (msg == WM_CREATE) + { + if (!LISTBOX_Create( wnd )) return -1; + dprintf_listbox( stddeb, "Listbox: creating wnd=%04x descr=%p\n", + hwnd, *(LB_DESCR **)wnd->wExtra ); + return 0; + } + /* Ignore all other messages before we get a WM_CREATE */ + return DefWindowProc32A( hwnd, msg, wParam, lParam ); + } + + dprintf_listbox( stddeb, "Listbox %04x: msg %s wp %08x lp %08lx\n", + wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam ); + switch(msg) + { + case LB_RESETCONTENT16: + case LB_RESETCONTENT32: + LISTBOX_ResetContent( wnd, descr ); + return 0; + + case LB_ADDSTRING16: + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_ADDSTRING32: + wParam = LISTBOX_FindStringPos( wnd, descr, (LPCSTR)lParam, FALSE ); + return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam ); + + case LB_INSERTSTRING16: + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + wParam = (INT32)(INT16)wParam; + /* fall through */ + case LB_INSERTSTRING32: + return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam ); + + case LB_ADDFILE16: + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_ADDFILE32: + wParam = LISTBOX_FindFileStrPos( wnd, descr, (LPCSTR)lParam ); + return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam ); + + case LB_DELETESTRING16: + case LB_DELETESTRING32: + return LISTBOX_RemoveItem( wnd, descr, wParam ); + + case LB_GETITEMDATA16: + case LB_GETITEMDATA32: + if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items)) + return LB_ERR; + return descr->items[wParam].data; + + case LB_SETITEMDATA16: + case LB_SETITEMDATA32: + if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items)) + return LB_ERR; + descr->items[wParam].data = (DWORD)lParam; + return LB_OKAY; + + case LB_GETCOUNT16: + case LB_GETCOUNT32: + return descr->nb_items; + + case LB_GETTEXT16: + lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_GETTEXT32: + return LISTBOX_GetText( wnd, descr, wParam, (LPSTR)lParam ); + + case LB_GETTEXTLEN16: + /* fall through */ + case LB_GETTEXTLEN32: + if (wParam >= descr->nb_items) return LB_ERR; + return (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str) + : sizeof(DWORD)); + + case LB_GETCURSEL16: + case LB_GETCURSEL32: + return descr->selected_item; + + case LB_GETTOPINDEX16: + case LB_GETTOPINDEX32: + return descr->top_item; + + case LB_GETITEMHEIGHT16: + case LB_GETITEMHEIGHT32: + return LISTBOX_GetItemHeight( wnd, descr, wParam ); + + case LB_SETITEMHEIGHT16: + lParam = LOWORD(lParam); + /* fall through */ + case LB_SETITEMHEIGHT32: + return LISTBOX_SetItemHeight( wnd, descr, wParam, lParam ); + + case LB_ITEMFROMPOINT32: + { + POINT32 pt = { LOWORD(lParam), HIWORD(lParam) }; + RECT32 rect = { 0, 0, descr->width, descr->height }; + return MAKELONG( LISTBOX_GetItemFromPoint(wnd, descr, pt.x, pt.y), + PtInRect32( &rect, pt ) ); + } + + case LB_SETCARETINDEX16: + case LB_SETCARETINDEX32: + return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam ); + + case LB_GETCARETINDEX16: + case LB_GETCARETINDEX32: + return descr->focus_item; + + case LB_SETTOPINDEX16: + case LB_SETTOPINDEX32: + return LISTBOX_SetTopItem( wnd, descr, wParam, TRUE ); + + case LB_SETCOLUMNWIDTH16: + case LB_SETCOLUMNWIDTH32: + return LISTBOX_SetColumnWidth( wnd, descr, wParam ); + + case LB_GETITEMRECT16: + { + RECT32 rect; + ret = LISTBOX_GetItemRect( wnd, descr, (INT16)wParam, &rect ); + CONV_RECT32TO16( &rect, (RECT16 *)PTR_SEG_TO_LIN(lParam) ); + } + return ret; + + case LB_GETITEMRECT32: + return LISTBOX_GetItemRect( wnd, descr, wParam, (RECT32 *)lParam ); + + case LB_FINDSTRING16: + wParam = (INT32)(INT16)wParam; + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_FINDSTRING32: + return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, FALSE ); + + case LB_FINDSTRINGEXACT16: + wParam = (INT32)(INT16)wParam; + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_FINDSTRINGEXACT32: + return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, TRUE ); + + case LB_SELECTSTRING16: + wParam = (INT32)(INT16)wParam; + if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam); + /* fall through */ + case LB_SELECTSTRING32: + { + INT32 index = LISTBOX_FindString( wnd, descr, wParam, + (LPCSTR)lParam, FALSE ); + if (index == LB_ERR) return LB_ERR; + LISTBOX_SetSelection( wnd, descr, index, TRUE, + (descr->style & LBS_NOTIFY) != 0 ); + return index; + } + + case LB_GETSEL16: + wParam = (INT32)(INT16)wParam; + /* fall through */ + case LB_GETSEL32: + if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items)) + return LB_ERR; + return descr->items[wParam].selected; + + case LB_SETSEL16: + lParam = (INT32)(INT16)lParam; + /* fall through */ + case LB_SETSEL32: + return LISTBOX_SetSelection( wnd, descr, lParam, wParam, + (descr->style & LBS_NOTIFY) != 0 ); + + case LB_SETCURSEL16: + wParam = (INT32)(INT16)wParam; + /* fall through */ + case LB_SETCURSEL32: + return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE ); + + case LB_GETSELCOUNT16: + case LB_GETSELCOUNT32: + return LISTBOX_GetSelCount( wnd, descr ); + + case LB_GETSELITEMS16: + return LISTBOX_GetSelItems16( wnd, descr, wParam, + (LPINT16)PTR_SEG_TO_LIN(lParam) ); + + case LB_GETSELITEMS32: + return LISTBOX_GetSelItems32( wnd, descr, wParam, (LPINT32)lParam ); + + case LB_SELITEMRANGE16: + case LB_SELITEMRANGE32: + return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam), + HIWORD(lParam), wParam ); + + case LB_SELITEMRANGEEX16: + case LB_SELITEMRANGEEX32: + if ((INT32)lParam >= (INT32)wParam) + return LISTBOX_SelectItemRange( wnd, descr, wParam, lParam, TRUE ); + else + return LISTBOX_SelectItemRange( wnd, descr, lParam, wParam, FALSE); + + case LB_GETHORIZONTALEXTENT16: + case LB_GETHORIZONTALEXTENT32: + return descr->horz_extent; + + case LB_SETHORIZONTALEXTENT16: + case LB_SETHORIZONTALEXTENT32: + return LISTBOX_SetHorizontalExtent( wnd, descr, wParam ); + + case LB_GETANCHORINDEX16: + case LB_GETANCHORINDEX32: + return descr->anchor_item; + + case LB_SETANCHORINDEX16: + wParam = (INT32)(INT16)wParam; + /* fall through */ + case LB_SETANCHORINDEX32: + if (((INT32)wParam < -1) || ((INT32)wParam >= descr->nb_items)) + return LB_ERR; + descr->anchor_item = (INT32)wParam; + return LB_OKAY; + + case LB_DIR16: + return LISTBOX_Directory( wnd, descr, wParam, + (LPCSTR)PTR_SEG_TO_LIN(lParam), FALSE ); + + case LB_DIR32: + return LISTBOX_Directory( wnd, descr, wParam, (LPCSTR)lParam, TRUE ); + + case LB_GETLOCALE32: + return descr->locale; + + case LB_SETLOCALE32: + descr->locale = (LCID)wParam; /* FIXME: should check for valid lcid */ + return LB_OKAY; + + case LB_INITSTORAGE32: + return LISTBOX_InitStorage( wnd, descr, wParam, (DWORD)lParam ); + + case LB_SETCOUNT32: + return LISTBOX_SetCount( wnd, descr, (INT32)wParam ); + + case LB_SETTABSTOPS16: + return LISTBOX_SetTabStops( wnd, descr, (INT32)(INT16)wParam, + (LPINT32)PTR_SEG_TO_LIN(lParam), TRUE ); + + case LB_SETTABSTOPS32: + return LISTBOX_SetTabStops( wnd, descr, wParam, + (LPINT32)lParam, FALSE ); + + case LB_CARETON16: + case LB_CARETON32: + if (descr->caret_on) return LB_OKAY; + descr->caret_on = TRUE; + if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf)) + LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS ); + return LB_OKAY; + + case LB_CARETOFF16: + case LB_CARETOFF32: + if (!descr->caret_on) return LB_OKAY; + descr->caret_on = FALSE; + if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf)) + LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS ); + return LB_OKAY; + + case WM_DESTROY: + return LISTBOX_Destroy( wnd, descr ); + + case WM_ENABLE: + InvalidateRect32( hwnd, NULL, TRUE ); + return 0; + + case WM_SETREDRAW: + LISTBOX_SetRedraw( wnd, descr, wParam != 0 ); + return 0; + + case WM_GETDLGCODE: + return DLGC_WANTARROWS | DLGC_WANTCHARS; + + case WM_PAINT: + { + PAINTSTRUCT32 ps; + HDC32 hdc = BeginPaint32( hwnd, &ps ); + ret = LISTBOX_Paint( wnd, descr, hdc ); + EndPaint32( hwnd, &ps ); + } + return ret; + + case WM_SIZE: + LISTBOX_UpdateSize( wnd, descr ); + return 0; + + case WM_GETFONT: + return descr->font; + + case WM_SETFONT: + LISTBOX_SetFont( wnd, descr, (HFONT32)wParam ); + if (lParam) InvalidateRect32( wnd->hwndSelf, 0, TRUE ); + return 0; + + case WM_SETFOCUS: + descr->caret_on = TRUE; + if (descr->focus_item != -1) + LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS ); + SEND_NOTIFICATION( wnd, descr, LBN_SETFOCUS ); + return 0; + + case WM_KILLFOCUS: + if ((descr->focus_item != -1) && descr->caret_on) + LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS ); + SEND_NOTIFICATION( wnd, descr, LBN_KILLFOCUS ); + return 0; + + case WM_HSCROLL: + return LISTBOX_HandleHScroll( wnd, descr, wParam, lParam ); + + case WM_VSCROLL: + return LISTBOX_HandleVScroll( wnd, descr, wParam, lParam ); + + case WM_LBUTTONDOWN: + return LISTBOX_HandleLButtonDown( wnd, descr, wParam, + (INT16)LOWORD(lParam), + (INT16)HIWORD(lParam) ); + + case WM_LBUTTONDBLCLK: + if (descr->style & LBS_NOTIFY) + SEND_NOTIFICATION( wnd, descr, LBN_DBLCLK ); + return 0; + + case WM_MOUSEMOVE: + if (GetCapture32() == hwnd) + LISTBOX_HandleMouseMove( wnd, descr, (INT16)LOWORD(lParam), + (INT16)HIWORD(lParam) ); + return 0; + + case WM_LBUTTONUP: + if (LISTBOX_Timer != LB_TIMER_NONE) + KillSystemTimer32( hwnd, LB_TIMER_ID ); + LISTBOX_Timer = LB_TIMER_NONE; + if (GetCapture32() == hwnd) ReleaseCapture(); + return 0; + + case WM_KEYDOWN: + return LISTBOX_HandleKeyDown( wnd, descr, wParam ); + + case WM_CHAR: + return LISTBOX_HandleChar( wnd, descr, wParam ); + + case WM_SYSTIMER: + return LISTBOX_HandleSystemTimer( wnd, descr ); + + case WM_ERASEBKGND: + if (IS_OWNERDRAW(descr)) + { + RECT32 rect = { 0, 0, descr->width, descr->height }; + HBRUSH32 hbrush = SendMessage32A( descr->owner, WM_CTLCOLORLISTBOX, + wParam, (LPARAM)wnd->hwndSelf ); + if (hbrush) FillRect32( (HDC32)wParam, &rect, hbrush ); + } + return 1; + + case WM_DROPFILES: + return SendMessage32A( descr->owner, msg, wParam, lParam ); + + case WM_DROPOBJECT: + case WM_QUERYDROPOBJECT: + case WM_DRAGSELECT: + case WM_DRAGMOVE: + { + LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam ); + dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x, + dragInfo->pt.y ); + return SendMessage32A( descr->owner, msg, wParam, lParam ); + } + + default: + if ((msg >= WM_USER) && (msg < 0xc000)) + fprintf(stderr,"Listbox %04x: unknown msg %04x wp %08x lp %08lx\n", + hwnd, msg, wParam, lParam ); + return DefWindowProc32A( hwnd, msg, wParam, lParam ); + } + return 0; } diff --git a/controls/menu.c b/controls/menu.c index 59cee2894b3..fd5bb8a13ef 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -84,8 +84,8 @@ static BOOL fEndMenuCalled = FALSE; #define NO_SELECTED_ITEM 0xffff #define SYSMENU_SELECTED 0xfffe /* Only valid on menu-bars */ -#define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \ - MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR))) +#define IS_STRING_ITEM(flags) \ + (!((flags) & (MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))) extern void NC_DrawSysButton(HWND hwnd, HDC32 hdc, BOOL down); /*nonclient.c*/ extern BOOL NC_GetSysPopupPos(WND* wndPtr, RECT16* rect); @@ -1923,8 +1923,9 @@ BOOL32 TrackPopupMenu32( HMENU32 hMenu, UINT32 wFlags, INT32 x, INT32 y, INT32 nReserved, HWND32 hWnd, const RECT32 *lpRect ) { RECT16 r; - CONV_RECT32TO16( lpRect, &r ); - return TrackPopupMenu16( hMenu, wFlags, x, y, nReserved, hWnd, &r ); + if (lpRect) + CONV_RECT32TO16( lpRect, &r ); + return TrackPopupMenu16(hMenu,wFlags,x,y,nReserved,hWnd,lpRect?&r:NULL); } diff --git a/controls/oldlbox.c b/controls/oldlbox.c new file mode 100644 index 00000000000..d7a7547ea1b --- /dev/null +++ b/controls/oldlbox.c @@ -0,0 +1,843 @@ +/* + * Listbox controls + * + * Copyright Martin Ayotte, 1993 + * Constantine Sapuntzakis, 1995 + * Alex Korobka, 1995, 1996 + * + */ + + /* + * FIXME: + * - proper scrolling for multicolumn style + * - anchor and caret for LBS_EXTENDEDSEL + * - proper selection with keyboard + * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style + * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles + */ + +#include +#include +#include +#include +#include "windows.h" +#include "win.h" +#include "gdi.h" +#include "msdos.h" +#include "listbox.h" +#include "dos_fs.h" +#include "drive.h" +#include "file.h" +#include "heap.h" +#include "stddebug.h" +#include "debug.h" +#include "xmalloc.h" + +#define LIST_HEAP_ALLOC(lphl,f,size) \ + LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) ) +#define LIST_HEAP_FREE(lphl,handle) \ + LOCAL_Free( lphl->HeapSel, (handle) ) +#define LIST_HEAP_ADDR(lphl,handle) \ + ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL) + +#define LIST_HEAP_SIZE 0x10000 + +#define LBMM_EDGE 4 /* distance inside box which is same as moving mouse + outside box, to trigger scrolling of LB */ + +#define MATCH_SUBSTR 2 +#define MATCH_EXACT 1 +#define MATCH_NEAREST 0 + +static void ListBoxInitialize(LPHEADLIST lphl) +{ + lphl->lpFirst = NULL; + lphl->ItemsCount = 0; + lphl->ItemsVisible = 0; + lphl->FirstVisible = 0; + lphl->ColumnsVisible = 1; + lphl->ItemsPerColumn = 0; + lphl->ItemFocused = -1; + lphl->PrevFocused = -1; +} + +void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent) +{ + LPHEADLIST lphl; + HDC32 hdc; + + lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST)); + SetWindowLong32A(hwnd, 0, (LONG)lphl); + ListBoxInitialize(lphl); + lphl->DrawCtlType = CtlType; + lphl->CtlID = GetWindowWord(hwnd,GWW_ID); + lphl->bRedrawFlag = TRUE; + lphl->iNumStops = 0; + lphl->TabStops = NULL; + lphl->hFont = GetStockObject32(SYSTEM_FONT); + lphl->hSelf = hwnd; + if (CtlType==ODT_COMBOBOX) /* use the "faked" style for COMBOLBOX */ + /* LBS_SORT instead CBS_SORT e.g. */ + lphl->dwStyle = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE))); + else + lphl->dwStyle = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */ + lphl->hParent = parent; + lphl->StdItemHeight = 15; /* FIXME: should get the font height */ + lphl->OwnerDrawn = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE); + lphl->HasStrings = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn; + + /* create dummy hdc to set text height */ + if ((hdc = GetDC32(0))) + { + TEXTMETRIC16 tm; + GetTextMetrics16( hdc, &tm ); + lphl->StdItemHeight = tm.tmHeight; + dprintf_listbox(stddeb,"CreateListBoxStruct: font height %d\n", + lphl->StdItemHeight); + ReleaseDC32( 0, hdc ); + } + + if (lphl->OwnerDrawn) + { + LISTSTRUCT dummyls; + + lphl->needMeasure = TRUE; + dummyls.mis.CtlType = lphl->DrawCtlType; + dummyls.mis.CtlID = lphl->CtlID; + dummyls.mis.itemID = -1; + dummyls.mis.itemWidth = 0; /* ignored */ + dummyls.mis.itemData = 0; + + ListBoxAskMeasure(lphl,&dummyls); + } + + lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE); + LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1); +} + +/* Send notification "code" as part of a WM_COMMAND-message if hwnd + has the LBS_NOTIFY style */ +void ListBoxSendNotification(LPHEADLIST lphl, WORD code) +{ + if (lphl->dwStyle & LBS_NOTIFY) + SendMessage32A( lphl->hParent, WM_COMMAND, + MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf ); +} + + +/* get the maximum value of lphl->FirstVisible */ +int ListMaxFirstVisible(LPHEADLIST lphl) +{ + int m = lphl->ItemsCount-lphl->ItemsVisible; + return (m < 0) ? 0 : m; +} + + +/* Returns: 0 if nothing needs to be changed */ +/* 1 if FirstVisible changed */ + +int ListBoxScrollToFocus(LPHEADLIST lphl) +{ + short end; + + if (lphl->ItemsCount == 0) return 0; + if (lphl->ItemFocused == -1) return 0; + + end = lphl->FirstVisible + lphl->ItemsVisible - 1; + + if (lphl->ItemFocused < lphl->FirstVisible ) { + lphl->FirstVisible = lphl->ItemFocused; + return 1; + } else { + if (lphl->ItemFocused > end) { + WORD maxFirstVisible = ListMaxFirstVisible(lphl); + + lphl->FirstVisible = lphl->ItemFocused; + + if (lphl->FirstVisible > maxFirstVisible) { + lphl->FirstVisible = maxFirstVisible; + } + return 1; + } + } + return 0; +} + + +LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex) +{ + LPLISTSTRUCT lpls; + UINT Count = 0; + + if (uIndex >= lphl->ItemsCount) return NULL; + + lpls = lphl->lpFirst; + while (Count++ < uIndex) lpls = lpls->lpNext; + return lpls; +} + + +void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls, + RECT16 *rect, WORD itemAction, WORD itemState) +{ + if (lphl->OwnerDrawn) + { + DRAWITEMSTRUCT32 dis; + + dis.CtlID = lpls->mis.CtlID; + dis.CtlType = lpls->mis.CtlType; + dis.itemID = lpls->mis.itemID; + dis.hDC = hdc; + dis.hwndItem = hwnd; + dis.itemData = lpls->mis.itemData; + dis.itemAction = itemAction; + dis.itemState = itemState; + CONV_RECT16TO32( rect, &dis.rcItem ); + SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis ); + return; + } + if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) { + int OldBkMode; + DWORD dwOldTextColor = 0; + + OldBkMode = SetBkMode(hdc, TRANSPARENT); + + if (itemState != 0) { + dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL); + FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH)); + } + + if (lphl->dwStyle & LBS_USETABSTOPS) { + TabbedTextOut(hdc, rect->left + 5, rect->top + 2, + (char *)lpls->itemText, strlen((char *)lpls->itemText), + lphl->iNumStops, lphl->TabStops, 0); + } else { + TextOut16(hdc, rect->left + 5, rect->top + 2, + (char *)lpls->itemText, strlen((char *)lpls->itemText)); + } + + if (itemState != 0) { + SetTextColor(hdc, dwOldTextColor); + } + + SetBkMode(hdc, OldBkMode); + } + else DrawFocusRect16(hdc, rect); +} + + +int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y) +{ + LPLISTSTRUCT lpls = lphl->lpFirst; + int i, j; + POINT16 point; + + point.x = X; point.y = Y; + if (lphl->ItemsCount == 0) return LB_ERR; + + for(i = 0; i < lphl->FirstVisible; i++) { + if (lpls == NULL) return LB_ERR; + lpls = lpls->lpNext; + } + for(j = 0; j < lphl->ItemsVisible; i++, j++) { + if (lpls == NULL) return LB_ERR; + if (PtInRect16(&lpls->itemRect,point)) { + return i; + } + lpls = lpls->lpNext; + } + dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n"); + return LB_ERR; +} + +BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls) +{ + /* called only for owner drawn listboxes */ + BOOL32 ret; + DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16); + if (!delItem) return FALSE; + + delItem->CtlType = lphl->DrawCtlType; + delItem->CtlID = lphl->CtlID; + delItem->itemID = lpls->mis.itemID; + delItem->hwndItem = lphl->hSelf; + delItem->itemData = lpls->mis.itemData; + + ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID, + (LPARAM)SEGPTR_GET(delItem) ); + SEGPTR_FREE(delItem); + return ret; +} + +/* -------------------- strings and item data ---------------------- */ + +void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls) +{ + MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16); + if (!lpmeasure) return; + *lpmeasure = lpls->mis; + lpmeasure->itemHeight = lphl->StdItemHeight; + SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID, + (LPARAM)SEGPTR_GET(lpmeasure) ); + + if (lphl->dwStyle & LBS_OWNERDRAWFIXED) + { + if (lpmeasure->itemHeight > lphl->StdItemHeight) + lphl->StdItemHeight = lpmeasure->itemHeight; + lpls->mis.itemHeight = lpmeasure->itemHeight; + } + SEGPTR_FREE(lpmeasure); +} + +static LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id) +{ + LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT)); + + if (lplsnew == NULL) return NULL; + + lplsnew->itemState = 0; + lplsnew->mis.CtlType = lphl->DrawCtlType; + lplsnew->mis.CtlID = lphl->CtlID; + lplsnew->mis.itemID = id; + lplsnew->mis.itemHeight = lphl->StdItemHeight; + lplsnew->mis.itemWidth = 0; /* ignored */ + lplsnew->mis.itemData = 0; + SetRectEmpty16( &lplsnew->itemRect ); + + return lplsnew; +} + +static int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch ) +{ + /* Do binary search for sorted listboxes. Linked list item storage sort of + * defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way... + * + * MATCH_NEAREST (0) - return position for insertion - for all styles + * MATCH_EXACT (1) - search for an item, return index or LB_ERR + * MATCH_SUBSTR (2) - same as exact match but with strncmp for string comparision + */ + + COMPAREITEMSTRUCT16 *itemCmp; + LPLISTSTRUCT currentItem = NULL; + LPCSTR matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL; + int head, pos = -1, tail, loop = 1; + short b = 0, s_length = 0; + + /* check if empty */ + + if( !lphl->ItemsCount ) + return (exactMatch)? LB_ERR: 0; + + /* set up variables */ + + if( exactMatch == MATCH_NEAREST ) + startItem = 0; + else if( ++startItem ) + { + loop = 2; + if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1; + } + + if( exactMatch == MATCH_SUBSTR && lphl->HasStrings ) + { + s_length = strlen( matchStr ); + if( !s_length ) return 0; /* head of the list - empty string */ + } + + head = startItem; tail = lphl->ItemsCount - 1; + + dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData ); + + if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0; + itemCmp->CtlType = lphl->DrawCtlType; + itemCmp->CtlID = lphl->CtlID; + itemCmp->hwndItem = lphl->hSelf; + + /* search from startItem */ + + while ( loop-- ) + { + while( head <= tail ) + { + pos = (tail + head)/2; + currentItem = ListBoxGetItem( lphl, pos ); + + if( lphl->HasStrings ) + { + b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length) + : lstrcmpi32A( currentItem->itemText, matchStr); + } + else + { + itemCmp->itemID1 = pos; + itemCmp->itemData1 = currentItem->mis.itemData; + itemCmp->itemID2 = -1; + itemCmp->itemData2 = matchData; + + b = SendMessage16( lphl->hParent, WM_COMPAREITEM, + (WPARAM16)lphl->CtlID, + (LPARAM)SEGPTR_GET(itemCmp) ); + } + + if( b == 0 ) + { + SEGPTR_FREE(itemCmp); + return pos; /* found exact match */ + } + else + if( b < 0 ) head = ++pos; + else + if( b > 0 ) tail = pos - 1; + } + + /* reset to search from the first item */ + head = 0; tail = startItem - 1; + } + + dprintf_listbox(stddeb,"\t-> pos = %i\n", pos ); + SEGPTR_FREE(itemCmp); + + /* if we got here match is not exact */ + + if( pos < 0 ) pos = 0; + else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount; + + return (exactMatch)? LB_ERR: pos; +} + +int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr) +{ + LPLISTSTRUCT *lppls, lplsnew, lpls; + HANDLE16 hStr; + LPSTR str; + UINT Count; + + dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr); + + if (!newstr) return -1; + + if (uIndex == (UINT)-1) + uIndex = lphl->ItemsCount; + + lppls = &lphl->lpFirst; + for(Count = 0; Count < uIndex; Count++) { + if (*lppls == NULL) return LB_ERR; + lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext; + } + + lplsnew = ListBoxCreateItem(lphl, Count); + + if (lplsnew == NULL) { + fprintf(stdnimp,"ListBoxInsertString() out of memory !\n"); + return LB_ERRSPACE; + } + + lplsnew->lpNext = *lppls; + *lppls = lplsnew; + lphl->ItemsCount++; + + hStr = 0; + if (lphl->HasStrings) { + dprintf_listbox(stddeb," string: %s\n", newstr); + hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1); + str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr); + if (str == NULL) return LB_ERRSPACE; + strcpy(str, newstr); + lplsnew->itemText = str; + /* I'm not so sure about the next one */ + lplsnew->mis.itemData = 0; + } else { + lplsnew->itemText = NULL; + lplsnew->mis.itemData = (DWORD)newstr; + } + + lplsnew->mis.itemID = uIndex; + lplsnew->hData = hStr; + + /* adjust the itemID field of the following entries */ + for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) { + lpls->mis.itemID++; + } + + if (lphl->needMeasure) { + ListBoxAskMeasure(lphl, lplsnew); + } + + dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount); + return uIndex; +} + + +int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData) +{ + UINT pos = (UINT) -1; + LPCSTR newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData; + + if ( lphl->dwStyle & LBS_SORT ) + pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST ); + + return ListBoxInsertString(lphl, pos, newstr); +} + + +int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr) +{ + LPLISTSTRUCT lpls; + + if (!OutStr) { + dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n"); + return 0; + } + *OutStr = '\0'; + lpls = ListBoxGetItem (lphl, uIndex); + if (lpls == NULL) return LB_ERR; + + if (!lphl->HasStrings) { + *((long *)OutStr) = lpls->mis.itemData; + return 4; + } + + strcpy(OutStr, lpls->itemText); + return strlen(OutStr); +} + + +DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex) +{ + LPLISTSTRUCT lpls; + + lpls = ListBoxGetItem (lphl, uIndex); + if (lpls == NULL) return LB_ERR; + return lpls->mis.itemData; +} + + +int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData) +{ + LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex); + + if (lpls == NULL) return LB_ERR; + lpls->mis.itemData = ItemData; + return 1; +} + + +int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex) +{ + LPLISTSTRUCT lpls, lpls2; + UINT Count; + + if (uIndex >= lphl->ItemsCount) return LB_ERR; + + lpls = lphl->lpFirst; + if (lpls == NULL) return LB_ERR; + + if (uIndex == 0) + { + if( lphl->OwnerDrawn ) + lbDeleteItemNotify( lphl, lpls); + lphl->lpFirst = lpls->lpNext; + } + else + { + LPLISTSTRUCT lpls2 = NULL; + for(Count = 0; Count < uIndex; Count++) { + if (lpls->lpNext == NULL) return LB_ERR; + + lpls2 = lpls; + lpls = (LPLISTSTRUCT)lpls->lpNext; + } + if( lphl->OwnerDrawn ) + lbDeleteItemNotify( lphl, lpls); + lpls2->lpNext = lpls->lpNext; + } + + /* adjust the itemID field of the following entries */ + for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) { + lpls2->mis.itemID--; + } + + lphl->ItemsCount--; + + if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData); + free(lpls); + + return lphl->ItemsCount; +} + +static int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match) +{ + /* match is either MATCH_SUBSTR or MATCH_EXACT */ + + LPLISTSTRUCT lpls; + UINT Count; + UINT First = nFirst + 1; + int s_length = 0; + LPSTR lpMatchStr = (LPSTR)MatchStr; + + if (First > lphl->ItemsCount) return LB_ERR; + + if (lphl->dwStyle & LBS_SORT ) + return ListBoxAskCompare( lphl, nFirst, MatchStr, match ); + + if (lphl->HasStrings ) + { + lpMatchStr = PTR_SEG_TO_LIN(MatchStr); + + if( match == MATCH_SUBSTR ) + { + s_length = strlen(lpMatchStr); + if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR; + } + } + + lpls = ListBoxGetItem(lphl, First); + Count = 0; + while(lpls != NULL) + { + if (lphl->HasStrings) + { + if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length) + : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count; + } + else + if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count; + + lpls = lpls->lpNext; + Count++; + } + + /* Start over at top */ + Count = 0; + lpls = lphl->lpFirst; + + while (Count < First) + { + if (lphl->HasStrings) + { + if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length) + : !lstrcmpi32A(lpls->itemText, lpMatchStr) ) return Count; + } + else + if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count; + + lpls = lpls->lpNext; + Count++; + } + + return LB_ERR; +} + +int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr) +{ + return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR ); +} + +int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr) +{ + return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT ); +} + +int ListBoxResetContent(LPHEADLIST lphl) +{ + LPLISTSTRUCT lpls; + int i; + + if (lphl->ItemsCount == 0) return 0; + + dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n", + lphl->ItemsCount); + + for(i = 0; i < lphl->ItemsCount; i++) { + lpls = lphl->lpFirst; + if (lpls == NULL) return LB_ERR; + + if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls); + + lphl->lpFirst = lpls->lpNext; + if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData); + free(lpls); + } + ListBoxInitialize(lphl); + + return TRUE; +} + +/* --------------------- selection ------------------------- */ + +int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex) +{ + LPLISTSTRUCT lpls; + + /* use ListBoxSetSel instead */ + if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0; + + /* unselect previous item */ + if (lphl->ItemFocused != -1) { + lphl->PrevFocused = lphl->ItemFocused; + lpls = ListBoxGetItem(lphl, lphl->ItemFocused); + if (lpls == 0) return LB_ERR; + lpls->itemState = 0; + } + + if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount)) + { + lphl->ItemFocused = wIndex; + lpls = ListBoxGetItem(lphl, wIndex); + if (lpls == 0) return LB_ERR; + lpls->itemState = ODS_SELECTED | ODS_FOCUS; + + return 0; + } + + return LB_ERR; +} + + + +/* ------------------------- dir listing ------------------------ */ + +LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec) +{ + char mask[13]; + char* temp = NULL; + const char* ptr; + int skip, count; + LONG ret; + DOS_DIRENT entry; + char *path, *p; + + dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib); + if (!filespec) return LB_ERR; + if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR; + path = xstrdup(ptr); + p = strrchr( path, '/' ); + *p++ = '\0'; + if (!(ptr = DOSFS_ToDosFCBFormat( p )) || + !(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) ) + { + free( path ); + return LB_ERR; + } + + strcpy( mask, ptr ); + + dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask); + + skip = ret = 0; + attrib &= ~FA_LABEL; + while ((count = DOSFS_FindNext( path, mask, NULL, 0, + attrib, skip, &entry )) > 0) + { + skip += count; + if (entry.attr & FA_DIRECTORY) + { + if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ". ")) + { + sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) ); + AnsiLower( temp ); + if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; + } + } + else /* not a directory */ + { + if (!(attrib & DDL_EXCLUSIVE) || + ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) == + (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)))) + { + strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) ); + AnsiLower( temp ); + if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; + } + } + + dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp); + } + if (attrib & DDL_DRIVES) + { + int x; + DWORD oldstyle = lphl->dwStyle; + + lphl->dwStyle &= ~LBS_SORT; + strcpy( temp, "[-a-]" ); + for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++) + { + if (DRIVE_IsValid(x)) + if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break; + } + lphl->dwStyle = oldstyle; + } + + free( path ); + SEGPTR_FREE( temp ); + + return ret; +} + +/* ------------------------- dimensions ------------------------- */ + +int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect) +{ + LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex); + + dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls); + if (lpls == NULL) + { + if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE) + return LB_ERR; + else + { + GetClientRect16(lphl->hSelf,lprect); + lprect->bottom=lphl->StdItemHeight; + if (lprect->right<0) lprect->right=0; + } + } + else + *lprect = lpls->itemRect; + dprintf_listbox(stddeb," = %d,%d %d,%d\n", lprect->left,lprect->top, + lprect->right,lprect->bottom); + return 0; +} + + +int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height) +{ + LPLISTSTRUCT lpls; + + if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) { + lphl->StdItemHeight = (short)height; + return 0; + } + + lpls = ListBoxGetItem(lphl, wIndex); + if (lpls == NULL) return LB_ERR; + + lpls->mis.itemHeight = height; + return 0; +} + +/* -------------------------- string search ------------------------ */ + +int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar) +{ + LPLISTSTRUCT lpls; + UINT count,first; + + if ((char)wChar < ' ') return LB_ERR; + if (!lphl->HasStrings) return LB_ERR; + + lpls = lphl->lpFirst; + + for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) { + if (tolower(*lpls->itemText) == tolower((char)wChar)) break; + } + if (lpls == NULL) return LB_ERR; + first = count; + for(; lpls != NULL; lpls = lpls->lpNext, count++) { + if (*lpls->itemText != (char)wChar) + break; + if ((short) count > lphl->ItemFocused) + return count; + } + return first; +} diff --git a/controls/scroll.c b/controls/scroll.c index 21316a019e2..0ffa3b4b528 100644 --- a/controls/scroll.c +++ b/controls/scroll.c @@ -54,7 +54,7 @@ static HBITMAP32 hRgArrowI = 0; #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) between scroll repetitions */ -#define SCROLL_REPEAT_DELAY 100 +#define SCROLL_REPEAT_DELAY 50 /* Scroll timer id */ #define SCROLL_TIMER 0 diff --git a/controls/widgets.c b/controls/widgets.c index 88d01a4b6d7..a884757c1f1 100644 --- a/controls/widgets.c +++ b/controls/widgets.c @@ -16,7 +16,12 @@ #include "module.h" #include "heap.h" -#define OLD_LISTBOX +/* Window procedures */ + +extern LRESULT ListBoxWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, + LPARAM lParam ); + +/* Win16 class info */ typedef struct { @@ -27,42 +32,39 @@ typedef struct LPCSTR className; } BUILTIN_CLASS_INFO16; +/* Win16 built-in classes */ + static const BUILTIN_CLASS_INFO16 WIDGETS_BuiltinClasses16[] = { { CS_GLOBALCLASS | CS_PARENTDC, - sizeof(STATICINFO), 0, "StaticWndProc", "STATIC" }, -#ifdef OLD_LISTBOX + sizeof(STATICINFO), 0, "StaticWndProc", "Static" }, { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, - 8, 0, "ListBoxWndProc", "LISTBOX" }, -#endif - { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, - 8, 0, "ComboBoxWndProc", "COMBOBOX" }, + 8, 0, "ComboBoxWndProc", "ComboBox" }, { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS, - 8, 0, "ComboLBoxWndProc", "COMBOLBOX" }, + 8, 0, "ComboLBoxWndProc", "ComboLBox" }, { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, - sizeof(DWORD), 0, "EditWndProc", "EDIT" }, + sizeof(DWORD), 0, "EditWndProc", "Edit" }, { CS_GLOBALCLASS | CS_SAVEBITS, sizeof(HMENU32), 0, "PopupMenuWndProc", POPUPMENU_CLASS_NAME }, { CS_GLOBALCLASS | CS_SAVEBITS, DLGWINDOWEXTRA, 0, "DefDlgProc", DIALOG_CLASS_NAME }, { CS_GLOBALCLASS, sizeof(MDICLIENTINFO), - STOCK_LTGRAY_BRUSH, "MDIClientWndProc", "MDICLIENT" } + STOCK_LTGRAY_BRUSH, "MDIClientWndProc", "MDIClient" } }; #define NB_BUILTIN_CLASSES16 \ (sizeof(WIDGETS_BuiltinClasses16)/sizeof(WIDGETS_BuiltinClasses16[0])) +/* Win32 built-in classes */ static WNDCLASS32A WIDGETS_BuiltinClasses32[] = { { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, - ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "BUTTON" }, -#ifndef OLD_LISTBOX + ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "Button" }, { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/, - ListBoxWndProc32, 0, sizeof(void *), 0, 0, 0, 0, 0, "LISTBOX" }, -#endif + ListBoxWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ListBox" }, { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, - ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "SCROLLBAR"}, + ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "ScrollBar"}, { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO), 0, 0, 0, 0, 0, DESKTOP_CLASS_NAME } }; @@ -71,6 +73,8 @@ static WNDCLASS32A WIDGETS_BuiltinClasses32[] = (sizeof(WIDGETS_BuiltinClasses32)/sizeof(WIDGETS_BuiltinClasses32[0])) +/* Win32 common controls */ + static WNDCLASS32A WIDGETS_CommonControls32[] = { { CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW, StatusWindowProc, 0, diff --git a/files/profile.c b/files/profile.c index ddb21ed7d93..d1a8426ab60 100644 --- a/files/profile.c +++ b/files/profile.c @@ -5,6 +5,7 @@ * Copyright 1996 Alexandre Julliard */ +#define NO_TRANSITION_TYPES /* This file is Win32-clean */ #include #include #include @@ -13,6 +14,7 @@ #include "windows.h" #include "dos_fs.h" #include "xmalloc.h" +#include "string32.h" #include "stddebug.h" #include "debug.h" @@ -33,7 +35,7 @@ typedef struct tagPROFILESECTION typedef struct { - int changed; + BOOL32 changed; PROFILESECTION *section; char *dos_name; } PROFILE; @@ -55,6 +57,8 @@ static const char PROFILE_WineIniName[] = "/.winerc"; #define WINE_INI_GLOBAL ETCDIR "/wine.conf" +static LPCWSTR wininiW = NULL; + /*********************************************************************** * PROFILE_CopyEntry * @@ -227,7 +231,7 @@ static PROFILESECTION *PROFILE_Load( FILE *file ) * * Delete a section from a profile tree. */ -static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name ) +static BOOL32 PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name ) { while (*section) { @@ -250,8 +254,8 @@ static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name ) * * Delete a key from a profile tree. */ -static BOOL PROFILE_DeleteKey( PROFILESECTION **section, - const char *section_name, const char *key_name ) +static BOOL32 PROFILE_DeleteKey( PROFILESECTION **section, + LPCSTR section_name, LPCSTR key_name ) { while (*section) { @@ -323,7 +327,7 @@ static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, * * Flush the current profile to disk if changed. */ -static BOOL PROFILE_FlushFile(void) +static BOOL32 PROFILE_FlushFile(void) { char *p, buffer[MAX_PATHNAME_LEN]; const char *unix_name; @@ -368,7 +372,7 @@ static BOOL PROFILE_FlushFile(void) * * Open a profile file, checking the cached file first. */ -static BOOL PROFILE_Open( const char *filename ) +static BOOL32 PROFILE_Open( LPCSTR filename ) { char buffer[MAX_PATHNAME_LEN]; const char *dos_name, *unix_name; @@ -443,16 +447,15 @@ static BOOL PROFILE_Open( const char *filename ) * * Enumerate all the keys of a section. */ -static INT PROFILE_GetSection( PROFILESECTION *section, - const char *section_name, - char *buffer, INT len, int handle_env ) +static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name, + LPSTR buffer, INT32 len, BOOL32 handle_env ) { PROFILEKEY *key; while (section) { if (section->name && !lstrcmpi32A( section->name, section_name )) { - INT oldlen = len; + INT32 oldlen = len; for (key = section->key; key; key = key->next) { if (len <= 2) break; @@ -476,8 +479,8 @@ static INT PROFILE_GetSection( PROFILESECTION *section, * * Get a profile string. */ -static INT PROFILE_GetString( const char *section, const char *key_name, - const char *def_val, char *buffer, INT len ) +static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name, + LPCSTR def_val, LPSTR buffer, INT32 len ) { PROFILEKEY *key = NULL; @@ -500,10 +503,10 @@ static INT PROFILE_GetString( const char *section, const char *key_name, * * Set a profile string. */ -static BOOL PROFILE_SetString( const char *section_name, const char *key_name, - const char *value ) +static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name, + LPCSTR value ) { - BOOL ret; + BOOL32 ret; if (!key_name) /* Delete a whole section */ { @@ -623,66 +626,156 @@ int PROFILE_LoadWineIni(void) } +/********************* API functions **********************************/ + /*********************************************************************** - * GetProfileInt (KERNEL.57) + * GetProfileInt16 (KERNEL.57) */ -UINT GetProfileInt( LPCSTR section, LPCSTR entry, INT def_val ) +UINT16 GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val ) { - return GetPrivateProfileInt( section, entry, def_val, "win.ini" ); + return GetPrivateProfileInt16( section, entry, def_val, "win.ini" ); } /*********************************************************************** - * GetProfileString (KERNEL.58) + * GetProfileInt32A (KERNEL32.264) */ -INT GetProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val, - LPSTR buffer, INT len ) +UINT32 GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val ) { - return GetPrivateProfileString( section, entry, def_val, - buffer, len, "win.ini" ); + return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" ); +} + +/*********************************************************************** + * GetProfileInt32W (KERNEL32.264) + */ +UINT32 GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val ) +{ + if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini"); + return GetPrivateProfileInt32W( section, entry, def_val, wininiW ); +} + +/*********************************************************************** + * GetProfileString16 (KERNEL.58) + */ +INT16 GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, INT16 len ) +{ + return GetPrivateProfileString16( section, entry, def_val, + buffer, len, "win.ini" ); +} + +/*********************************************************************** + * GetProfileString32A (KERNEL32.268) + */ +INT32 GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, INT32 len ) +{ + return GetPrivateProfileString32A( section, entry, def_val, + buffer, len, "win.ini" ); +} + +/*********************************************************************** + * GetProfileString32W (KERNEL32.269) + */ +INT32 GetProfileString32W( LPCWSTR section,LPCWSTR entry,LPCWSTR def_val, + LPWSTR buffer, INT32 len ) +{ + if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini"); + return GetPrivateProfileString32W( section, entry, def_val, + buffer, len, wininiW ); } /*********************************************************************** - * WriteProfileString (KERNEL.59) + * WriteProfileString16 (KERNEL.59) */ -BOOL WriteProfileString( LPCSTR section, LPCSTR entry, LPCSTR string ) +BOOL16 WriteProfileString16( LPCSTR section, LPCSTR entry, LPCSTR string ) { - return WritePrivateProfileString( section, entry, string, "win.ini" ); + return WritePrivateProfileString16( section, entry, string, "win.ini" ); +} + +/*********************************************************************** + * WriteProfileString32A (KERNEL32.587) + */ +BOOL32 WriteProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR string ) +{ + return WritePrivateProfileString32A( section, entry, string, "win.ini" ); +} + +/*********************************************************************** + * WriteProfileString32W (KERNEL32.588) + */ +BOOL32 WriteProfileString32W( LPCWSTR section, LPCWSTR entry, LPCWSTR string ) +{ + if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini"); + return WritePrivateProfileString32W( section, entry, string, wininiW ); } /*********************************************************************** - * GetPrivateProfileInt (KERNEL.127) + * GetPrivateProfileInt16 (KERNEL.127) */ -UINT GetPrivateProfileInt( LPCSTR section, LPCSTR entry, INT def_val, - LPCSTR filename ) +UINT16 GetPrivateProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val, + LPCSTR filename ) +{ + long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename); + + if (result > 65535) return 65535; + if (result >= 0) return (UINT16)result; + if (result < -32768) return -32768; + return (UINT16)(INT16)result; +} + +/*********************************************************************** + * GetPrivateProfileInt32A (KERNEL32.251) + */ +UINT32 GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val, + LPCSTR filename ) { char buffer[20]; char *p; long result; - GetPrivateProfileString( section, entry, "", - buffer, sizeof(buffer), filename ); - if (!buffer[0]) return (UINT)def_val; + GetPrivateProfileString32A( section, entry, "", + buffer, sizeof(buffer), filename ); + if (!buffer[0]) return (UINT32)def_val; result = strtol( buffer, &p, 0 ); if (p == buffer) return 0; /* No digits at all */ -#ifdef WINELIB32 - return (UINT)result; -#else - if (result > 65535) return 65535; - if (result >= 0) return (UINT)result; - if (result < -32768) return -32768; - return (UINT)(INT)result; -#endif + return (UINT32)result; } +/*********************************************************************** + * GetPrivateProfileInt32W (KERNEL32.252) + */ +UINT32 GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val, + LPCWSTR filename ) +{ + LPSTR sectionA=section?STRING32_DupUniToAnsi(section):NULL; + LPSTR entryA=entry?STRING32_DupUniToAnsi(entry):NULL; + LPSTR filenameA=filename?STRING32_DupUniToAnsi(filename):NULL; + UINT32 res; + + res=GetPrivateProfileInt32A(sectionA,entryA,def_val,filenameA); + if (sectionA) free(sectionA); + if (filenameA) free(filenameA); + if (entryA) free(entryA); + return res; +} /*********************************************************************** - * GetPrivateProfileString (KERNEL.128) + * GetPrivateProfileString16 (KERNEL.128) */ -INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val, - LPSTR buffer, INT len, LPCSTR filename ) +INT16 GetPrivateProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, INT16 len, LPCSTR filename ) +{ + return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename); +} + +/*********************************************************************** + * GetPrivateProfileString32A (KERNEL32.255) + */ +INT32 GetPrivateProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, INT32 len, LPCSTR filename ) { if (PROFILE_Open( filename )) return PROFILE_GetString( section, entry, def_val, buffer, len ); @@ -690,18 +783,73 @@ INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val, return strlen( buffer ); } +/*********************************************************************** + * GetPrivateProfileString32W (KERNEL32.256) + */ +INT32 GetPrivateProfileString32W( LPCWSTR section,LPCWSTR entry,LPCWSTR def_val, + LPWSTR buffer,INT32 len,LPCWSTR filename ) +{ + LPSTR sectionA = section?STRING32_DupUniToAnsi(section):NULL; + LPSTR entryA = entry?STRING32_DupUniToAnsi(entry):NULL; + LPSTR filenameA = filename?STRING32_DupUniToAnsi(filename):NULL; + LPSTR def_valA = def_val?STRING32_DupUniToAnsi(def_val):NULL; + LPSTR bufferA = xmalloc(len); + INT32 ret; + + ret=GetPrivateProfileString32A(sectionA,entryA,def_valA,bufferA,len,filenameA); + if (sectionA) free(sectionA); + if (entryA) free(entryA); + if (filenameA) free(filenameA); + if (def_valA) free(def_valA); + + lstrcpynAtoW( buffer, bufferA, len ); + free(bufferA); + return ret; +} + + /*********************************************************************** - * WritePrivateProfileString (KERNEL.129) + * WritePrivateProfileString16 (KERNEL.129) */ -BOOL WritePrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR string, - LPCSTR filename ) +BOOL16 WritePrivateProfileString16(LPCSTR section,LPCSTR entry,LPCSTR string, + LPCSTR filename) +{ + return WritePrivateProfileString32A(section,entry,string,filename); +} + +/*********************************************************************** + * WritePrivateProfileString32A (KERNEL32.582) + */ +BOOL32 WritePrivateProfileString32A(LPCSTR section,LPCSTR entry,LPCSTR string, + LPCSTR filename ) { if (!PROFILE_Open( filename )) return FALSE; if (!section) return PROFILE_FlushFile(); return PROFILE_SetString( section, entry, string ); } +/*********************************************************************** + * WritePrivateProfileString32W (KERNEL32.583) + */ +BOOL32 WritePrivateProfileString32W(LPCWSTR section,LPCWSTR entry,LPCWSTR string, + LPCWSTR filename ) +{ + LPSTR sectionA = section?STRING32_DupUniToAnsi(section):NULL; + LPSTR entryA = entry?STRING32_DupUniToAnsi(entry):NULL; + LPSTR stringA = string?STRING32_DupUniToAnsi(string):NULL; + LPSTR filenameA = filename?STRING32_DupUniToAnsi(filename):NULL; + BOOL32 res; + + res = WritePrivateProfileString32A(sectionA,entryA,stringA,filenameA); + + if (sectionA) free(sectionA); + if (entryA) free(entryA); + if (stringA) free(stringA); + if (filenameA) free(filenameA); + return res; +} + /*********************************************************************** * WriteOutProfiles (KERNEL.315) diff --git a/graphics/Makefile.in b/graphics/Makefile.in index 9bb95359771..cc14f5f4562 100644 --- a/graphics/Makefile.in +++ b/graphics/Makefile.in @@ -6,6 +6,7 @@ VPATH = @srcdir@ MODULE = graphics C_SRCS = \ + wing.c \ bitblt.c \ driver.c diff --git a/graphics/wing.c b/graphics/wing.c new file mode 100644 index 00000000000..4f3b29d5b09 --- /dev/null +++ b/graphics/wing.c @@ -0,0 +1,67 @@ +/* + * WingG support + * + * Started by Robert Pouliot + */ + +#include "gdi.h" +#include "stddebug.h" +#include "debug.h" + +/* I dunno if this structure can be put here... Maybe copyright, I'm no lawyer... */ +typedef enum WING_DITHER_TYPE +{ + WING_DISPERSED_4x4, + WING_DISPERSED_8x8, + + WING_CLUSTERED_4x4 + +} WING_DITHER_TYPE; + +/*********************************************************************** + * WingCreateDC16 (WING.1001) + */ +HDC16 WinGCreateDC16(void) +{ + /* FIXME: Probably wrong... */ + return CreateDC("DISPLAY", NULL, NULL, NULL); +} + + +/*********************************************************************** + * WinGRecommendDIBFormat16 (WING.1002) + */ +BOOL16 WinGRecommendDIBFormat16(BITMAPINFO *fmt) +{ + fprintf(stdnimp,"WinGRecommendDIBFormat: empty stub!\n"); + return 0; +} + +/*********************************************************************** + * WinGCreateBitmap16 (WING.1003) + */ +HBITMAP16 WinGCreateBitmap16(HDC16 winDC, BITMAPINFO *header, void **bits) +{ + fprintf(stdnimp,"WinGCreateBitmap: empty stub! (expect failure)\n"); + *bits=0; + return 0; +} + +/*********************************************************************** + * WinGCreateHalfTonePalette16 (WING.1007) + */ +HPALETTE16 WinGCreateHalfTonePalette16(void) +{ + fprintf(stdnimp,"WinGCreateHalfTonePalette: empty stub!\n"); + return 0; +} + +/*********************************************************************** + * WinGCreateHalfToneBrush16 (WING.1008) + */ +HPALETTE16 WinGCreateHalfToneBrush16(HDC16 winDC, COLORREF col, WING_DITHER_TYPE type) +{ + fprintf(stdnimp,"WinGCreateHalfToneBrush: empty stub!\n"); + return 0; +} + diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec index 6e15693f0b9..bf709fb35b1 100644 --- a/if1632/crtdll.spec +++ b/if1632/crtdll.spec @@ -343,7 +343,7 @@ base 1 338 stub abort 339 cdecl abs(long) CRTDLL_abs 340 cdecl acos(long) CRTDLL_acos -341 stub asctime +341 cdecl asctime(ptr) asctime 342 cdecl asin(long) CRTDLL_asin 343 cdecl atan(long) CRTDLL_atan 344 cdecl atan2(long long) CRTDLL_atan2 @@ -352,15 +352,15 @@ base 1 347 cdecl atoi(ptr) CRTDLL_atoi 348 cdecl atol(ptr) CRTDLL_atol 349 stub bsearch -350 stub calloc +350 cdecl calloc(long long) CRTDLL_calloc 351 stub ceil 352 stub clearerr -353 stub clock +353 cdecl clock() clock 354 cdecl cos(long) CRTDLL_cos 355 cdecl cosh(long) CRTDLL_cosh -356 stub ctime +356 cdecl ctime(ptr) ctime 357 stub difftime -358 stub div +358 cdecl div(long long) div 359 cdecl exit(long) CRTDLL_exit 360 cdecl exp(long) CRTDLL_exp 361 cdecl fabs(long) CRTDLL_fabs @@ -394,7 +394,7 @@ base 1 389 stub getchar 390 stub getenv 391 cdecl gets(ptr) CRTDLL_gets -392 stub gmtime +392 cdecl gmtime(ptr) gmtime 393 stub is_wctype 394 cdecl isalnum(long) CRTDLL_isalnum 395 cdecl isalpha(long) CRTDLL_isalpha @@ -423,9 +423,9 @@ base 1 418 cdecl isxdigit(long) CRTDLL_isxdigit 419 cdecl labs(long) CRTDLL_labs 420 stub ldexp -421 stub ldiv +421 cdecl ldiv(long long) ldiv 422 stub localeconv -423 stub localtime +423 cdecl localtime(ptr) localtime 424 cdecl log(long) CRTDLL_log 425 cdecl log10(long) CRTDLL_log10 426 stub longjmp @@ -438,7 +438,7 @@ base 1 433 cdecl memcpy(ptr ptr long) memcpy 434 cdecl memmove(ptr ptr long) memmove 435 cdecl memset(ptr long long) memset -436 stub mktime +436 cdecl mktime(ptr) mktime 437 stub modf 438 stub perror 439 cdecl pow(long long) CRTDLL_pow @@ -449,7 +449,7 @@ base 1 444 stub qsort 445 stub raise 446 cdecl rand() CRTDLL_rand -447 stub realloc +447 cdecl realloc(ptr long) CRTDLL_realloc 448 stub remove 449 stub rename 450 stub rewind @@ -464,27 +464,27 @@ base 1 459 cdecl sqrt(long) CRTDLL_sqrt 460 cdecl srand(long) CRTDLL_srand 461 stub sscanf -462 cdecl strcat(ptr ptr) lstrcat32A +462 cdecl strcat(ptr ptr) strcat 463 cdecl strchr(ptr long) strchr -464 cdecl strcmp(ptr ptr) lstrcmp32A -465 stub strcoll -466 cdecl strcpy(ptr ptr) lstrcpy32A +464 cdecl strcmp(ptr ptr) strcmp +465 cdecl strcoll(ptr ptr) strcoll +466 cdecl strcpy(ptr ptr) strcpy 467 cdecl strcspn(ptr ptr) strcspn 468 stub strerror -469 stub strftime -470 cdecl strlen(ptr) lstrlen32A -471 cdecl strncat(ptr ptr long) lstrcatn32A -472 cdecl strncmp(ptr ptr long) lstrncmp32A -473 cdecl strncpy(ptr ptr long) lstrcpyn32A -474 stub strpbrk -475 stub strrchr +469 cdecl strftime(ptr long ptr ptr) strftime +470 cdecl strlen(ptr) strlen +471 cdecl strncat(ptr ptr long) strncat +472 cdecl strncmp(ptr ptr long) strncmp +473 cdecl strncpy(ptr ptr long) strncpy +474 cdecl strpbrk(ptr ptr) strpbrk +475 cdecl strrchr(ptr long) strrchr 476 cdecl strspn(ptr ptr) strspn 477 cdecl strstr(ptr ptr) strstr 478 stub strtod 479 cdecl strtok(ptr ptr) strtok 480 cdecl strtol(ptr ptr long) strtol 481 cdecl strtoul(ptr ptr long) strtoul -482 stub strxfrm +482 cdecl strxfrm(ptr ptr long) strxfrm 483 stub swprintf 484 stub swscanf 485 stub system diff --git a/if1632/gdi.spec b/if1632/gdi.spec index 4a8e1b5fe6d..3fd6b1e3ffb 100644 --- a/if1632/gdi.spec +++ b/if1632/gdi.spec @@ -149,7 +149,7 @@ heap 65488 # 65536 - 16 (instance data) - 32 (stock objects) 169 stub IsDCDirty 170 stub SetDCStatus 172 pascal16 SetRectRgn(word s_word s_word s_word s_word) SetRectRgn -173 pascal16 GetClipRgn(word) GetClipRgn +173 pascal16 GetClipRgn(word) GetClipRgn16 175 pascal16 EnumMetaFile(word word segptr long) THUNK_EnumMetaFile16 176 pascal16 PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord 179 pascal16 GetDCState(word) GetDCState @@ -382,7 +382,7 @@ heap 65488 # 65536 - 16 (instance data) - 32 (stock objects) 610 stub GDISignalProc32 611 stub GetRandomRgn 612 stub GetTextCharSet -613 stub EnumFontFamiliesEx +613 pascal16 EnumFontFamiliesEx(word ptr segptr long long) THUNK_EnumFontFamiliesEx16 614 stub AddLpkToGDI 615 stub GetCharacterPlacement 616 stub GetFontLanguageInfo diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec index 6c6853e0545..c84bf4a4b2a 100644 --- a/if1632/gdi32.spec +++ b/if1632/gdi32.spec @@ -86,11 +86,11 @@ base 1 0078 stub EndPath 0079 stub EnumEnhMetaFile 0080 stdcall EnumFontFamiliesA(long ptr ptr long) THUNK_EnumFontFamilies32A -0081 stub EnumFontFamiliesExA -0082 stub EnumFontFamiliesExW +0081 stdcall EnumFontFamiliesExA(long ptr ptr long long) THUNK_EnumFontFamiliesEx32A +0082 stdcall EnumFontFamiliesExW(long ptr ptr long long) THUNK_EnumFontFamiliesEx32W 0083 stdcall EnumFontFamiliesW(long ptr ptr long) THUNK_EnumFontFamilies32W -0084 stub EnumFontsA -0085 stub EnumFontsW +0084 stdcall EnumFontsA(long ptr ptr long) THUNK_EnumFonts32A +0085 stdcall EnumFontsW(long ptr ptr long) THUNK_EnumFonts32W 0086 stub EnumICMProfilesA 0087 stub EnumICMProfilesW 0088 stub EnumMetaFile @@ -153,7 +153,7 @@ base 1 0145 stdcall GetBkColor(long) GetBkColor 0146 stub GetBkMode 0147 stub GetBoundsRect -0148 stub GetBrushOrgEx +0148 stdcall GetBrushOrgEx(long ptr) GetBrushOrgEx32 0149 stub GetCharABCWidthsA 0150 stub GetCharABCWidthsFloatA 0151 stub GetCharABCWidthsFloatW @@ -168,12 +168,12 @@ base 1 0160 stub GetCharacterPlacementA 0161 stub GetCharacterPlacementW 0162 stdcall GetClipBox(long ptr) GetClipBox32 -0163 stub GetClipRgn +0163 stdcall GetClipRgn(long long) GetClipRgn32 0164 stub GetColorAdjustment 0165 stub GetColorSpace 0166 stub GetCurrentObject -0167 stub GetCurrentPositionEx -0168 stub GetDCOrgEx +0167 stdcall GetCurrentPositionEx(long ptr) GetCurrentPositionEx32 +0168 stdcall GetDCOrgEx(long ptr) GetDCOrgEx 0169 stub GetDIBColorTable 0170 stub GetDIBits 0171 stdcall GetDeviceCaps(long long) GetDeviceCaps @@ -239,16 +239,16 @@ base 1 0231 stub GetTextExtentPoint32W 0232 stdcall GetTextExtentPointA(long ptr long ptr) GetTextExtentPoint32A 0233 stdcall GetTextExtentPointW(long ptr long ptr) GetTextExtentPoint32W -0234 stub GetTextFaceA +0234 stdcall GetTextFaceA(long long ptr) GetTextFace 0235 stub GetTextFaceW 0236 stdcall GetTextMetricsA(long ptr) GetTextMetrics32A 0237 stdcall GetTextMetricsW(long ptr) GetTextMetrics32W 0238 stub GetTransform -0239 stub GetViewportExtEx -0240 stub GetViewportOrgEx +0239 stdcall GetViewportExtEx(long ptr) GetViewportExtEx32 +0240 stdcall GetViewportOrgEx(long ptr) GetViewportOrgEx32 0241 stub GetWinMetaFileBits -0242 stub GetWindowExtEx -0243 stub GetWindowOrgEx +0242 stdcall GetWindowExtEx(long ptr) GetWindowExtEx32 +0243 stdcall GetWindowOrgEx(long ptr) GetWindowOrgEx32 0244 stub GetWorldTransform 0245 stdcall IntersectClipRect(long long long long long) IntersectClipRect32 0246 stdcall InvertRgn(long long) InvertRgn32 @@ -328,7 +328,7 @@ base 1 0319 stub SetICMProfileA 0320 stub SetICMProfileW 0321 stdcall SetMapMode(long long) SetMapMode -0322 stub SetMapperFlags +0322 stdcall SetMapperFlags(long long) SetMapperFlags 0323 stub SetMetaFileBitsEx 0324 stub SetMetaRgn 0325 stub SetMiterLimit diff --git a/if1632/kernel.spec b/if1632/kernel.spec index 9b2c4c9dedd..eb3fd297bc7 100644 --- a/if1632/kernel.spec +++ b/if1632/kernel.spec @@ -53,9 +53,9 @@ type win16 54 pascal16 GetInstanceData(word word word) GetInstanceData 55 pascal16 Catch(ptr) Catch 56 pascal16 Throw(ptr word) Throw -57 pascal16 GetProfileInt(ptr ptr s_word) GetProfileInt -58 pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString -59 pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString +57 pascal16 GetProfileInt(ptr ptr s_word) GetProfileInt16 +58 pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString16 +59 pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString16 60 pascal16 FindResource(word segptr segptr) FindResource16 61 pascal16 LoadResource(word word) LoadResource16 62 pascal LockResource(word) WIN16_LockResource16 @@ -123,11 +123,11 @@ type win16 124 return EnableKernel 0 0 125 return DisableKernel 0 0 126 stub MemoryFreed -127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt +127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt16 128 pascal16 GetPrivateProfileString(ptr ptr ptr ptr word ptr) - GetPrivateProfileString + GetPrivateProfileString16 129 pascal16 WritePrivateProfileString(ptr ptr ptr ptr) - WritePrivateProfileString + WritePrivateProfileString16 130 pascal FileCDR(ptr) FileCDR 131 pascal GetDOSEnvironment() GetDOSEnvironment 132 pascal GetWinFlags() GetWinFlags diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec index ecf60202819..9c7501eb2f5 100644 --- a/if1632/kernel32.spec +++ b/if1632/kernel32.spec @@ -96,8 +96,8 @@ base 1 0091 stub EnumResourceTypesW 0092 stdcall EnumSystemCodePagesA(ptr long) THUNK_EnumSystemCodePages32A 0093 stdcall EnumSystemCodePagesW(ptr long) THUNK_EnumSystemCodePages32W -0094 stub EnumSystemLocalesA -0095 stub EnumSystemLocalesW +0094 stdcall EnumSystemLocalesA(ptr long) THUNK_EnumSystemLocales32A +0095 stdcall EnumSystemLocalesW(ptr long) THUNK_EnumSystemLocales32W 0096 stub EnumTimeFormatsA 0097 stub EnumTimeFormatsW 0098 stub EraseTape @@ -253,12 +253,12 @@ base 1 0248 stdcall GetOEMCP() GetOEMCP 0249 stub GetOverlappedResult 0250 stub GetPriorityClass -0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt -0252 stub GetPrivateProfileIntW +0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt32A +0252 stdcall GetPrivateProfileIntW(ptr ptr long ptr) GetPrivateProfileInt32W 0253 stub GetPrivateProfileSectionA 0254 stub GetPrivateProfileSectionW -0255 stdcall GetPrivateProfileStringA(ptr ptr ptr ptr long ptr) GetPrivateProfileString -0256 stub GetPrivateProfileStringW +0255 stdcall GetPrivateProfileStringA(ptr ptr ptr ptr long ptr) GetPrivateProfileString32A +0256 stdcall GetPrivateProfileStringW(ptr ptr ptr ptr long ptr) GetPrivateProfileString32W 0257 stdcall GetProcAddress(long ptr) GetProcAddress32 0258 stdcall GetProcessAffinityMask(long ptr ptr) GetProcessAffinityMask 0259 stdcall GetProcessHeap() GetProcessHeap @@ -266,12 +266,12 @@ base 1 0261 stub GetProcessShutdownParameters 0262 stub GetProcessTimes 0263 stub GetProcessWorkingSetSize -0264 stdcall GetProfileIntA(ptr ptr long) GetProfileInt -0265 stub GetProfileIntW +0264 stdcall GetProfileIntA(ptr ptr long) GetProfileInt32A +0265 stdcall GetProfileIntW(ptr ptr long) GetProfileInt32W 0266 stub GetProfileSectionA 0267 stub GetProfileSectionW -0268 stdcall GetProfileStringA(ptr ptr ptr ptr long) GetProfileString -0269 stub GetProfileStringW +0268 stdcall GetProfileStringA(ptr ptr ptr ptr long) GetProfileString32A +0269 stdcall GetProfileStringW(ptr ptr ptr ptr long) GetProfileString32W 0270 stub GetQueuedCompletionStatus 0271 stdcall GetShortPathNameA(ptr ptr long) GetShortPathName32A 0272 stdcall GetShortPathNameW(ptr ptr long) GetShortPathName32W @@ -542,7 +542,7 @@ base 1 0537 stdcall UnhandledExceptionFilter(ptr) UnhandledExceptionFilter 0538 stub UnlockFile 0539 stub UnlockFileEx -0540 stub UnmapViewOfFile +0540 stdcall UnmapViewOfFile(ptr) UnmapViewOfFile 0541 stub UpdateResourceA 0542 stub UpdateResourceW 0543 stub VDMConsoleOperation @@ -584,13 +584,13 @@ base 1 0579 stub WriteFileEx 0580 stub WritePrivateProfileSectionA 0581 stub WritePrivateProfileSectionW -0582 stdcall WritePrivateProfileStringA(ptr ptr ptr ptr) WritePrivateProfileString -0583 stub WritePrivateProfileStringW +0582 stdcall WritePrivateProfileStringA(ptr ptr ptr ptr) WritePrivateProfileString32A +0583 stdcall WritePrivateProfileStringW(ptr ptr ptr ptr) WritePrivateProfileString32W 0584 stub WriteProcessMemory 0585 stub WriteProfileSectionA 0586 stub WriteProfileSectionW -0587 stdcall WriteProfileStringA(ptr ptr ptr) WriteProfileString -0588 stub WriteProfileStringW +0587 stdcall WriteProfileStringA(ptr ptr ptr) WriteProfileString32A +0588 stdcall WriteProfileStringW(ptr ptr ptr) WriteProfileString32W 0589 stub WriteTapemark 0590 stdcall _hread(long ptr long) _hread 0591 stdcall _hwrite(long ptr long) _hwrite diff --git a/if1632/thunk.c b/if1632/thunk.c index 348606f368d..5da3982add8 100644 --- a/if1632/thunk.c +++ b/if1632/thunk.c @@ -117,9 +117,28 @@ INT16 THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName, FONTENUMPROC16 func, LPARAM lParam ) { DECL_THUNK( thunk, func, CallTo16_word_llwl ); - return EnumFonts( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam ); + return EnumFonts16( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam ); } +/************************************************************************* + * THUNK_EnumFonts32A (GDI32.84) + */ +INT32 THUNK_EnumFonts32A( HDC32 hdc, LPCSTR lpFaceName, + FONTENUMPROC32A func, LPARAM lParam ) +{ + DECL_THUNK( thunk, func, CallTo32_4 ); + return EnumFonts32A( hdc, lpFaceName, (FONTENUMPROC32A)&thunk, lParam ); +} + +/************************************************************************* + * THUNK_EnumFonts32W (GDI32.85) + */ +INT32 THUNK_EnumFonts32W( HDC32 hdc, LPCWSTR lpFaceName, + FONTENUMPROC32W func, LPARAM lParam ) +{ + DECL_THUNK( thunk, func, CallTo32_4 ); + return EnumFonts32W( hdc, lpFaceName, (FONTENUMPROC32W)&thunk, lParam ); +} /****************************************************************** * THUNK_EnumMetaFile16 (GDI.175) @@ -164,6 +183,44 @@ INT32 THUNK_EnumFontFamilies32W( HDC32 hdc, LPCWSTR lpszFamily, return EnumFontFamilies32W(hdc,lpszFamily,(FONTENUMPROC32W)&thunk,lParam); } +/************************************************************************* + * THUNK_EnumFontFamiliesEx16 (GDI.613) + */ +INT16 THUNK_EnumFontFamiliesEx16( HDC16 hdc, LPLOGFONT16 lpLF, + FONTENUMPROCEX16 func, LPARAM lParam, + DWORD reserved ) +{ + DECL_THUNK( thunk, func, CallTo16_word_llwl ); + return EnumFontFamiliesEx16( hdc, lpLF, (FONTENUMPROCEX16)&thunk, + lParam, reserved ); +} + + +/************************************************************************* + * THUNK_EnumFontFamiliesEx32A (GDI32.81) + */ +INT32 THUNK_EnumFontFamiliesEx32A( HDC32 hdc, LPLOGFONT32A lpLF, + FONTENUMPROCEX32A func, LPARAM lParam, + DWORD reserved) +{ + DECL_THUNK( thunk, func, CallTo32_4 ); + return EnumFontFamiliesEx32A( hdc, lpLF, (FONTENUMPROCEX32A)&thunk, + lParam, reserved ); +} + + +/************************************************************************* + * THUNK_EnumFontFamiliesEx32W (GDI32.82) + */ +INT32 THUNK_EnumFontFamiliesEx32W( HDC32 hdc, LPLOGFONT32W lpLF, + FONTENUMPROCEX32W func, LPARAM lParam, + DWORD reserved ) +{ + DECL_THUNK( thunk, func, CallTo32_4 ); + return EnumFontFamiliesEx32W( hdc, lpLF, (FONTENUMPROCEX32W)&thunk, + lParam, reserved ); +} + /********************************************************************** * THUNK_LineDDA16 (GDI.100) @@ -320,6 +377,25 @@ BOOL32 THUNK_EnumSystemCodePages32W( CODEPAGE_ENUMPROC32W func, DWORD flags ) return EnumSystemCodePages32W( (CODEPAGE_ENUMPROC32W)&thunk, flags ); } +/*********************************************************************** + * THUNK_EnumSystemLocales32A (KERNEL32.92) + */ +BOOL32 THUNK_EnumSystemLocales32A( LOCALE_ENUMPROC32A func, DWORD flags ) +{ + DECL_THUNK( thunk, func, CallTo32_1 ); + return EnumSystemLocales32A( (LOCALE_ENUMPROC32A)&thunk, flags ); +} + + +/*********************************************************************** + * THUNK_EnumSystemLocales32W (KERNEL32.93) + */ +BOOL32 THUNK_EnumSystemLocales32W( LOCALE_ENUMPROC32W func, DWORD flags ) +{ + DECL_THUNK( thunk, func, CallTo32_1 ); + return EnumSystemLocales32W( (LOCALE_ENUMPROC32W)&thunk, flags ); +} + /*********************************************************************** * THUNK_GrayString16 (USER.185) diff --git a/if1632/user.spec b/if1632/user.spec index 2ca9abf6994..20ab847a325 100644 --- a/if1632/user.spec +++ b/if1632/user.spec @@ -99,7 +99,7 @@ heap 65520 97 pascal16 CheckDlgButton(word word word) CheckDlgButton 98 pascal16 IsDlgButtonChecked(word word) IsDlgButtonChecked 99 pascal16 DlgDirSelect(word ptr word) DlgDirSelect -100 pascal16 DlgDirList(word segptr word word word) DlgDirList +100 pascal16 DlgDirList(word ptr word word word) DlgDirList16 101 pascal SendDlgItemMessage(word word word word long) SendDlgItemMessage16 102 pascal16 AdjustWindowRect(ptr long word) AdjustWindowRect16 103 pascal16 MapDialogRect(word ptr) MapDialogRect16 @@ -194,7 +194,7 @@ heap 65520 192 pascal16 InSendMessage() InSendMessage 193 pascal16 IsClipboardFormatAvailable(word) IsClipboardFormatAvailable 194 pascal16 DlgDirSelectComboBox(word ptr word) DlgDirSelectComboBox -195 pascal16 DlgDirListComboBox(word segptr word word word) DlgDirListComboBox16 +195 pascal16 DlgDirListComboBox(word ptr word word word) DlgDirListComboBox16 196 pascal TabbedTextOut(word s_word s_word ptr s_word s_word ptr s_word) TabbedTextOut 197 pascal GetTabbedTextExtent(word ptr word word ptr) GetTabbedTextExtent diff --git a/if1632/user32.spec b/if1632/user32.spec index 7a484ba9f46..e4c871d1192 100644 --- a/if1632/user32.spec +++ b/if1632/user32.spec @@ -82,7 +82,7 @@ base 1 0077 stub CreateIconIndirect 0078 stub CreateMDIWindowA 0079 stub CreateMDIWindowW -0080 stub CreateMenu +0080 stdcall CreateMenu() CreateMenu 0081 stdcall CreatePopupMenu() CreatePopupMenu 0082 stdcall CreateWindowExA(long ptr ptr long long long long long long long long ptr) CreateWindowEx32A @@ -146,10 +146,10 @@ base 1 0139 stdcall DialogBoxParamW(long ptr long ptr long) DialogBoxParam32W 0140 stdcall DispatchMessageA(ptr) USER32_DispatchMessageA 0141 stdcall DispatchMessageW(ptr) USER32_DispatchMessageA -0142 stub DlgDirListA +0142 stdcall DlgDirListA(long ptr long long long) DlgDirList32A 0143 stdcall DlgDirListComboBoxA(long ptr long long long) DlgDirListComboBox32A 0144 stdcall DlgDirListComboBoxW(long ptr long long long) DlgDirListComboBox32W -0145 stub DlgDirListW +0145 stdcall DlgDirListW(long ptr long long long) DlgDirList32W 0146 stdcall DlgDirSelectComboBoxExA(long ptr long long) DlgDirSelectComboBoxEx32A 0147 stdcall DlgDirSelectComboBoxExW(long ptr long long) DlgDirSelectComboBoxEx32W 0148 stdcall DlgDirSelectExA(long ptr long long) DlgDirSelectEx32A @@ -466,7 +466,7 @@ base 1 0459 stub SendNotifyMessageA 0460 stub SendNotifyMessageW 0461 stub ServerSetFunctionPointers -0462 stub SetActiveWindow +0462 stdcall SetActiveWindow(long) SetActiveWindow 0463 stdcall SetCapture(long) SetCapture32 0464 stdcall SetCaretBlinkTime(long) SetCaretBlinkTime 0465 stdcall SetCaretPos(long long) SetCaretPos diff --git a/if1632/wing.spec b/if1632/wing.spec index ec1ab43d816..f22122e9b0c 100644 --- a/if1632/wing.spec +++ b/if1632/wing.spec @@ -1,15 +1,16 @@ name wing type win16 -1001 stub WINGCREATEDC -1002 stub WINGRECOMMENDDIBFORMAT -1003 stub WINGCREATEBITMAP +1001 pascal16 WinGCreateDC() WinGCreateDC16 +1002 pascal16 WinGRecommendDIBFormat(ptr) WinGRecommendDIBFormat16 +1003 pascal16 WinGCreateBitmap(word ptr ptr) WinGCreateBitmap16 1004 stub WINGGETDIBPOINTER 1005 stub WINGGETDIBCOLORTABLE 1006 stub WINGSETDIBCOLORTABLE -1007 stub WINGCREATEHALFTONEPALETTE -1008 stub WINGCREATEHALFTONEBRUSH +1007 pascal16 WinGCreateHalfTonePalette() WinGCreateHalfTonePalette16 +1008 pascal16 WinGCreateHalfToneBrush(word long word) WinGCreateHalfToneBrush16 1009 stub WINGSTRETCHBLT +# Probably much like BitBlt16... but, without the last field (what value?) 1010 stub WINGBITBLT # Seem that 1299 is the limit... weird... diff --git a/if1632/winmm.spec b/if1632/winmm.spec index 570780382eb..44a06910472 100644 --- a/if1632/winmm.spec +++ b/if1632/winmm.spec @@ -139,7 +139,7 @@ type win32 0138 stub timeEndPeriod 0139 stub timeGetDevCaps 0140 stub timeGetSystemTime -0141 stub timeGetTime +0141 stdcall timeGetTime() timeGetTime 0142 stub timeKillEvent 0143 stub timeSetEvent 0144 stub waveInAddBuffer diff --git a/if1632/winsock.spec b/if1632/winsock.spec index 5048f838cb7..24d2fc0c704 100644 --- a/if1632/winsock.spec +++ b/if1632/winsock.spec @@ -37,17 +37,17 @@ type win16 56 pascal getservbyport(word ptr) WINSOCK_getservbyport 57 pascal gethostname(ptr word) WINSOCK_gethostname 101 pascal16 WSAAsyncSelect(word word word long) WSAAsyncSelect -102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word ptr word) +102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word segptr word) WSAAsyncGetHostByAddr -103 pascal16 WSAAsyncGetHostByName(word word ptr ptr word) +103 pascal16 WSAAsyncGetHostByName(word word ptr segptr word) WSAAsyncGetHostByName -104 pascal16 WSAAsyncGetProtoByNumber(word word word ptr word) +104 pascal16 WSAAsyncGetProtoByNumber(word word word segptr word) WSAAsyncGetProtoByNumber -105 pascal16 WSAAsyncGetProtoByName(word word ptr ptr word) +105 pascal16 WSAAsyncGetProtoByName(word word ptr segptr word) WSAAsyncGetProtoByName -106 pascal16 WSAAsyncGetServByPort(word word word ptr ptr word) +106 pascal16 WSAAsyncGetServByPort(word word word ptr segptr word) WSAAsyncGetServByPort -107 pascal16 WSAAsyncGetServByName(word word ptr ptr ptr word) +107 pascal16 WSAAsyncGetServByName(word word ptr ptr segptr word) WSAAsyncGetServByName 108 pascal16 WSACancelAsyncRequest(word) WSACancelAsyncRequest 109 pascal16 WSASetBlockingHook() WSASetBlockingHook @@ -58,4 +58,4 @@ type win16 114 pascal16 WSAIsBlocking() WSAIsBlocking 115 pascal WSAStartup(word ptr) WSAStartup 116 pascal WSACleanup() WSACleanup -151 pascal16 __WSAFDIsSet(word ptr) WSAFDIsSet +151 pascal16 __WSAFDIsSet(word ptr) __WSAFDIsSet diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec index 07d63e76ea6..3522fecf145 100644 --- a/if1632/wprocs.spec +++ b/if1632/wprocs.spec @@ -4,7 +4,6 @@ type win16 1 pascal WINPROC_CallProc16To32A(word word word long long) WINPROC_CallProc16To32A 2 pascal StaticWndProc(word word word long) StaticWndProc 3 pascal ScrollBarWndProc(word word word long) ScrollBarWndProc -4 pascal ListBoxWndProc(word word word long) ListBoxWndProc 5 pascal ComboBoxWndProc(word word word long) ComboBoxWndProc 6 pascal EditWndProc(word word word long) EditWndProc 7 pascal PopupMenuWndProc(word word word long) PopupMenuWndProc diff --git a/include/config.h.in b/include/config.h.in index 638652aa6c5..cf00d2821d2 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -3,9 +3,6 @@ /* Define to empty if the keyword does not work. */ #undef const -/* Define if you need to in order for stat and other things to work. */ -#undef _POSIX_SOURCE - /* Define to `unsigned' if doesn't define. */ #undef size_t @@ -15,6 +12,9 @@ /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + /* Define if symbols declared in assembly code need an underscore prefix */ #undef NEED_UNDERSCORE_PREFIX diff --git a/include/dce.h b/include/dce.h index 06ff0629e8e..b21ec2a94e9 100644 --- a/include/dce.h +++ b/include/dce.h @@ -8,6 +8,7 @@ #define DCE_H #include "windows.h" +#include "win.h" /* additional DCX flags */ @@ -44,8 +45,9 @@ typedef struct tagDCE } DCE; -extern void DCE_Init(void); -extern DCE *DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type ); -extern void DCE_FreeDCE( DCE *dce ); +extern void DCE_Init(void); +extern DCE* DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type ); +extern void DCE_FreeDCE( DCE *dce ); +extern INT16 DCE_ExcludeRgn( HDC32, WND*, HRGN32 ); #endif /* DCE_H */ diff --git a/include/hook.h b/include/hook.h index 535afc27d66..2a9857b5849 100644 --- a/include/hook.h +++ b/include/hook.h @@ -13,6 +13,7 @@ extern HANDLE16 HOOK_GetHook( INT16 id , HQUEUE16 hQueue ); extern LRESULT HOOK_CallHooks( INT16 id, INT16 code, WPARAM16 wParam, LPARAM lParam ); extern HOOKPROC16 HOOK_GetProc16( HHOOK hook ); +extern void HOOK_ResetQueueHooks( HQUEUE16 hQueue ); extern void HOOK_FreeModuleHooks( HMODULE16 hModule ); extern void HOOK_FreeQueueHooks( HQUEUE16 hQueue ); diff --git a/include/keyboard.h b/include/keyboard.h new file mode 100644 index 00000000000..95f681ce678 --- /dev/null +++ b/include/keyboard.h @@ -0,0 +1,32 @@ +/* + * Keyboard definitions + * + */ + +#ifndef __WINE_KEYBOARD_H +#define __WINE_KEYBOARD_H + +#define WINE_VKEY_MAPPINGS\ + vkcase('!', '1')\ + vkcase('@', '2')\ + vkcase('#', '3')\ + vkcase('$', '4')\ + vkcase('%', '5')\ + vkcase('^', '6')\ + vkcase('&', '7')\ + vkcase('*', '8')\ + vkcase('(', '9')\ + vkcase(')', '0')\ + vkcase2('`', '~', 0xc0)\ + vkcase2('-', '_', 0xbd)\ + vkcase2('=', '+', 0xbb)\ + vkcase2('[', '{', 0xdb)\ + vkcase2(']', '}', 0xdd)\ + vkcase2(';', ':', 0xba)\ + vkcase2('\'', '"', 0xde)\ + vkcase2(',', '<', 0xbc)\ + vkcase2('.', '>', 0xbe)\ + vkcase2('/', '?', 0xbf)\ + vkcase2('\\', '|', 0xdc) + +#endif /* __WINE_KEYBOARD_H */ diff --git a/include/listbox.h b/include/listbox.h index 3cfe426c739..ebee8137a94 100644 --- a/include/listbox.h +++ b/include/listbox.h @@ -69,5 +69,3 @@ extern void ListBoxDrawItem (HWND hwnd, LPHEADLIST lphl, HDC16 hdc, WORD itemState); extern int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y); extern void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls); - -extern LRESULT ListBoxWndProc(HWND hwnd,UINT message,WPARAM16 wParam,LPARAM lParam); diff --git a/include/win.h b/include/win.h index 18c3321d4ee..445ee3bd07a 100644 --- a/include/win.h +++ b/include/win.h @@ -92,7 +92,7 @@ extern BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter ); extern HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue ); extern void WIN_SendParentNotify( HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue ); -extern void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue ); +extern void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew ); extern BOOL32 WIN_CreateDesktopWindow(void); extern HWND32 WIN_GetTopParent( HWND32 hwnd ); extern BOOL32 WIN_IsWindowDrawable(WND*, BOOL32 ); diff --git a/include/windows.h b/include/windows.h index 8e03f4998b6..2cf3596866e 100644 --- a/include/windows.h +++ b/include/windows.h @@ -920,8 +920,40 @@ typedef struct WCHAR elfStyle[LF_FACESIZE] WINE_PACKED; } ENUMLOGFONT32W, *LPENUMLOGFONT32W; +typedef struct +{ + LOGFONT16 elfLogFont; + BYTE elfFullName[LF_FULLFACESIZE] WINE_PACKED; + BYTE elfStyle[LF_FACESIZE] WINE_PACKED; + BYTE elfScript[LF_FACESIZE] WINE_PACKED; +} ENUMLOGFONTEX16, *LPENUMLOGFONTEX16; + +typedef struct +{ + LOGFONT32A elfLogFont; + BYTE elfFullName[LF_FULLFACESIZE] WINE_PACKED; + BYTE elfStyle[LF_FACESIZE] WINE_PACKED; + BYTE elfScript[LF_FACESIZE] WINE_PACKED; +} ENUMLOGFONTEX32A,*LPENUMLOGFONTEX32A; + +typedef struct +{ + LOGFONT32W elfLogFont; + WCHAR elfFullName[LF_FULLFACESIZE] WINE_PACKED; + WCHAR elfStyle[LF_FACESIZE] WINE_PACKED; + WCHAR elfScript[LF_FACESIZE] WINE_PACKED; +} ENUMLOGFONTEX32W,*LPENUMLOGFONTEX32W; + DECL_WINELIB_TYPE_AW(ENUMLOGFONT); DECL_WINELIB_TYPE_AW(LPENUMLOGFONT); +DECL_WINELIB_TYPE_AW(LPENUMLOGFONTEX); + +typedef struct +{ + DWORD fsUsb[4]; + DWORD fsCsb[2]; +} FONTSIGNATURE,*LPFONTSIGNATURE; + /* lfWeight values */ #define FW_DONTCARE 0 @@ -1057,11 +1089,130 @@ typedef struct DECL_WINELIB_TYPE_AW(TEXTMETRIC); DECL_WINELIB_TYPE_AW(LPTEXTMETRIC); +/* ntmFlags field flags */ +#define NTM_REGULAR 0x00000040L +#define NTM_BOLD 0x00000020L +#define NTM_ITALIC 0x00000001L + +typedef struct +{ + INT16 tmHeight; + INT16 tmAscent; + INT16 tmDescent; + INT16 tmInternalLeading; + INT16 tmExternalLeading; + INT16 tmAveCharWidth; + INT16 tmMaxCharWidth; + INT16 tmWeight; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmFirstChar; + BYTE tmLastChar; + BYTE tmDefaultChar; + BYTE tmBreakChar; + BYTE tmPitchAndFamily; + BYTE tmCharSet; + INT16 tmOverhang WINE_PACKED; + INT16 tmDigitizedAspectX WINE_PACKED; + INT16 tmDigitizedAspectY WINE_PACKED; + DWORD ntmFlags; + UINT16 ntmSizeEM; + UINT16 ntmCellHeight; + UINT16 ntmAvgWidth; +} NEWTEXTMETRIC16,*LPNEWTEXTMETRIC16; + +typedef struct +{ + INT32 tmHeight; + INT32 tmAscent; + INT32 tmDescent; + INT32 tmInternalLeading; + INT32 tmExternalLeading; + INT32 tmAveCharWidth; + INT32 tmMaxCharWidth; + INT32 tmWeight; + INT32 tmOverhang; + INT32 tmDigitizedAspectX; + INT32 tmDigitizedAspectY; + BYTE tmFirstChar; + BYTE tmLastChar; + BYTE tmDefaultChar; + BYTE tmBreakChar; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmPitchAndFamily; + BYTE tmCharSet; + DWORD ntmFlags; + UINT32 ntmSizeEM; + UINT32 ntmCellHeight; + UINT32 ntmAvgWidth; +} NEWTEXTMETRIC32A, *LPNEWTEXTMETRIC32A; + +typedef struct +{ + INT32 tmHeight; + INT32 tmAscent; + INT32 tmDescent; + INT32 tmInternalLeading; + INT32 tmExternalLeading; + INT32 tmAveCharWidth; + INT32 tmMaxCharWidth; + INT32 tmWeight; + INT32 tmOverhang; + INT32 tmDigitizedAspectX; + INT32 tmDigitizedAspectY; + WCHAR tmFirstChar; + WCHAR tmLastChar; + WCHAR tmDefaultChar; + WCHAR tmBreakChar; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmPitchAndFamily; + BYTE tmCharSet; + DWORD ntmFlags; + UINT32 ntmSizeEM; + UINT32 ntmCellHeight; + UINT32 ntmAvgWidth; +} NEWTEXTMETRIC32W, *LPNEWTEXTMETRIC32W; + +DECL_WINELIB_TYPE_AW(NEWTEXTMETRIC); +DECL_WINELIB_TYPE_AW(LPNEWTEXTMETRIC); + +typedef struct +{ + NEWTEXTMETRIC16 ntmetm; + FONTSIGNATURE ntmeFontSignature; +} NEWTEXTMETRICEX16,*LPNEWTEXTMETRICEX16; + +typedef struct +{ + NEWTEXTMETRIC32A ntmetm; + FONTSIGNATURE ntmeFontSignature; +} NEWTEXTMETRICEX32A,*LPNEWTEXTMETRICEX32A; + +typedef struct +{ + NEWTEXTMETRIC32W ntmetm; + FONTSIGNATURE ntmeFontSignature; +} NEWTEXTMETRICEX32W,*LPNEWTEXTMETRICEX32W; + +DECL_WINELIB_TYPE_AW(NEWTEXTMETRICEX); +DECL_WINELIB_TYPE_AW(LPNEWTEXTMETRICEX); + + typedef INT16 (*FONTENUMPROC16)(SEGPTR,SEGPTR,UINT16,LPARAM); -typedef INT32 (*FONTENUMPROC32A)(const LOGFONT32A*,const TEXTMETRIC32A*,UINT32,LPARAM); -typedef INT32 (*FONTENUMPROC32W)(const LOGFONT32W*,const TEXTMETRIC32W*,UINT32,LPARAM); +typedef INT32 (*FONTENUMPROC32A)(LPENUMLOGFONT32A,LPNEWTEXTMETRIC32A,UINT32,LPARAM); +typedef INT32 (*FONTENUMPROC32W)(LPENUMLOGFONT32W,LPNEWTEXTMETRIC32W,UINT32,LPARAM); DECL_WINELIB_TYPE_AW(FONTENUMPROC); +typedef INT16 (*FONTENUMPROCEX16)(SEGPTR,SEGPTR,UINT16,LPARAM); +typedef INT32 (*FONTENUMPROCEX32A)(LPENUMLOGFONTEX32A,LPNEWTEXTMETRICEX32A,UINT32,LPARAM); +typedef INT32 (*FONTENUMPROCEX32W)(LPENUMLOGFONTEX32W,LPNEWTEXTMETRICEX32W,UINT32,LPARAM); +DECL_WINELIB_TYPE_AW(FONTENUMPROCEX); + /* tmPitchAndFamily values */ #define TMPF_FIXED_PITCH 1 #define TMPF_VECTOR 2 @@ -2724,7 +2875,12 @@ typedef struct #define LB_FINDSTRINGEXACT16 (WM_USER+35) #define LB_FINDSTRINGEXACT32 0x01a2 #define LB_FINDSTRINGEXACT WINELIB_NAME(LB_FINDSTRINGEXACT) -/* Here are 2 undocumented messages used by ComboLBoxes */ +#define LB_CARETON16 (WM_USER+36) +#define LB_CARETON32 0x01a3 +#define LB_CARETON WINELIB_NAME(LB_CARETON) +#define LB_CARETOFF16 (WM_USER+37) +#define LB_CARETOFF32 0x01a4 +#define LB_CARETOFF WINELIB_NAME(LB_CARETOFF) #define LB_SETLOCALE16 WM_NULL /* Not in Win16 */ #define LB_SETLOCALE32 0x01a5 #define LB_SETLOCALE WINELIB_NAME(LB_SETLOCALE) @@ -3088,16 +3244,22 @@ DECL_WINELIB_TYPE(LPCOMPAREITEMSTRUCT); #define VK_RBUTTON 0x02 #define VK_CANCEL 0x03 #define VK_MBUTTON 0x04 +/* 0x05-0x07 Undefined */ #define VK_BACK 0x08 #define VK_TAB 0x09 +/* 0x0A-0x0B Undefined */ #define VK_CLEAR 0x0C #define VK_RETURN 0x0D +/* 0x0E-0x0F Undefined */ #define VK_SHIFT 0x10 #define VK_CONTROL 0x11 #define VK_MENU 0x12 #define VK_PAUSE 0x13 #define VK_CAPITAL 0x14 +/* 0x15-0x19 Reserved for Kanji systems */ +/* 0x1A Undefined */ #define VK_ESCAPE 0x1B +/* 0x1C-0x1F Reserved for Kanji systems */ #define VK_SPACE 0x20 #define VK_PRIOR 0x21 #define VK_NEXT 0x22 @@ -3108,12 +3270,50 @@ DECL_WINELIB_TYPE(LPCOMPAREITEMSTRUCT); #define VK_RIGHT 0x27 #define VK_DOWN 0x28 #define VK_SELECT 0x29 -#define VK_PRINT 0x2A +#define VK_PRINT 0x2A /* OEM specific in Windows 3.1 SDK */ #define VK_EXECUTE 0x2B #define VK_SNAPSHOT 0x2C #define VK_INSERT 0x2D #define VK_DELETE 0x2E #define VK_HELP 0x2F +#define VK_0 0x30 +#define VK_1 0x31 +#define VK_2 0x32 +#define VK_3 0x33 +#define VK_4 0x34 +#define VK_5 0x35 +#define VK_6 0x36 +#define VK_7 0x37 +#define VK_8 0x38 +#define VK_9 0x39 +/* 0x3A-0x40 Undefined */ +#define VK_A 0x41 +#define VK_B 0x42 +#define VK_C 0x43 +#define VK_D 0x44 +#define VK_E 0x45 +#define VK_F 0x46 +#define VK_G 0x47 +#define VK_H 0x48 +#define VK_I 0x49 +#define VK_J 0x4A +#define VK_K 0x4B +#define VK_L 0x4C +#define VK_M 0x4D +#define VK_N 0x4E +#define VK_O 0x4F +#define VK_P 0x50 +#define VK_Q 0x51 +#define VK_R 0x52 +#define VK_S 0x53 +#define VK_T 0x54 +#define VK_U 0x55 +#define VK_V 0x56 +#define VK_W 0x57 +#define VK_X 0x58 +#define VK_Y 0x59 +#define VK_Z 0x5A +/* 0x5B-0x5F Undefined */ #define VK_NUMPAD0 0x60 #define VK_NUMPAD1 0x61 #define VK_NUMPAD2 0x62 @@ -3154,8 +3354,18 @@ DECL_WINELIB_TYPE(LPCOMPAREITEMSTRUCT); #define VK_F22 0x85 #define VK_F23 0x86 #define VK_F24 0x87 +/* 0x88-0x8F Unassigned */ #define VK_NUMLOCK 0x90 #define VK_SCROLL 0x91 +/* 0x92-0xB9 Unassigned */ +/* 0xBA-0xC0 OEM specific */ +/* 0xC1-0xDA Unassigned */ +/* 0xDB-0xE4 OEM specific */ +/* 0xE5 Unassigned */ +/* 0xE6 OEM specific */ +/* 0xE7-0xE8 Unassigned */ +/* 0xE9-0xF5 OEM specific */ +/* 0xF6-0xFE Unassigned */ #define LMEM_FIXED 0 @@ -3705,6 +3915,10 @@ typedef BOOL32 (*CODEPAGE_ENUMPROC32A)(LPSTR); typedef BOOL32 (*CODEPAGE_ENUMPROC32W)(LPWSTR); DECL_WINELIB_TYPE_AW(CODEPAGE_ENUMPROC); +typedef BOOL32 (*LOCALE_ENUMPROC32A)(LPSTR); +typedef BOOL32 (*LOCALE_ENUMPROC32W)(LPWSTR); +DECL_WINELIB_TYPE_AW(LOCALE_ENUMPROC); + typedef struct tagSYSTEM_INFO { DWORD dwOemId; @@ -3742,10 +3956,6 @@ BOOL16 FastWindowFrame(HDC16,const RECT16*,INT16,INT16,DWORD); VOID FillWindow(HWND16,HWND16,HDC16,HBRUSH16); INT16 FlushComm(INT16,INT16); WORD FreeSelector(WORD); -void GlobalFreeAll(HGLOBAL16); -HGLOBAL16 GlobalLRUNewest(HGLOBAL16); -HGLOBAL16 GlobalLRUOldest(HGLOBAL16); -VOID GlobalNotify(FARPROC16); HANDLE16 GetAtomHandle(ATOM); DWORD GetBitmapDimension(HBITMAP16); HANDLE16 GetCodeHandle(FARPROC16); @@ -3755,6 +3965,7 @@ VOID GetCodeInfo(FARPROC16,LPVOID); HANDLE16 GetCurrentPDB(void); HTASK16 GetCurrentTask(void); DWORD GetDCHook(HDC16,FARPROC16*); +DWORD GetDCOrg(HDC16); HWND16 GetDesktopHwnd(void); HMODULE16 GetExePtr(HANDLE16); WORD GetExeVersion(void); @@ -3768,6 +3979,10 @@ HINSTANCE16 GetTaskDS(void); HQUEUE16 GetTaskQueue(HTASK16); DWORD GlobalDOSAlloc(DWORD); WORD GlobalDOSFree(WORD); +void GlobalFreeAll(HGLOBAL16); +HGLOBAL16 GlobalLRUNewest(HGLOBAL16); +HGLOBAL16 GlobalLRUOldest(HGLOBAL16); +VOID GlobalNotify(FARPROC16); WORD GlobalPageLock(HGLOBAL16); WORD GlobalPageUnlock(HGLOBAL16); INT16 InitApp(HINSTANCE16); @@ -3815,6 +4030,7 @@ INT16 UngetCommChar(INT16,CHAR); VOID UserYield(void); BOOL16 WaitEvent(HTASK16); INT16 WriteComm(INT16,LPSTR,INT16); +VOID WriteOutProfiles(VOID); VOID hmemcpy(LPVOID,LPCVOID,LONG); VOID Yield(void); @@ -3835,6 +4051,9 @@ INT32 EnumPropsEx32W(HWND32,PROPENUMPROCEX32W,LPARAM); BOOL32 EnumSystemCodePages32A(CODEPAGE_ENUMPROC32A,DWORD); BOOL32 EnumSystemCodePages32W(CODEPAGE_ENUMPROC32W,DWORD); #define EnumSystemCodePages WINELIB_NAME_AW(EnumSystemCodePages) +BOOL32 EnumSystemLocales32A(LOCALE_ENUMPROC32A,DWORD); +BOOL32 EnumSystemLocales32W(LOCALE_ENUMPROC32W,DWORD); +#define EnumSystemLocales WINELIB_NAME_AW(EnumSystemLocales) BOOL32 EnumThreadWindows(DWORD,WNDENUMPROC32,LPARAM); void ExitProcess(DWORD); BOOL32 FileTimeToDosDateTime(LPFILETIME,LPWORD,LPWORD); @@ -3848,6 +4067,7 @@ LPCSTR GetCommandLine32A(); LPCWSTR GetCommandLine32W(); #define GetCommandLine WINELIB_NAME_AW(GetCommandLine) BOOL32 GetCommTimeouts(INT32,LPCOMMTIMEOUTS); +BOOL32 GetDCOrgEx(HDC32,LPPOINT32); DWORD GetFileInformationByHandle(HFILE,BY_HANDLE_FILE_INFORMATION*); DWORD GetFileSize(HFILE,LPDWORD); DWORD GetFileType(HFILE); @@ -3873,6 +4093,7 @@ DWORD HeapSize(HANDLE32,DWORD,LPVOID); BOOL32 HeapUnlock(HANDLE32); BOOL32 HeapValidate(HANDLE32,DWORD,LPVOID); BOOL32 IsWindowUnicode(HWND32); +BOOL32 IsValidLocale(DWORD,DWORD); BOOL32 LocalFileTimeToFileTime(LPFILETIME,LPFILETIME); LPVOID MapViewOfFileEx(HANDLE32,DWORD,DWORD,DWORD,DWORD,DWORD); BOOL32 MoveFile32A(LPCSTR,LPCSTR); @@ -4220,7 +4441,11 @@ INT16 DialogBoxParam16(HINSTANCE16,SEGPTR,HWND16,DLGPROC16,LPARAM); INT32 DialogBoxParam32A(HINSTANCE32,LPCSTR,HWND32,DLGPROC32,LPARAM); INT32 DialogBoxParam32W(HINSTANCE32,LPCWSTR,HWND32,DLGPROC32,LPARAM); #define DialogBoxParam WINELIB_NAME_AW(DialogBoxParam) -INT16 DlgDirListComboBox16(HWND16,SEGPTR,INT16,INT16,UINT16); +INT16 DlgDirList16(HWND16,LPCSTR,INT16,INT16,UINT16); +INT32 DlgDirList32A(HWND32,LPCSTR,INT32,INT32,UINT32); +INT32 DlgDirList32W(HWND32,LPCWSTR,INT32,INT32,UINT32); +#define DlgDirList WINELIB_NAME_AW(DlgDirList) +INT16 DlgDirListComboBox16(HWND16,LPCSTR,INT16,INT16,UINT16); INT32 DlgDirListComboBox32A(HWND32,LPCSTR,INT32,INT32,UINT32); INT32 DlgDirListComboBox32W(HWND32,LPCWSTR,INT32,INT32,UINT32); #define DlgDirListComboBox WINELIB_NAME_AW(DlgDirListComboBox) @@ -4264,6 +4489,14 @@ INT16 EnumFontFamilies16(HDC16,LPCSTR,FONTENUMPROC16,LPARAM); INT32 EnumFontFamilies32A(HDC32,LPCSTR,FONTENUMPROC32A,LPARAM); INT32 EnumFontFamilies32W(HDC32,LPCWSTR,FONTENUMPROC32W,LPARAM); #define EnumFontFamilies WINELIB_NAME_AW(EnumFontFamilies) +INT16 EnumFontFamiliesEx16(HDC16,LPLOGFONT16,FONTENUMPROCEX16,LPARAM,DWORD); +INT32 EnumFontFamiliesEx32A(HDC32,LPLOGFONT32A,FONTENUMPROCEX32A,LPARAM,DWORD); +INT32 EnumFontFamiliesEx32W(HDC32,LPLOGFONT32W,FONTENUMPROCEX32W,LPARAM,DWORD); +#define EnumFontFamiliesEx WINELIB_NAME_AW(EnumFontFamiliesEx) +INT16 EnumFonts16(HDC16,LPCSTR,FONTENUMPROC16,LPARAM); +INT32 EnumFonts32A(HDC32,LPCSTR,FONTENUMPROC32A,LPARAM); +INT32 EnumFonts32W(HDC32,LPCWSTR,FONTENUMPROC32W,LPARAM); +#define EnumFonts WINELIB_NAME_AW(EnumFonts) INT16 EnumObjects16(HDC16,INT16,GOBJENUMPROC16,LPARAM); INT32 EnumObjects32(HDC32,INT32,GOBJENUMPROC32,LPARAM); #define EnumObjects WINELIB_NAME(EnumObjects) @@ -4384,6 +4617,9 @@ INT32 GetClipBox32(HDC32,LPRECT32); void GetClipCursor16(LPRECT16); void GetClipCursor32(LPRECT32); #define GetClipCursor WINELIB_NAME(GetClipCursor) +HRGN16 GetClipRgn16(HDC16); +INT32 GetClipRgn32(HDC32,HRGN32); +#define GetClipRgn WINELIB_NAME(GetClipRgn) INT16 GetCommState16(INT16,LPDCB16); BOOL32 GetCommState32(INT32,LPDCB32); #define GetCommState WINELIB_NAME(GetCommState) @@ -4459,9 +4695,25 @@ HWND32 GetParent32(HWND32); COLORREF GetPixel16(HDC16,INT16,INT16); COLORREF GetPixel32(HDC32,INT32,INT32); #define GetPixel WINELIB_NAME(GetPixel) +UINT16 GetPrivateProfileInt16(LPCSTR,LPCSTR,INT16,LPCSTR); +UINT32 GetPrivateProfileInt32A(LPCSTR,LPCSTR,INT32,LPCSTR); +UINT32 GetPrivateProfileInt32W(LPCWSTR,LPCWSTR,INT32,LPCWSTR); +#define GetPrivateProfileInt WINELIB_NAME_AW(GetPrivateProfileInt) +INT16 GetPrivateProfileString16(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT16,LPCSTR); +INT32 GetPrivateProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT32,LPCSTR); +INT32 GetPrivateProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPWSTR,INT32,LPCWSTR); +#define GetPrivateProfileString WINELIB_NAME_AW(GetPrivateProfileString) FARPROC16 GetProcAddress16(HMODULE16,SEGPTR); FARPROC32 GetProcAddress32(HMODULE32,LPCSTR); #define GetProcAddress WINELIB_NAME(GetProcAddress) +UINT16 GetProfileInt16(LPCSTR,LPCSTR,INT16); +UINT32 GetProfileInt32A(LPCSTR,LPCSTR,INT32); +UINT32 GetProfileInt32W(LPCWSTR,LPCWSTR,INT32); +#define GetProfileInt WINELIB_NAME_AW(GetProfileInt) +INT16 GetProfileString16(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT16); +INT32 GetProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT32); +INT32 GetProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPWSTR,INT32); +#define GetProfileString WINELIB_NAME_AW(GetProfileString) HANDLE16 GetProp16(HWND16,LPCSTR); HANDLE32 GetProp32A(HWND32,LPCSTR); HANDLE32 GetProp32W(HWND32,LPCWSTR); @@ -5099,6 +5351,14 @@ HWND32 WindowFromDC32(HDC32); HWND16 WindowFromPoint16(POINT16); HWND32 WindowFromPoint32(POINT32); #define WindowFromPoint WINELIB_NAME(WindowFromPoint) +BOOL16 WritePrivateProfileString16(LPCSTR,LPCSTR,LPCSTR,LPCSTR); +BOOL32 WritePrivateProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPCSTR); +BOOL32 WritePrivateProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR); +#define WritePrivateProfileString WINELIB_NAME_AW(WritePrivateProfileString) +BOOL16 WriteProfileString16(LPCSTR,LPCSTR,LPCSTR); +BOOL32 WriteProfileString32A(LPCSTR,LPCSTR,LPCSTR); +BOOL32 WriteProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR); +#define WriteProfileString WINELIB_NAME_AW(WriteProfileString) SEGPTR lstrcat16(SEGPTR,SEGPTR); LPSTR lstrcat32A(LPSTR,LPCSTR); LPWSTR lstrcat32W(LPWSTR,LPCWSTR); @@ -5238,7 +5498,6 @@ BOOL DestroyIcon(HICON16); BOOL DestroyMenu(HMENU16); BOOL DestroyWindow(HWND); LONG DispatchMessage(const MSG16*); -INT DlgDirList(HWND,SEGPTR,INT,INT,UINT); BOOL16 DragDetect(HWND16,POINT16); DWORD DragObject(HWND, HWND, WORD, HANDLE16, WORD, HCURSOR16); BOOL DrawIcon(HDC16,INT,INT,HICON16); @@ -5249,7 +5508,6 @@ BOOL EnableMenuItem(HMENU16,UINT,UINT); BOOL EnableWindow(HWND,BOOL); BOOL EndDeferWindowPos(HDWP16); UINT16 EnumClipboardFormats(UINT16); -INT EnumFonts(HDC16,LPCSTR,FONTENUMPROC16,LPARAM); BOOL EnumMetaFile(HDC16,HMETAFILE16,MFENUMPROC16,LPARAM); INT Escape(HDC16,INT,INT,SEGPTR,SEGPTR); BOOL ExitWindows(DWORD,WORD); @@ -5271,7 +5529,6 @@ WORD GetBkMode(HDC16); DWORD GetBrushOrg(HDC16); BOOL GetCharABCWidths(HDC16,UINT,UINT,LPABC16); BOOL GetCharWidth(HDC16,WORD,WORD,LPINT16); -HRGN32 GetClipRgn(HDC16); HANDLE16 GetClipboardData(WORD); int GetClipboardFormatName(WORD,LPSTR,short); HWND GetClipboardOwner(void); @@ -5280,7 +5537,6 @@ HBRUSH16 GetControlBrush(HWND,HDC16,WORD); DWORD GetCurrentPosition(HDC16); DWORD GetCurrentTime(void); HCURSOR16 GetCursor(void); -DWORD GetDCOrg(HDC16); HDC16 GetDCState(HDC16); int GetDIBits(HDC16,HBITMAP16,WORD,WORD,LPSTR,LPBITMAPINFO,WORD); SEGPTR GetDOSEnvironment(void); @@ -5323,10 +5579,6 @@ HWND GetOpenClipboardWindow(void); WORD GetPaletteEntries(HPALETTE16,WORD,WORD,LPPALETTEENTRY); WORD GetPolyFillMode(HDC16); int GetPriorityClipboardFormat(WORD*,short); -UINT GetPrivateProfileInt(LPCSTR,LPCSTR,INT,LPCSTR); -INT GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT,LPCSTR); -UINT GetProfileInt(LPCSTR,LPCSTR,INT); -INT GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT); DWORD GetQueueStatus(UINT); BOOL GetRasterizerCaps(LPRASTERIZER_STATUS,UINT); WORD GetROP2(HDC16); @@ -5484,9 +5736,6 @@ void WaitMessage(void); int WaitSoundState(int); HINSTANCE16 WinExec(LPSTR,WORD); BOOL WinHelp(HWND,LPSTR,WORD,DWORD); -void WriteOutProfiles(void); -BOOL WritePrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPCSTR); -BOOL WriteProfileString(LPCSTR,LPCSTR,LPCSTR); #endif /* NO_TRANSITION_TYPES */ diff --git a/include/winnls.h b/include/winnls.h index 6791fd300b4..04c92d40ac7 100644 --- a/include/winnls.h +++ b/include/winnls.h @@ -1,6 +1,9 @@ #ifndef __WINE_WINNLS_H #define __WINE_WINNLS_H +/* When adding new defines, don't forget to add an entry to the + * locale2id map in misc/ole2nls.c + */ #define LOCALE_ILANGUAGE 0x00000001 #define LOCALE_SLANGUAGE 0x00000002 #define LOCALE_SENGLANGUAGE 0x00001001 diff --git a/include/winproc.h b/include/winproc.h index f5ce4f5a12a..1a5ba1117b4 100644 --- a/include/winproc.h +++ b/include/winproc.h @@ -50,9 +50,9 @@ extern void WINPROC_UnmapMsg16To32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam ); extern void WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam ); -extern void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, +extern void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam ); -extern void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam, +extern void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam ); #endif /* __WINE_WINPROC_H */ diff --git a/include/winsock.h b/include/winsock.h index 95482297a3e..9119c01a96c 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -16,26 +16,112 @@ #include #include "windows.h" -/* - * The new type to be used in all - * instances which refer to sockets. - */ -typedef u_int SOCKET; - -extern int __WSAFDIsSet(SOCKET, fd_set *); - -/* - * Internet address (old style... should be updated) - */ -#ifdef WS_USE_OLD_STYLE -#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ -#define s_host S_un.S_un_b.s_b2 /* host on imp */ -#define s_net S_un.S_un_b.s_b1 /* network */ -#define s_imp S_un.S_un_w.s_w2 /* imp */ -#define s_impno S_un.S_un_b.s_b4 /* imp # */ -#define s_lh S_un.S_un_b.s_b3 /* logical host */ +#ifndef WINELIB +#pragma pack(1) /* tight alignment for the emulator */ #endif +/* Win16 socket-related types */ + +typedef UINT16 SOCKET16; + +typedef struct ws_hostent +{ + SEGPTR h_name; /* official name of host */ + SEGPTR h_aliases; /* alias list */ + INT16 h_addrtype; /* host address type */ + INT16 h_length; /* length of address */ + SEGPTR h_addr_list; /* list of addresses from name server */ +} _ws_hostent; + +typedef struct ws_protoent +{ + SEGPTR p_name; /* official protocol name */ + SEGPTR p_aliases; /* alias list */ + INT16 p_proto; /* protocol # */ +} _ws_protoent; + +typedef struct ws_servent +{ + SEGPTR s_name; /* official service name */ + SEGPTR s_aliases; /* alias list */ + INT16 s_port; /* port # */ + SEGPTR s_proto; /* protocol to use */ +} _ws_servent; + +typedef struct ws_netent +{ + SEGPTR n_name; /* official name of net */ + SEGPTR n_aliases; /* alias list */ + INT16 n_addrtype; /* net address type */ + INT32 n_net; /* network # */ +} _ws_netent; + +typedef struct sockaddr ws_sockaddr; + +typedef struct +{ + UINT16 fd_count; /* how many are SET? */ + SOCKET16 fd_array[FD_SETSIZE]; /* an array of SOCKETs */ +} ws_fd_set; + +/* ws_fd_set operations */ + +INT16 __WSAFDIsSet( SOCKET16, ws_fd_set * ); + +#define WS_FD_CLR(fd, set) do { \ + UINT16 __i; \ + for (__i = 0; __i < ((ws_fd_set*)(set))->fd_count ; __i++) \ + { \ + if (((ws_fd_set*)(set))->fd_array[__i] == fd) \ + { \ + while (__i < ((ws_fd_set*)(set))->fd_count-1) \ + { \ + ((ws_fd_set*)(set))->fd_array[__i] = \ + ((ws_fd_set*)(set))->fd_array[__i+1]; \ + __i++; \ + } \ + ((ws_fd_set*)(set))->fd_count--; \ + break; \ + } \ + } \ +} while(0) + +#define WS_FD_SET(fd, set) do { \ + if (((ws_fd_set*)(set))->fd_count < FD_SETSIZE) \ + ((ws_fd_set*)(set))->fd_array[((ws_fd_set*)(set))->fd_count++]=(fd);\ +} while(0) + +#define WS_FD_ZERO(set) (((ws_fd_set*)(set))->fd_count=0) + +#define WS_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET16)(fd), (ws_fd_set*)(set)) + +/* + * Internet address (old style... should be updated) + */ + +typedef struct ws_addr_in +{ + union { + struct { BYTE s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { UINT16 s_w1,s_w2; } S_un_w; + UINT32 S_addr; + } S_un; +#define ws_addr S_un.S_addr /* can be used for most tcp & ip code */ +#define ws_host S_un.S_un_b.s_b2 /* host on imp */ +#define ws_net S_un.S_un_b.s_b1 /* network */ +#define ws_imp S_un.S_un_w.s_w2 /* imp */ +#define ws_impno S_un.S_un_b.s_b4 /* imp # */ +#define ws_lh S_un.S_un_b.s_b3 /* logical host */ +} _ws_in_addr; + +typedef struct ws_sockaddr_in +{ + INT16 sin_family; + UINT16 sin_port; + _ws_in_addr sin_addr; + char sin_zero[8]; +} _ws_sockaddr_in; + #define WSADESCRIPTION_LEN 256 #define WSASYS_STATUS_LEN 128 @@ -44,24 +130,79 @@ typedef struct WSAData { WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; - unsigned short iMaxSockets; - unsigned short iMaxUdpDg; - char *lpVendorInfo; + UINT16 iMaxSockets; + UINT16 iMaxUdpDg; + SEGPTR lpVendorInfo; } WSADATA, *LPWSADATA; +#ifndef WINELIB +#pragma pack(4) +#endif + +/* ----------------------------------- no Win16 structure defs beyond this line! */ + /* * This is used instead of -1, since the * SOCKET type is unsigned. */ -#define INVALID_SOCKET (SOCKET)(~0) -#define SOCKET_ERROR (-1) +#define INVALID_SOCKET (SOCKET16)(~0) +#define SOCKET_ERROR (-1) + +/* + * Types + */ +#define WS_SOCK_STREAM 1 /* stream socket */ +#define WS_SOCK_DGRAM 2 /* datagram socket */ +#define WS_SOCK_RAW 3 /* raw-protocol interface */ +#define WS_SOCK_RDM 4 /* reliably-delivered message */ +#define WS_SOCK_SEQPACKET 5 /* sequenced packet stream */ + +#define WS_SOL_SOCKET (-1) +#define WS_IPPROTO_TCP 6 /* * Option flags per-socket. */ -#ifndef SO_DONTLINGER -#define SO_DONTLINGER (u_int)(~SO_LINGER) -#endif +#define WS_SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define WS_SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define WS_SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define WS_SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define WS_SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define WS_SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define WS_SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define WS_SO_LINGER 0x0080 /* linger on close if data present */ +#define WS_SO_OOBINLINE 0x0100 /* leave received OOB data in line */ + +#define WS_SO_DONTLINGER (UINT16)(~WS_SO_LINGER) + +/* + * Additional options. + */ +#define WS_SO_SNDBUF 0x1001 /* send buffer size */ +#define WS_SO_RCVBUF 0x1002 /* receive buffer size */ +#define WS_SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define WS_SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define WS_SO_SNDTIMEO 0x1005 /* send timeout */ +#define WS_SO_RCVTIMEO 0x1006 /* receive timeout */ +#define WS_SO_ERROR 0x1007 /* get error status and clear */ +#define WS_SO_TYPE 0x1008 /* get socket type */ + +#define WS_IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ +#define WS_IOC_VOID 0x20000000 /* no parameters */ +#define WS_IOC_OUT 0x40000000 /* copy out parameters */ +#define WS_IOC_IN 0x80000000 /* copy in parameters */ +#define WS_IOC_INOUT (WS_IOC_IN|WS_IOC_OUT) +#define WS_IOR(x,y,t) (WS_IOC_OUT|(((UINT32)sizeof(t)&WS_IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#define WS_IOW(x,y,t) (WS_IOC_IN|(((UINT32)sizeof(t)&WS_IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +/* + * Socket I/O flags (supported by spec 1.1) + */ + +#define WS_FIONREAD WS_IOR('f', 127, u_long) +#define WS_FIONBIO WS_IOW('f', 126, u_long) + +#define WS_SIOCATMARK WS_IOR('s', 7, u_long) /* * Maximum queue length specifiable by listen. @@ -84,12 +225,17 @@ typedef struct WSAData { /* * Define flags to be used with the WSAAsyncSelect() call. */ -#define FD_READ 0x01 -#define FD_WRITE 0x02 -#define FD_OOB 0x04 -#define FD_ACCEPT 0x08 -#define FD_CONNECT 0x10 -#define FD_CLOSE 0x20 +#define WS_FD_READ 0x01 +#define WS_FD_WRITE 0x02 +#define WS_FD_OOB 0x04 +#define WS_FD_ACCEPT 0x08 +#define WS_FD_CONNECT 0x10 +#define WS_FD_CLOSE 0x20 + +#define WS_FD_NONBLOCK 0x10000000 /* internal per-socket flags */ +#define WS_FD_INACTIVE 0x20000000 +#define WS_FD_CONNECTED 0x40000000 +#define WS_FD_INTERNAL 0xFFFF0000 /* * All Windows Sockets error constants are biased by WSABASEERR from @@ -190,29 +336,35 @@ extern "C" { /* Microsoft Windows Extension function prototypes */ -INT WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData); -INT WSACleanup(void); -void WSASetLastError(INT iError); -INT WSAGetLastError(void); -BOOL WSAIsBlocking(void); -INT WSAUnhookBlockingHook(void); +INT16 WSAStartup(UINT16 wVersionRequired, LPWSADATA lpWSAData); +INT16 WSACleanup(void); +void WSASetLastError(INT16 iError); +INT16 WSAGetLastError(void); +BOOL16 WSAIsBlocking(void); +INT16 WSAUnhookBlockingHook(void); FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc); -INT WSACancelBlockingCall(void); -HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg, - LPCSTR name, LPCSTR proto, - LPSTR buf, INT buflen); -HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, - LPCSTR proto, LPSTR buf, INT buflen); -HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, - LPCSTR name, LPSTR buf, INT buflen); -HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, - INT number, LPSTR buf, INT buflen); -HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, - LPCSTR name, LPSTR buf, INT buflen); -HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr, INT len, - INT type, LPSTR buf, INT buflen); -INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle); -INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent); +INT16 WSACancelBlockingCall(void); +HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 wMsg, + LPCSTR name, LPCSTR proto, + SEGPTR buf, INT16 buflen); + +HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 wMsg, INT16 port, + LPCSTR proto, SEGPTR buf, INT16 buflen); + +HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 wMsg, + LPCSTR name, SEGPTR buf, INT16 buflen); + +HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 wMsg, + INT16 number, SEGPTR buf, INT16 buflen); + +HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 wMsg, + LPCSTR name, SEGPTR buf, INT16 buflen); + +HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 wMsg, LPCSTR addr, INT16 len, + INT16 type, SEGPTR buf, INT16 buflen); + +INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle); +INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, UINT32 lEvent); #ifdef __cplusplus } @@ -267,4 +419,121 @@ typedef struct timeval TIMEVAL, *PTIMEVAL, *LPTIMEVAL; */ #define WSAGETSELECTERROR(lParam) HIWORD(lParam) +/* ----------------------------------- internal structures */ + +#define WS_DUP_NATIVE 0x0 +#define WS_DUP_OFFSET 0x2 +#define WS_DUP_SEGPTR 0x4 + +#define AOP_IO 0x0000001 /* aop_control paramaters */ + +#define AOP_CONTROL_REMOVE 0x0000000 /* aop_control return values */ +#define AOP_CONTROL_KEEP 0x0000001 + +typedef struct __aop +{ + /* AOp header */ + + struct __aop *next, *prev; + int fd[2]; /* pipe */ + int (*aop_control)(struct __aop*, int); /* SIGIO handler */ + pid_t pid; /* child process pid */ + + /* custom data */ + + HWND16 hWnd; + UINT16 uMsg; + + unsigned flags; + SEGPTR buffer_base; + int buflen; + char* init; /* parameter data - length is in the async_ctl */ +} ws_async_op; + +#define WSMSG_ASYNC_SELECT 0x0000001 +#define WSMSG_ASYNC_HOSTBYNAME 0x0000010 +#define WSMSG_ASYNC_HOSTBYADDR 0x0000020 +#define WSMSG_ASYNC_PROTOBYNAME 0x0000100 +#define WSMSG_ASYNC_PROTOBYNUM 0x0000200 +#define WSMSG_ASYNC_SERVBYNAME 0x0001000 +#define WSMSG_ASYNC_SERVBYPORT 0x0002000 + +#define MTYPE_PARENT 0x50505357 +#define MTYPE_CLIENT 0x50435357 + +#pragma pack(1) +typedef struct +{ + long mtype; /* WSMSG_... */ + + UINT32 lParam; + UINT16 wParam; /* socket handle */ +} ipc_packet; + +#define MTYPE_PARENT_SIZE \ + (sizeof(UINT32)) +#define MTYPE_CLIENT_SIZE \ + (sizeof(ipc_packet) - sizeof(long)) +#pragma pack(4) + +typedef struct +{ + int fd; + unsigned flags; + ws_async_op* p_aop; +} ws_socket; + +typedef struct +{ + ws_async_op* ws_aop; /* init'ed for getXbyY */ + ws_socket* ws_sock; /* init'ed for AsyncSelect */ + int lEvent; + int lLength; + char* buffer; + ipc_packet ip; +} ws_async_ctl; + +#define WS_MAX_SOCKETS_PER_THREAD 16 +#define WS_MAX_UDP_DATAGRAM 1024 + +#define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */ + +typedef struct __WSINFO +{ + struct __WSINFO* prev,*next; + + unsigned flags; + int errno; + int num_startup; + int num_async_rq; + int last_free; + ws_socket sock[WS_MAX_SOCKETS_PER_THREAD]; + int buflen; + char* buffer; + FARPROC16 blocking_hook; + HTASK16 tid; /* owning thread id - better switch + * to TLS when it gets fixed */ +} WSINFO, *LPWSINFO; + +int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag); +int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag); +int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag); + +void WS_do_async_gethost(LPWSINFO, unsigned); +void WS_do_async_getproto(LPWSINFO, unsigned); +void WS_do_async_getserv(LPWSINFO, unsigned); + +int WINSOCK_async_io(int fd, int async); +int WINSOCK_unblock_io(int fd, int noblock); + +int WINSOCK_check_async_op(ws_async_op* p_aop); +void WINSOCK_link_async_op(ws_async_op* p_aop); +void WINSOCK_unlink_async_op(ws_async_op* p_aop); +void WINSOCK_cancel_async_op(HTASK16 tid); +void WINSOCK_do_async_select(void); + +UINT16 wsaErrno(void); +UINT16 wsaHerrno(void); + #endif /* _WINSOCKAPI_ */ + diff --git a/library/miscstubs.c b/library/miscstubs.c index 45f8bd73d87..6a7cda14731 100644 --- a/library/miscstubs.c +++ b/library/miscstubs.c @@ -13,6 +13,11 @@ #include "debug.h" #include "xmalloc.h" +void SIGNAL_MaskAsyncEvents( BOOL32 mask ) +{ + /* FIXME: signals don't work in the library */ +} + int CallTo32_LargeStack( int (*func)(), int nbargs, ...) { va_list arglist; @@ -49,7 +54,6 @@ extern LRESULT EditWndProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT FileOpenDlgProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT FileSaveDlgProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT FindTextDlgProc(HWND,UINT,WPARAM16,LPARAM); -extern LRESULT ListBoxWndProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT MDIClientWndProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT PopupMenuWndProc(HWND,UINT,WPARAM16,LPARAM); extern LRESULT PrintDlgProc(HWND,UINT,WPARAM16,LPARAM); @@ -77,7 +81,6 @@ FARPROC16 MODULE_GetWndProcEntry16( char *name ) MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc); MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc); MAP_STR_TO_PROC("FindTextDlgProc",FindTextDlgProc); - MAP_STR_TO_PROC("ListBoxWndProc",ListBoxWndProc); MAP_STR_TO_PROC("MDIClientWndProc",MDIClientWndProc); MAP_STR_TO_PROC("PopupMenuWndProc",PopupMenuWndProc); MAP_STR_TO_PROC("PrintDlgProc",PrintDlgProc); diff --git a/loader/main.c b/loader/main.c index ada29345b87..8cac97659f7 100644 --- a/loader/main.c +++ b/loader/main.c @@ -149,11 +149,11 @@ int MAIN_Init(void) if (!KERN32_Init()) return 0; /* Create system message queue */ - queueSize = GetProfileInt( "windows", "TypeAhead", 120 ); + queueSize = GetProfileInt32A( "windows", "TypeAhead", 120 ); if (!QUEUE_CreateSysMsgQueue( queueSize )) return 0; /* Set double click time */ - SetDoubleClickTime( GetProfileInt( "windows", "DoubleClickSpeed", 452 ) ); + SetDoubleClickTime( GetProfileInt32A("windows","DoubleClickSpeed",452) ); return 1; } diff --git a/loader/module.c b/loader/module.c index 5707003d543..3866137cc8e 100644 --- a/loader/module.c +++ b/loader/module.c @@ -1290,6 +1290,7 @@ INT16 GetModuleFileName( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize ) { NE_MODULE *pModule; + if (!hModule) hModule = GetCurrentTask(); hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ if (!(pModule = MODULE_GetPtr( hModule ))) return 0; lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize ); @@ -1407,7 +1408,8 @@ HINSTANCE16 WinExec( LPSTR lpCmdLine, WORD nCmdShow ) { /* Check that the original file name did not have a suffix */ p = strrchr(filename, '.'); - if (!p || (strchr(p, '/') && strchr(p, '\\'))) + /* if there is a '.', check if either \ OR / follow */ + if (!p || strchr(p, '/') || strchr(p, '\\')) { p = filename + strlen(filename); strcpy( p, ".exe" ); diff --git a/loader/signal.c b/loader/signal.c index 8474223da79..d9238e34f3a 100644 --- a/loader/signal.c +++ b/loader/signal.c @@ -124,14 +124,14 @@ static void SIGNAL_fault(int signal, int code, SIGCONTEXT *context) /********************************************************************** * SIGNAL_SetHandler */ -static void SIGNAL_SetHandler( int sig, void (*func)() ) +static void SIGNAL_SetHandler( int sig, void (*func)(), int flags ) { int ret; struct sigaction sig_act; #ifdef linux sig_act.sa_handler = func; - sig_act.sa_flags = SA_RESTART | SA_NOMASK; + sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0; /* Point to the top of the stack, minus 4 just in case, and make it aligned */ sig_act.sa_restorer = @@ -165,6 +165,7 @@ static void SIGNAL_SetHandler( int sig, void (*func)() ) } extern void stop_wait(int a); +extern void WINSOCK_sigio(int a); /********************************************************************** @@ -204,18 +205,19 @@ BOOL32 SIGNAL_Init(void) } #endif /* __svr4__ || _SCO_DS */ - SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer ); - SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault ); - SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault ); - SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault ); - SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap ); /* debugger */ - SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap ); /* forced break */ + SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1); + SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */ + SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break */ #ifdef SIGBUS - SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault ); + SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1); #endif #ifdef CONFIG_IPC - SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait ); /* For IPC */ + SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */ #endif + SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0); return TRUE; } @@ -239,4 +241,19 @@ void SIGNAL_StartBIOSTimer(void) setitimer(ITIMER_REAL, &vt_timer, NULL); } +/********************************************************************** + * SIGNAL_MaskAsyncEvents + */ +void SIGNAL_MaskAsyncEvents( BOOL32 flag ) +{ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGUSR1); +#ifdef CONFIG_IPC + sigaddset(&set, SIGUSR2); +#endif + sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL); +} + #endif /* ifndef WINELIB */ diff --git a/loader/task.c b/loader/task.c index 97b2ac3f384..d55e252ff16 100644 --- a/loader/task.c +++ b/loader/task.c @@ -67,6 +67,7 @@ static FARPROC16 TASK_RescheduleProc; #endif static HGLOBAL16 TASK_CreateDOSEnvironment(void); +static void TASK_YieldToSystem(TDB*); /*********************************************************************** * TASK_Init @@ -514,7 +515,7 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, /* Get the compatibility flags */ - pTask->compat_flags = GetProfileInt( "Compatibility", name, 0 ); + pTask->compat_flags = GetProfileInt32A( "Compatibility", name, 0 ); /* Allocate a code segment alias for the TDB */ @@ -685,11 +686,22 @@ void TASK_KillCurrentTask( INT16 exitCode ) /* Remove the task from the list to be sure we never switch back to it */ TASK_UnlinkTask( hCurrentTask ); - + if( nTaskCount ) + { + TDB* p = (TDB *)GlobalLock16( hFirstTask ); + while( p ) + { + if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0; + p = (TDB *)GlobalLock16( p->hNext ); + } + } + hTaskToKill = hCurrentTask; hLockedTask = 0; - Yield(); + pTask->nEvents = 0; + TASK_YieldToSystem(pTask); + /* We should never return from this Yield() */ fprintf(stderr,"Return of the living dead %04x!!!\n", hCurrentTask); @@ -753,8 +765,9 @@ void TASK_Reschedule(void) /* check for DirectedYield() */ hTask = pOldTask->hYieldTo; - if (!(pNewTask = (TDB *)GlobalLock16( hTask )) || !pNewTask->nEvents) - hTask = 0; + pNewTask = (TDB *)GlobalLock16( hTask ); + if( !pNewTask || !pNewTask->nEvents) hTask = 0; + pOldTask->hYieldTo = 0; } /* extract hardware events only! */ diff --git a/misc/Makefile.in b/misc/Makefile.in index 32b5cc2ed66..e21b133cb4b 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -38,7 +38,8 @@ C_SRCS = \ user.c \ ver.c \ w32sys.c \ - winsocket.c \ + winsock.c \ + winsock_async.c \ wsprintf.c \ xmalloc.c diff --git a/misc/commdlg.c b/misc/commdlg.c index 80aa834f6fa..fddf5a9791e 100644 --- a/misc/commdlg.c +++ b/misc/commdlg.c @@ -166,22 +166,14 @@ static void FILEDLG_StripEditControl(HWND hwnd) */ static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath) { - BOOL32 ret = FALSE; int len; - char *str = SEGPTR_ALLOC(512); - if (!str) return TRUE; + char str[512]; lstrcpyn32A( str, newPath, 512 ); len = strlen(str); - GetDlgItemText32A( hWnd, edt1, str + len, 512 - len ); - if (DlgDirList(hWnd, SEGPTR_GET(str), lst1, 0, 0x0000)) - { - strcpy( str, "*.*" ); - DlgDirList(hWnd, SEGPTR_GET(str), lst2, stc1, 0x8010 ); - ret = TRUE; - } - SEGPTR_FREE(str); - return ret; + GetDlgItemText32A( hWnd, edt1, str + len, sizeof(str) - len ); + if (!DlgDirList32A( hWnd, str, lst1, 0, 0x0000 )) return FALSE; + return DlgDirList32A( hWnd, "*.*", lst2, stc1, 0x8010 ); } /*********************************************************************** @@ -388,10 +380,7 @@ static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM16 wParam, LPARAM lParam) lpofn->nFilterIndex, tmpstr); SetDlgItemText32A( hWnd, edt1, tmpstr ); /* get drive list */ - pstr = SEGPTR_ALLOC(1); - *pstr = 0; - DlgDirListComboBox16(hWnd, SEGPTR_GET(pstr), cmb2, 0, 0xC000); - SEGPTR_FREE(pstr); + DlgDirListComboBox32A(hWnd, "", cmb2, 0, 0xC000); /* read initial directory */ if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) { diff --git a/misc/crtdll.c b/misc/crtdll.c index e7a8be6b3a9..66b05499247 100644 --- a/misc/crtdll.c +++ b/misc/crtdll.c @@ -615,6 +615,22 @@ VOID* CRTDLL_malloc(DWORD size) return HeapAlloc(GetProcessHeap(),0,size); } +/********************************************************************* + * calloc (CRTDLL.350) + */ +VOID* CRTDLL_calloc(DWORD size, DWORD count) +{ + return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count ); +} + +/********************************************************************* + * realloc (CRTDLL.447) + */ +VOID* CRTDLL_realloc( VOID *ptr, DWORD size ) +{ + return HeapReAlloc( GetProcessHeap(), 0, ptr, size ); +} + /********************************************************************* * free (CRTDLL.427) */ diff --git a/misc/driver.c b/misc/driver.c index e09113b8082..c0a23b0b4af 100644 --- a/misc/driver.c +++ b/misc/driver.c @@ -21,7 +21,7 @@ void LoadStartupDrivers(void) char str[256]; LPSTR ptr; - if (GetPrivateProfileString( "drivers", NULL, "", str, sizeof(str), + if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str), "SYSTEM.INI" ) < 2) { fprintf( stderr, @@ -84,7 +84,7 @@ HDRVR16 OpenDriver(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam) lpDriverName, lpSectionName, lParam ); if (lpSectionName == NULL) lpSectionName = "drivers"; - GetPrivateProfileString( lpSectionName, lpDriverName, "", DrvName, + GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName, sizeof(DrvName), "SYSTEM.INI" ); dprintf_driver( stddeb,"OpenDriver // DrvName='%s'\n", DrvName ); if (lstrlen32A(DrvName) < 1) return 0; diff --git a/misc/keyboard.c b/misc/keyboard.c index 750a645bf01..cf0cbbef4c1 100644 --- a/misc/keyboard.c +++ b/misc/keyboard.c @@ -8,6 +8,7 @@ static char Copyright[] = "Copyright Scott A. Laird, Erik Bos 1993, 1994"; #include #include #include "windows.h" +#include "keyboard.h" #include "stddebug.h" /* #define DEBUG_KEYBOARD */ #include "debug.h" @@ -22,105 +23,110 @@ struct KeyTableEntry { static const struct KeyTableEntry KeyTable[] = { - { 0x3, 0x3, 0x0, "" }, - { 0x8, 0x8, 0xe, "Backspace" }, - { 0x9, 0x9, 0xf, "Tab" }, - { 0xc, 0x0, 0x4c, "Num 5" }, - { 0xd, 0xd, 0x1c, "Enter" }, - { 0x10, 0x0, 0x2a, "Shift" }, - { 0x11, 0x0, 0x1d, "Ctrl" }, - { 0x12, 0x0, 0x38, "Alt" }, - { 0x14, 0x0, 0x3a, "Caps Lock" }, - { 0x1b, 0x1b, 0x1, "Esc" }, - { 0x20, 0x20, 0x39, "Space" }, - { 0x21, 0x0, 0x49, "Num 9" }, - { 0x22, 0x0, 0x51, "Num 3" }, - { 0x23, 0x0, 0x4f, "Num 1" }, - { 0x24, 0x0, 0x47, "Num 7" }, - { 0x25, 0x0, 0x4b, "Num 4" }, - { 0x26, 0x0, 0x48, "Num 8" }, - { 0x27, 0x0, 0x4d, "Num 6" }, - { 0x28, 0x0, 0x50, "Num 2" }, - { 0x2d, 0x0, 0x52, "Num 0" }, - { 0x2e, 0x0, 0x53, "Num Del" }, - { 0x30, 0x30, 0xb, "0" }, - { 0x31, 0x31, 0x2, "1" }, - { 0x32, 0x32, 0x3, "2" }, - { 0x33, 0x33, 0x4, "3" }, - { 0x34, 0x34, 0x5, "4" }, - { 0x35, 0x35, 0x6, "5" }, - { 0x36, 0x36, 0x7, "6" }, - { 0x37, 0x37, 0x8, "7" }, - { 0x38, 0x38, 0x9, "8" }, - { 0x39, 0x39, 0xa, "9" }, - { 0x41, 0x41, 0x1e, "A" }, - { 0x42, 0x42, 0x30, "B" }, - { 0x43, 0x43, 0x2e, "C" }, - { 0x44, 0x44, 0x20, "D" }, - { 0x45, 0x45, 0x12, "E" }, - { 0x46, 0x46, 0x21, "F" }, - { 0x47, 0x47, 0x22, "G" }, - { 0x48, 0x48, 0x23, "H" }, - { 0x49, 0x49, 0x17, "I" }, - { 0x4a, 0x4a, 0x24, "J" }, - { 0x4b, 0x4b, 0x25, "K" }, - { 0x4c, 0x4c, 0x26, "L" }, - { 0x4d, 0x4d, 0x32, "M" }, - { 0x4e, 0x4e, 0x31, "N" }, - { 0x4f, 0x4f, 0x18, "O" }, - { 0x50, 0x50, 0x19, "P" }, - { 0x51, 0x51, 0x10, "Q" }, - { 0x52, 0x52, 0x13, "R" }, - { 0x53, 0x53, 0x1f, "S" }, - { 0x54, 0x54, 0x14, "T" }, - { 0x55, 0x55, 0x16, "U" }, - { 0x56, 0x56, 0x2f, "V" }, - { 0x57, 0x57, 0x11, "W" }, - { 0x58, 0x58, 0x2d, "X" }, - { 0x59, 0x59, 0x15, "Y" }, - { 0x5a, 0x5a, 0x2c, "Z" }, - { 0x60, 0x0, 0x52, "Num 0" }, - { 0x61, 0x0, 0x4f, "Num 1" }, - { 0x62, 0x0, 0x50, "Num 2" }, - { 0x63, 0x0, 0x51, "Num 3" }, - { 0x64, 0x0, 0x4b, "Num 4" }, - { 0x65, 0x0, 0x4c, "Num 5" }, - { 0x66, 0x0, 0x4d, "Num 6" }, - { 0x67, 0x0, 0x47, "Num 7" }, - { 0x68, 0x0, 0x48, "Num 8" }, - { 0x69, 0x0, 0x49, "Num 9" }, - { 0x6a, 0x2a, 0x37, "Num *" }, - { 0x6b, 0x2b, 0x4e, "Num +" }, - { 0x6c, 0x0, 0x0, "" }, - { 0x6d, 0x2d, 0x4a, "Num -" }, - { 0x6e, 0x2e, 0x53, "Num Del" }, - { 0x6f, 0x2f, 0x0, "" }, - { 0x70, 0x0, 0x3b, "F1" }, - { 0x71, 0x0, 0x3c, "F2" }, - { 0x72, 0x0, 0x3d, "F3" }, - { 0x73, 0x0, 0x3e, "F4" }, - { 0x74, 0x0, 0x3f, "F5" }, - { 0x75, 0x0, 0x40, "F6" }, - { 0x76, 0x0, 0x41, "F7" }, - { 0x77, 0x0, 0x42, "F8" }, - { 0x78, 0x0, 0x43, "F9" }, - { 0x79, 0x0, 0x44, "F10" }, - { 0x7a, 0x0, 0x57, "F11" }, - { 0x7b, 0x0, 0x58, "F12" }, - { 0x90, 0x0, 0x45, "Pause" }, - { 0x91, 0x0, 0x46, "Scroll Lock" }, - { 0xba, 0x3b, 0x27, ";" }, - { 0xbb, 0x3d, 0xd, "=" }, - { 0xbc, 0x2c, 0x33, "," }, - { 0xbd, 0x2d, 0xc, "-" }, - { 0xbe, 0x2e, 0x34, "." }, - { 0xbf, 0x2f, 0x35, "/" }, - { 0xc0, 0x60, 0x29, "`" }, - { 0xdb, 0x5b, 0x1a, "[" }, - { 0xdc, 0x5c, 0x2b, "\\" }, - { 0xdd, 0x5d, 0x1b, "]" }, - { 0xde, 0x27, 0x28, "\'" }, - { 0xe2, 0x5c, 0x56, "\\" }, + { VK_CANCEL, 0x3, 0, "" }, + { VK_BACK, 0x8, 0xe, "Backspace" }, + { VK_TAB, 0x9, 0xf, "Tab" }, + { VK_CLEAR, 0, 0x4c, "Clear" }, + { VK_RETURN, 0xd, 0x1c, "Enter" }, + { VK_SHIFT, 0, 0x2a, "Shift" }, + { VK_CONTROL, 0, 0x1d, "Ctrl" }, + { VK_MENU, 0, 0x38, "Alt" }, + { VK_CAPITAL, 0, 0x3a, "Caps Lock" }, + { VK_ESCAPE, 0x1b, 0x1, "Esc" }, + { VK_SPACE, 0x20, 0x39, "Space" }, + { VK_PRIOR, 0, 0x49, "Page Up" }, + { VK_NEXT, 0, 0x51, "Page Down" }, + { VK_END, 0, 0x4f, "End" }, + { VK_HOME, 0, 0x47, "Home" }, + { VK_LEFT, 0, 0x4b, "Left Arrow" }, + { VK_UP, 0, 0x48, "Up Arrow" }, + { VK_RIGHT, 0, 0x4d, "Right Arrow" }, + { VK_DOWN, 0, 0x50, "Down Arrow" }, + { VK_INSERT, 0, 0x52, "Ins" }, + { VK_DELETE, 0, 0x53, "Del" }, + { VK_0, 0x30, 0xb, "0" }, + { VK_1, 0x31, 0x2, "1" }, + { VK_2, 0x32, 0x3, "2" }, + { VK_3, 0x33, 0x4, "3" }, + { VK_4, 0x34, 0x5, "4" }, + { VK_5, 0x35, 0x6, "5" }, + { VK_6, 0x36, 0x7, "6" }, + { VK_7, 0x37, 0x8, "7" }, + { VK_8, 0x38, 0x9, "8" }, + { VK_9, 0x39, 0xa, "9" }, + { VK_A, 0x41, 0x1e, "A" }, + { VK_B, 0x42, 0x30, "B" }, + { VK_C, 0x43, 0x2e, "C" }, + { VK_D, 0x44, 0x20, "D" }, + { VK_E, 0x45, 0x12, "E" }, + { VK_F, 0x46, 0x21, "F" }, + { VK_G, 0x47, 0x22, "G" }, + { VK_H, 0x48, 0x23, "H" }, + { VK_I, 0x49, 0x17, "I" }, + { VK_J, 0x4a, 0x24, "J" }, + { VK_K, 0x4b, 0x25, "K" }, + { VK_L, 0x4c, 0x26, "L" }, + { VK_M, 0x4d, 0x32, "M" }, + { VK_N, 0x4e, 0x31, "N" }, + { VK_O, 0x4f, 0x18, "O" }, + { VK_P, 0x50, 0x19, "P" }, + { VK_Q, 0x51, 0x10, "Q" }, + { VK_R, 0x52, 0x13, "R" }, + { VK_S, 0x53, 0x1f, "S" }, + { VK_T, 0x54, 0x14, "T" }, + { VK_U, 0x55, 0x16, "U" }, + { VK_V, 0x56, 0x2f, "V" }, + { VK_W, 0x57, 0x11, "W" }, + { VK_X, 0x58, 0x2d, "X" }, + { VK_Y, 0x59, 0x15, "Y" }, + { VK_Z, 0x5a, 0x2c, "Z" }, + { VK_NUMPAD0, 0, 0x52, "Num 0" }, + { VK_NUMPAD1, 0, 0x4f, "Num 1" }, + { VK_NUMPAD2, 0, 0x50, "Num 2" }, + { VK_NUMPAD3, 0, 0x51, "Num 3" }, + { VK_NUMPAD4, 0, 0x4b, "Num 4" }, + { VK_NUMPAD5, 0, 0x4c, "Num 5" }, + { VK_NUMPAD6, 0, 0x4d, "Num 6" }, + { VK_NUMPAD7, 0, 0x47, "Num 7" }, + { VK_NUMPAD8, 0, 0x48, "Num 8" }, + { VK_NUMPAD9, 0, 0x49, "Num 9" }, + { VK_MULTIPLY, 0x2a, 0x37, "Num *" }, + { VK_ADD, 0x2b, 0x4e, "Num +" }, + { VK_SEPARATOR, 0, 0, "" }, + { VK_SUBTRACT, 0x2d, 0x4a, "Num -" }, + { VK_DECIMAL, 0x2e, 0x53, "Num Del" }, + { VK_DIVIDE, 0x2f, 0, "Num /" }, + { VK_F1, 0, 0x3b, "F1" }, + { VK_F2, 0, 0x3c, "F2" }, + { VK_F3, 0, 0x3d, "F3" }, + { VK_F4, 0, 0x3e, "F4" }, + { VK_F5, 0, 0x3f, "F5" }, + { VK_F6, 0, 0x40, "F6" }, + { VK_F7, 0, 0x41, "F7" }, + { VK_F8, 0, 0x42, "F8" }, + { VK_F9, 0, 0x43, "F9" }, + { VK_F10, 0, 0x44, "F10" }, + { VK_F11, 0, 0x57, "F11" }, + { VK_F12, 0, 0x58, "F12" }, + { VK_NUMLOCK, 0, 0x45, "Num Lock" }, + { VK_SCROLL, 0, 0x46, "Scroll Lock" }, + /* Allowable ranges for OEM-specific virtual-key codes */ +/* - 0xBA-0xC0 OEM specific */ + { 0xba, 0x3b, 0x27, ";" }, + { 0xbb, 0x3d, 0xd, "=" }, + { 0xbc, 0x2c, 0x33, "," }, + { 0xbd, 0x2d, 0xc, "-" }, + { 0xbe, 0x2e, 0x34, "." }, + { 0xbf, 0x2f, 0x35, "/" }, + { 0xc0, 0x60, 0x29, "`" }, +/* - 0xDB-0xE4 OEM specific */ + { 0xdb, 0x5b, 0x1a, "[" }, + { 0xdc, 0x5c, 0x2b, "\\" }, + { 0xdd, 0x5d, 0x1b, "]" }, + { 0xde, 0x27, 0x28, "'" }, + { 0xe2, 0x5c, 0x56, "\\" }, +/* - 0xE6 OEM specific */ +/* - 0xE9-0xF5 OEM specific */ }; #define KeyTableSize sizeof(KeyTable) / sizeof(struct KeyTableEntry) @@ -128,34 +134,55 @@ static const struct KeyTableEntry KeyTable[] = int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, LPVOID lpChar, WORD wFlags) { + char shift = lpKeyState[VK_SHIFT] < 0; int i; - dprintf_keyboard(stddeb,"ToAscii (%d,%d)\n",wVirtKey, wScanCode); + dprintf_keyboard(stddeb, "ToAscii (%x,%x) -> ", wVirtKey, wScanCode); /* FIXME: codepage is broken */ - for (i = 0 ; i != KeyTableSize ; i++) - if (KeyTable[i].virtualkey == wVirtKey) - { - dprintf_keyboard(stddeb,"\t\tchar = %s\n", KeyTable[i].name); - if( isprint(KeyTable[i].ASCII) || isspace(KeyTable[i].ASCII) ) - { - *(BYTE*)lpChar = KeyTable[i].ASCII; - *(((BYTE*)lpChar) + 1) = 0; - - if( isalpha( *(BYTE*)lpChar ) ) - if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) || - (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) ) - *(BYTE*)lpChar = toupper( *(BYTE*)lpChar ); - else - *(BYTE*)lpChar = tolower( *(BYTE*)lpChar ); - - return 1; - } - } - *(BYTE*)lpChar = 0; - return 0; + switch (wVirtKey) + { +#define vkcase2(k1,k2,val) case val : *(BYTE*)lpChar = shift ? k2 : k1; break; +#define vkcase(k, val) vkcase2(val, k, val) + WINE_VKEY_MAPPINGS +#undef vkcase +#undef vkcase2 + default : + for (i = 0 ; ; i++) + { + if (i == KeyTableSize) + { + dprintf_keyboard(stddeb, "0\n"); + return 0; + } + if (KeyTable[i].virtualkey == wVirtKey) + { + if (!isprint(KeyTable[i].ASCII) && !isspace(KeyTable[i].ASCII)) + { + dprintf_keyboard(stddeb, "0\n"); + return 0; + } + dprintf_keyboard(stddeb,"\"%s\" ", KeyTable[i].name); + + *(BYTE*)lpChar = KeyTable[i].ASCII; + *(((BYTE*)lpChar) + 1) = 0; + + if (isalpha(*(BYTE*)lpChar)) + if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) || + (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) ) + *(BYTE*)lpChar = toupper( *(BYTE*)lpChar ); + else + *(BYTE*)lpChar = tolower( *(BYTE*)lpChar ); + break; + } + } + } + if (lpKeyState[VK_CONTROL] < 0) + *(BYTE*)lpChar = *(BYTE*)lpChar & 0x1f; + dprintf_keyboard(stddeb, "1 (%x)\n", *(BYTE*)lpChar); + return 1; } DWORD OemKeyScan(WORD wOemChar) @@ -166,7 +193,16 @@ DWORD OemKeyScan(WORD wOemChar) } /* VkKeyScan translates an ANSI character to a virtual-key and shift code - * for the current keyboard. */ + * for the current keyboard. + * FIXME high-order byte should yield : + * 0 Unshifted + * 1 Shift + * 2 Ctrl + * 3-5 Shift-key combinations that are not used for characters + * 6 Ctrl-Alt + * 7 Ctrl-Alt-Shift + * I.e. : Shift = 1, Ctrl = 2, Alt = 4. + */ WORD VkKeyScan(WORD cChar) { @@ -208,26 +244,28 @@ WORD MapVirtualKey(WORD wCode, WORD wMapType) int i; switch(wMapType) { - case 0: + case 0: /* vkey-code to scan-code */ for (i = 0 ; i != KeyTableSize ; i++) if (KeyTable[i].virtualkey == wCode) return KeyTable[i].scancode; return 0; - case 1: + case 1: /* scan-code to vkey-code */ for (i = 0 ; i != KeyTableSize ; i++) if (KeyTable[i].scancode == wCode) return KeyTable[i].virtualkey; return 0; - case 2: + case 2: /* vkey-code to unshifted ANSI code */ + /* FIXME : what does unshifted mean ? 'a' or 'A' ? */ for (i = 0 ; i != KeyTableSize ; i++) if (KeyTable[i].virtualkey == wCode) return KeyTable[i].ASCII; return 0; - default: - fprintf(stderr, "MapVirtualKey: unknown wMapType!\n"); + default: /* reserved */ + fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n", + wMapType); return 0; } return 0; diff --git a/misc/main.c b/misc/main.c index b9113a764b8..f8597ec1604 100644 --- a/misc/main.c +++ b/misc/main.c @@ -804,7 +804,8 @@ LONG GetWinFlags(void) fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n"); break; } - + if( getVersionEx.dwPlatformId == VER_PLATFORM_WIN32_NT ) + result |= 0x4000; /* undocumented WF_WINNT */ return result; } @@ -1076,18 +1077,21 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi break; case SPI_GETFASTTASKSWITCH: - *(BOOL *) lpvParam = FALSE; - /* FIXME GetProfileInt( "windows", "CoolSwitch", 1 ) */ + if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 ) + *(BOOL *) lpvParam = TRUE; + else + *(BOOL *) lpvParam = FALSE; break; case SPI_GETGRIDGRANULARITY: - *(INT *) lpvParam = 1; - /* FIXME GetProfileInt( "desktop", "GridGranularity", 1 ) */ - break; + *(INT *) lpvParam = GetProfileInt32A( "desktop", + "GridGranularity", + 1 ); + break; case SPI_GETICONTITLEWRAP: *(BOOL *) lpvParam = FALSE; - /* FIXME GetProfileInt( "desktop", "?", True ) */ + /* FIXME GetProfileInt32A( "desktop", "?", True ) */ break; case SPI_GETKEYBOARDDELAY: @@ -1105,9 +1109,11 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi break; case SPI_GETSCREENSAVEACTIVE: - /* FIXME GetProfileInt( "windows", "ScreenSaveActive", 1 ); */ - *(BOOL *) lpvParam = FALSE; - break; + if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 ) + *(BOOL *) lpvParam = TRUE; + else + *(BOOL *) lpvParam = FALSE; + break; case SPI_GETSCREENSAVETIMEOUT: /* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */ @@ -1116,18 +1122,20 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi break; case SPI_ICONHORIZONTALSPACING: + /* FIXME Get/SetProfileInt */ if (lpvParam == NULL) - fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam); - else - *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING ); + /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ; + else + *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING ); break; case SPI_ICONVERTICALSPACING: - if (lpvParam == NULL) - fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam); - else - *(INT *) lpvParam = GetSystemMetrics( SM_CYICONSPACING ); - break; + /* FIXME Get/SetProfileInt */ + if (lpvParam == NULL) + /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ; + else + *(INT *) lpvParam = GetSystemMetrics(SM_CYICONSPACING); + break; case SPI_SETBEEP: if (uParam == TRUE) @@ -1147,7 +1155,7 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi case SPI_SETSCREENSAVETIMEOUT: XSetScreenSaver(display, uParam, 60, DefaultBlanking, - DefaultExposures); + DefaultExposures); break; case SPI_SETDESKWALLPAPER: @@ -1156,7 +1164,7 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi case SPI_SETDESKPATTERN: if ((INT) uParam == -1) { - GetProfileString("Desktop", "Pattern", + GetProfileString32A("Desktop", "Pattern", "170 85 170 85 170 85 170 85", buffer, sizeof(buffer) ); return (DESKTOP_SetPattern((LPSTR) buffer)); @@ -1166,19 +1174,20 @@ BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWi case SPI_GETICONTITLELOGFONT: { - /* FIXME GetProfileString( "?", "?", "?" ) */ - LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam; - lpLogFont->lfHeight = 10; - lpLogFont->lfWidth = 0; - lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0; - lpLogFont->lfWeight = FW_NORMAL; - lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE; - lpLogFont->lfCharSet = ANSI_CHARSET; - lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS; - lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS; - lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS; - break; - } + /* FIXME GetProfileString32A( "?", "?", "?" ) */ + LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam; + lpLogFont->lfHeight = 10; + lpLogFont->lfWidth = 0; + lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0; + lpLogFont->lfWeight = FW_NORMAL; + lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE; + lpLogFont->lfCharSet = ANSI_CHARSET; + lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS; + lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS; + break; + } + case SPI_LANGDRIVER: case SPI_SETBORDER: case SPI_SETDOUBLECLKHEIGHT: diff --git a/misc/ole2nls.c b/misc/ole2nls.c index 66a7a741cff..8669f500b33 100644 --- a/misc/ole2nls.c +++ b/misc/ole2nls.c @@ -4,16 +4,126 @@ * Copyright 1995 Martin von Loewis */ -/* At the moment, these are only empty stubs. - */ - #include +#include #include "windows.h" #include "ole.h" #include "options.h" #include "winnls.h" #include "stddebug.h" #include "debug.h" +#include "string32.h" + +/* Locale name to id map. used by EnumSystemLocales, GetLocalInfoA + * MUST contain all #defines from winnls.h + * last entry has NULL name, 0 id. + */ +#define LOCALE_ENTRY(x) {#x,LOCALE_##x} +static struct tagLOCALE_NAME2ID { + char *name; + DWORD id; +} locale_name2id[]= { + LOCALE_ENTRY(ILANGUAGE), + LOCALE_ENTRY(SLANGUAGE), + LOCALE_ENTRY(SENGLANGUAGE), + LOCALE_ENTRY(SABBREVLANGNAME), + LOCALE_ENTRY(SNATIVELANGNAME), + LOCALE_ENTRY(ICOUNTRY), + LOCALE_ENTRY(SCOUNTRY), + LOCALE_ENTRY(SENGCOUNTRY), + LOCALE_ENTRY(SABBREVCTRYNAME), + LOCALE_ENTRY(SNATIVECTRYNAME), + LOCALE_ENTRY(IDEFAULTLANGUAGE), + LOCALE_ENTRY(IDEFAULTCOUNTRY), + LOCALE_ENTRY(IDEFAULTCODEPAGE), + LOCALE_ENTRY(IDEFAULTANSICODEPAGE), + LOCALE_ENTRY(SLIST), + LOCALE_ENTRY(IMEASURE), + LOCALE_ENTRY(SDECIMAL), + LOCALE_ENTRY(STHOUSAND), + LOCALE_ENTRY(SGROUPING), + LOCALE_ENTRY(IDIGITS), + LOCALE_ENTRY(ILZERO), + LOCALE_ENTRY(INEGNUMBER), + LOCALE_ENTRY(SNATIVEDIGITS), + LOCALE_ENTRY(SCURRENCY), + LOCALE_ENTRY(SINTLSYMBOL), + LOCALE_ENTRY(SMONDECIMALSEP), + LOCALE_ENTRY(SMONTHOUSANDSEP), + LOCALE_ENTRY(SMONGROUPING), + LOCALE_ENTRY(ICURRDIGITS), + LOCALE_ENTRY(IINTLCURRDIGITS), + LOCALE_ENTRY(ICURRENCY), + LOCALE_ENTRY(INEGCURR), + LOCALE_ENTRY(SDATE), + LOCALE_ENTRY(STIME), + LOCALE_ENTRY(SSHORTDATE), + LOCALE_ENTRY(SLONGDATE), + LOCALE_ENTRY(STIMEFORMAT), + LOCALE_ENTRY(IDATE), + LOCALE_ENTRY(ILDATE), + LOCALE_ENTRY(ITIME), + LOCALE_ENTRY(ITIMEMARKPOSN), + LOCALE_ENTRY(ICENTURY), + LOCALE_ENTRY(ITLZERO), + LOCALE_ENTRY(IDAYLZERO), + LOCALE_ENTRY(IMONLZERO), + LOCALE_ENTRY(S1159), + LOCALE_ENTRY(S2359), + LOCALE_ENTRY(ICALENDARTYPE), + LOCALE_ENTRY(IOPTIONALCALENDAR), + LOCALE_ENTRY(IFIRSTDAYOFWEEK), + LOCALE_ENTRY(IFIRSTWEEKOFYEAR), + LOCALE_ENTRY(SDAYNAME1), + LOCALE_ENTRY(SDAYNAME2), + LOCALE_ENTRY(SDAYNAME3), + LOCALE_ENTRY(SDAYNAME4), + LOCALE_ENTRY(SDAYNAME5), + LOCALE_ENTRY(SDAYNAME6), + LOCALE_ENTRY(SDAYNAME7), + LOCALE_ENTRY(SABBREVDAYNAME1), + LOCALE_ENTRY(SABBREVDAYNAME2), + LOCALE_ENTRY(SABBREVDAYNAME3), + LOCALE_ENTRY(SABBREVDAYNAME4), + LOCALE_ENTRY(SABBREVDAYNAME5), + LOCALE_ENTRY(SABBREVDAYNAME6), + LOCALE_ENTRY(SABBREVDAYNAME7), + LOCALE_ENTRY(SMONTHNAME1), + LOCALE_ENTRY(SMONTHNAME2), + LOCALE_ENTRY(SMONTHNAME3), + LOCALE_ENTRY(SMONTHNAME4), + LOCALE_ENTRY(SMONTHNAME5), + LOCALE_ENTRY(SMONTHNAME6), + LOCALE_ENTRY(SMONTHNAME7), + LOCALE_ENTRY(SMONTHNAME8), + LOCALE_ENTRY(SMONTHNAME9), + LOCALE_ENTRY(SMONTHNAME10), + LOCALE_ENTRY(SMONTHNAME11), + LOCALE_ENTRY(SMONTHNAME12), + LOCALE_ENTRY(SMONTHNAME13), + LOCALE_ENTRY(SABBREVMONTHNAME1), + LOCALE_ENTRY(SABBREVMONTHNAME2), + LOCALE_ENTRY(SABBREVMONTHNAME3), + LOCALE_ENTRY(SABBREVMONTHNAME4), + LOCALE_ENTRY(SABBREVMONTHNAME5), + LOCALE_ENTRY(SABBREVMONTHNAME6), + LOCALE_ENTRY(SABBREVMONTHNAME7), + LOCALE_ENTRY(SABBREVMONTHNAME8), + LOCALE_ENTRY(SABBREVMONTHNAME9), + LOCALE_ENTRY(SABBREVMONTHNAME10), + LOCALE_ENTRY(SABBREVMONTHNAME11), + LOCALE_ENTRY(SABBREVMONTHNAME12), + LOCALE_ENTRY(SABBREVMONTHNAME13), + LOCALE_ENTRY(SPOSITIVESIGN), + LOCALE_ENTRY(SNEGATIVESIGN), + LOCALE_ENTRY(IPOSSIGNPOSN), + LOCALE_ENTRY(INEGSIGNPOSN), + LOCALE_ENTRY(IPOSSYMPRECEDES), + LOCALE_ENTRY(IPOSSEPBYSPACE), + LOCALE_ENTRY(INEGSYMPRECEDES), + LOCALE_ENTRY(INEGSEPBYSPACE), + {NULL,0}, +}; /*********************************************************************** * GetUserDefaultLCID (OLE2NLS.1) @@ -86,137 +196,39 @@ WORD GetSystemDefaultLangID() */ int GetLocaleInfoA(DWORD lcid,DWORD LCType,LPSTR buf,WORD len) { - char *retString; - int retLen; - dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n", + char *retString; + int found,i; + + dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n", lcid,LCType,buf,len); -#if 0 - /* Wine is supporting only the default locale */ - if(lcid!=GetUserDefaultLCID()) - { - dprintf_ole(stdnimp,"GetLocaleInfoA: Unknown locale\n"); - return 0; - } -#endif /* As an option, we could obtain the value from win.ini. This would not match the Wine compile-time option. Also, not all identifiers are available from win.ini */ retString=0; - retLen=0; /* If we are through all of this, retLen should not be zero anymore. If it is, the value is not supported */ -#define LOCVAL(type,value) if(type==LCType) \ - {retLen=strlen(value)+1;\ - retString=value; \ - } -#define UNSUPPORTED(type) if(type==lcid)retString=#type; + i=0; + while (locale_name2id[i].name!=NULL) { + if (LCType == locale_name2id[i].id) { + retString = locale_name2id[i].name; + break; + } + i++; + } + if (!retString) { + fprintf(stderr,"Unkown LC type %lX\n",LCType); + return 0; + } -/* I really wish I would know a better way to do this */ -UNSUPPORTED(LOCALE_ILANGUAGE) -UNSUPPORTED(LOCALE_SLANGUAGE) -UNSUPPORTED(LOCALE_SENGLANGUAGE) -UNSUPPORTED(LOCALE_SABBREVLANGNAME) -UNSUPPORTED(LOCALE_SNATIVELANGNAME) -UNSUPPORTED(LOCALE_ICOUNTRY) -UNSUPPORTED(LOCALE_SCOUNTRY) -UNSUPPORTED(LOCALE_SENGCOUNTRY) -UNSUPPORTED(LOCALE_SABBREVCTRYNAME) -UNSUPPORTED(LOCALE_SNATIVECTRYNAME) -UNSUPPORTED(LOCALE_IDEFAULTLANGUAGE) -UNSUPPORTED(LOCALE_IDEFAULTCOUNTRY) -UNSUPPORTED(LOCALE_IDEFAULTCODEPAGE) -UNSUPPORTED(LOCALE_IDEFAULTANSICODEPAGE) -UNSUPPORTED(LOCALE_SLIST) -UNSUPPORTED(LOCALE_IMEASURE) -UNSUPPORTED(LOCALE_SDECIMAL) -UNSUPPORTED(LOCALE_STHOUSAND) -UNSUPPORTED(LOCALE_SGROUPING) -UNSUPPORTED(LOCALE_IDIGITS) -UNSUPPORTED(LOCALE_ILZERO) -UNSUPPORTED(LOCALE_INEGNUMBER) -UNSUPPORTED(LOCALE_SNATIVEDIGITS) -UNSUPPORTED(LOCALE_SCURRENCY) -UNSUPPORTED(LOCALE_SINTLSYMBOL) -UNSUPPORTED(LOCALE_SMONDECIMALSEP) -UNSUPPORTED(LOCALE_SMONTHOUSANDSEP) -UNSUPPORTED(LOCALE_SMONGROUPING) -UNSUPPORTED(LOCALE_ICURRDIGITS) -UNSUPPORTED(LOCALE_IINTLCURRDIGITS) -UNSUPPORTED(LOCALE_ICURRENCY) -UNSUPPORTED(LOCALE_INEGCURR) -UNSUPPORTED(LOCALE_SDATE) -UNSUPPORTED(LOCALE_STIME) -UNSUPPORTED(LOCALE_SSHORTDATE) -UNSUPPORTED(LOCALE_SLONGDATE) -UNSUPPORTED(LOCALE_STIMEFORMAT) -UNSUPPORTED(LOCALE_IDATE) -UNSUPPORTED(LOCALE_ILDATE) -UNSUPPORTED(LOCALE_ITIME) -UNSUPPORTED(LOCALE_ITIMEMARKPOSN) -UNSUPPORTED(LOCALE_ICENTURY) -UNSUPPORTED(LOCALE_ITLZERO) -UNSUPPORTED(LOCALE_IDAYLZERO) -UNSUPPORTED(LOCALE_IMONLZERO) -UNSUPPORTED(LOCALE_S1159) -UNSUPPORTED(LOCALE_S2359) -UNSUPPORTED(LOCALE_ICALENDARTYPE) -UNSUPPORTED(LOCALE_IOPTIONALCALENDAR) -UNSUPPORTED(LOCALE_IFIRSTDAYOFWEEK) -UNSUPPORTED(LOCALE_IFIRSTWEEKOFYEAR) -UNSUPPORTED(LOCALE_SDAYNAME1) -UNSUPPORTED(LOCALE_SDAYNAME2) -UNSUPPORTED(LOCALE_SDAYNAME3) -UNSUPPORTED(LOCALE_SDAYNAME4) -UNSUPPORTED(LOCALE_SDAYNAME5) -UNSUPPORTED(LOCALE_SDAYNAME6) -UNSUPPORTED(LOCALE_SDAYNAME7) -UNSUPPORTED(LOCALE_SABBREVDAYNAME1) -UNSUPPORTED(LOCALE_SABBREVDAYNAME2) -UNSUPPORTED(LOCALE_SABBREVDAYNAME3) -UNSUPPORTED(LOCALE_SABBREVDAYNAME4) -UNSUPPORTED(LOCALE_SABBREVDAYNAME5) -UNSUPPORTED(LOCALE_SABBREVDAYNAME6) -UNSUPPORTED(LOCALE_SABBREVDAYNAME7) -UNSUPPORTED(LOCALE_SMONTHNAME1) -UNSUPPORTED(LOCALE_SMONTHNAME2) -UNSUPPORTED(LOCALE_SMONTHNAME3) -UNSUPPORTED(LOCALE_SMONTHNAME4) -UNSUPPORTED(LOCALE_SMONTHNAME5) -UNSUPPORTED(LOCALE_SMONTHNAME6) -UNSUPPORTED(LOCALE_SMONTHNAME7) -UNSUPPORTED(LOCALE_SMONTHNAME8) -UNSUPPORTED(LOCALE_SMONTHNAME9) -UNSUPPORTED(LOCALE_SMONTHNAME10) -UNSUPPORTED(LOCALE_SMONTHNAME11) -UNSUPPORTED(LOCALE_SMONTHNAME12) -UNSUPPORTED(LOCALE_SMONTHNAME13) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME1) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME2) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME3) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME4) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME5) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME6) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME7) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME8) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME9) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME10) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME11) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME12) -UNSUPPORTED(LOCALE_SABBREVMONTHNAME13) -UNSUPPORTED(LOCALE_SPOSITIVESIGN) -UNSUPPORTED(LOCALE_SNEGATIVESIGN) -UNSUPPORTED(LOCALE_IPOSSIGNPOSN) -UNSUPPORTED(LOCALE_INEGSIGNPOSN) -UNSUPPORTED(LOCALE_IPOSSYMPRECEDES) -UNSUPPORTED(LOCALE_IPOSSEPBYSPACE) -UNSUPPORTED(LOCALE_INEGSYMPRECEDES) -UNSUPPORTED(LOCALE_INEGSEPBYSPACE) +#define LOCVAL(type,value) case type:retString=value;break; /* Now, the language specific definitions. They don't have to be complete */ + found=1; switch(Options.language) { case LANG_De: + switch (LCType) { /* This definitions apply to Germany only. Users in Austria or Switzerland might want to modify them */ LOCVAL(LOCALE_ILANGUAGE,"9") @@ -339,9 +351,12 @@ LOCVAL(LOCALE_IPOSSEPBYSPACE) LOCVAL(LOCALE_INEGSYMPRECEDES) LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(De) */ case LANG_Da: + switch (LCType) { /* LOCVAL(LOCALE_ILANGUAGE,"9") */ LOCVAL(LOCALE_SLANGUAGE,"Dansk") LOCVAL(LOCALE_SENGLANGUAGE,"Danish") @@ -441,9 +456,12 @@ LOCVAL(LOCALE_SABBREVMONTHNAME13,"") /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ /* LOCVAL(LOCALE_INEGSYMPRECEDES) */ /* LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(Da) */ case LANG_En: + switch (LCType) { /* This definitions apply to Germany only. Users in Austria or Switzerland might want to modify them */ LOCVAL(LOCALE_ILANGUAGE,"9") @@ -566,9 +584,12 @@ LOCVAL(LOCALE_IPOSSEPBYSPACE) LOCVAL(LOCALE_INEGSYMPRECEDES) LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(En) */ case LANG_Eo: + switch (LCType) { /* LOCVAL(LOCALE_ILANGUAGE,"9") ISO numerical ID for language TODO */ LOCVAL(LOCALE_SLANGUAGE,"Esperanto") LOCVAL(LOCALE_SENGLANGUAGE,"Esperanto") @@ -668,9 +689,12 @@ LOCVAL(LOCALE_SABBREVMONTHNAME13,"") /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ /* LOCVAL(LOCALE_INEGSYMPRECEDES) */ /* LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(Eo) */ case LANG_Fi: + switch (LCType) { LOCVAL(LOCALE_ILANGUAGE,"11") LOCVAL(LOCALE_SLANGUAGE,"Suomi") LOCVAL(LOCALE_SENGLANGUAGE,"Finnish") @@ -791,9 +815,12 @@ LOCVAL(LOCALE_IPOSSEPBYSPACE) LOCVAL(LOCALE_INEGSYMPRECEDES) LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(Fi) */ case LANG_It: + switch (LCType) { LOCVAL(LOCALE_ILANGUAGE,"9") LOCVAL(LOCALE_SLANGUAGE,"Italiano") LOCVAL(LOCALE_SENGLANGUAGE,"Italian") @@ -914,9 +941,12 @@ LOCVAL(LOCALE_IPOSSEPBYSPACE) LOCVAL(LOCALE_INEGSYMPRECEDES) LOCVAL(LOCALE_INEGSEPBYSPACE) */ + default: found=0;break; + } break; /* LANG(It) */ case 0x0409: + switch (LCType) { LOCVAL(LOCALE_ILANGUAGE, "0409") LOCVAL(LOCALE_SLANGUAGE, "English (United States)") LOCVAL(LOCALE_SENGLANGUAGE, "English") @@ -1016,9 +1046,12 @@ LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") LOCVAL(LOCALE_INEGSYMPRECEDES, "1") LOCVAL(LOCALE_INEGSEPBYSPACE, "0") + default: found=0;break; + } break; /* LANG(0x0409) (U.S. English) */ case 0x0809: + switch (LCType) { LOCVAL(LOCALE_ILANGUAGE, "0809") LOCVAL(LOCALE_SLANGUAGE, "English (United Kingdom)") LOCVAL(LOCALE_SENGLANGUAGE, "English") @@ -1118,25 +1151,24 @@ LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") LOCVAL(LOCALE_INEGSYMPRECEDES, "1") LOCVAL(LOCALE_INEGSEPBYSPACE, "0") + default: found=0;break; + } break; /* LANG(0x0809) (U.K. English) */ /*Insert other languages here*/ default: + found=0; break; } /* switch */ - if(!retLen) - { - if(!retString)fprintf(stderr,"Unkown LC type %lX\n",LCType); - else fprintf(stderr,"'%s' not supported for your language.\n", + if(!found) { + fprintf(stderr,"'%s' not supported for your language.\n", retString); return 0; } - - if(retLen>len)retLen=len; lstrcpyn32A(buf,retString,len); - return retLen; + return strlen(retString)+1; } /*********************************************************************** @@ -1230,7 +1262,57 @@ BOOL SetLocaleInfoA(DWORD lcid, DWORD lctype, LPCSTR data) { return TRUE; } -BOOL IsValidLocale(DWORD lcid,DWORD flags) { - fprintf(stdnimp,"IsValidLocale(%ld,%ld)\n",lcid,flags); +/*********************************************************************** + * IsValidLocale (KERNEL32.361) + */ +BOOL32 IsValidLocale(DWORD lcid,DWORD flags) { + int i; + + i=0; + while (locale_name2id[i].name!=NULL) + if (locale_name2id[i].id == lcid) + return TRUE; + return FALSE; +} + +/*********************************************************************** + * EnumSystemLocales32W (KERNEL32.93) + */ +BOOL32 +EnumSystemLocales32W(LOCALE_ENUMPROC32W lpfnLocaleEnum,DWORD flags) { + WCHAR *cp; + int i; + BOOL32 ret; + + dprintf_win32(stddeb,"EnumSystemLocales32W(%p,%08lx)\n", + lpfnLocaleEnum,flags + ); + i=0; + while (locale_name2id[i].name!=NULL) { + cp=(LPWSTR)STRING32_DupAnsiToUni(locale_name2id[i].name); + ret=lpfnLocaleEnum(cp); + free(cp); + if (!ret) break; + i++; + } + return TRUE; +} + +/*********************************************************************** + * EnumSystemLocales32A (KERNEL32.92) + */ +BOOL32 +EnumSystemLocales32A(LOCALE_ENUMPROC32A lpfnLocaleEnum,DWORD flags) { + int i; + + dprintf_win32(stddeb,"EnumSystemLocales32A(%p,%08lx)\n", + lpfnLocaleEnum,flags + ); + i=0; + while (locale_name2id[i].name!=NULL) { + if (!lpfnLocaleEnum(locale_name2id[i].name)) + break; + i++; + } return TRUE; } diff --git a/misc/registry.c b/misc/registry.c index cdd6751434e..90c001a4479 100644 --- a/misc/registry.c +++ b/misc/registry.c @@ -450,7 +450,7 @@ _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) { return _savesubkey(F,lpkey->nextsub,0,all); } -static void +static BOOL32 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) { FILE *F; @@ -459,15 +459,16 @@ _savereg(LPKEYSTRUCT lpkey,char *fn,int all) { fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n", fn,strerror(errno) ); - return; + return FALSE; } if (!_savesubreg(F,lpkey,all)) { fclose(F); unlink(fn); fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn); - return; + return FALSE; } fclose(F); + return TRUE; } void @@ -500,19 +501,22 @@ SHELL_SaveRegistry() { if (lstrcmpi32A(buf,"yes")) all=1; pwd=getpwuid(getuid()); - if (pwd!=NULL && pwd->pw_dir!=NULL) { - fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2); + if (pwd!=NULL && pwd->pw_dir!=NULL) + { + char *tmp = tmpnam(NULL); + fn=(char*)xmalloc( strlen(pwd->pw_dir) + strlen(WINE_PREFIX) + + strlen(SAVE_CURRENT_USER) + 2 ); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX); /* create the directory. don't care about errorcodes. */ mkdir(fn,0755); /* drwxr-xr-x */ strcat(fn,"/"SAVE_CURRENT_USER); - _savereg(key_current_user,fn,all); + if (_savereg(key_current_user,tmp,all)) rename(tmp,fn); free(fn); fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE); - _savereg(key_local_machine,fn,all); + if (_savereg(key_local_machine,tmp,all)) rename(tmp,fn); free(fn); } else fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid()); @@ -1315,6 +1319,216 @@ _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) { free(keys); } +/* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */ + +/* + reghack - windows 3.11 registry data format demo program. + + The reg.dat file has 3 parts, a header, a table of 8-byte entries that is + a combined hash table and tree description, and finally a text table. + + The header is obvious from the struct header. The taboff1 and taboff2 + fields are always 0x20, and their usage is unknown. + + The 8-byte entry table has various entry types. + + tabent[0] is a root index. The second word has the index of the root of + the directory. + tabent[1..hashsize] is a hash table. The first word in the hash entry is + the index of the key/value that has that hash. Data with the same + hash value are on a circular list. The other three words in the + hash entry are always zero. + tabent[hashsize..tabcnt] is the tree structure. There are two kinds of + entry: dirent and keyent/valent. They are identified by context. + tabent[freeidx] is the first free entry. The first word in a free entry + is the index of the next free entry. The last has 0 as a link. + The other three words in the free list are probably irrelevant. + + Entries in text table are preceeded by a word at offset-2. This word + has the value (2*index)+1, where index is the referring keyent/valent + entry in the table. I have no suggestion for the 2* and the +1. + Following the word, there are N bytes of data, as per the keyent/valent + entry length. The offset of the keyent/valent entry is from the start + of the text table to the first data byte. + + This information is not available from Microsoft. The data format is + deduced from the reg.dat file by me. Mistakes may + have been made. I claim no rights and give no guarantees for this program. + + Tor Sjøwall, tor@sn.no +*/ + +/* reg.dat header format */ +struct _w31_header { + char cookie[8]; /* 'SHCC3.10' */ + unsigned long taboff1; /* offset of hash table (??) = 0x20 */ + unsigned long taboff2; /* offset of index table (??) = 0x20 */ + unsigned long tabcnt; /* number of entries in index table */ + unsigned long textoff; /* offset of text part */ + unsigned long textsize; /* byte size of text part */ + unsigned short hashsize; /* hash size */ + unsigned short freeidx; /* free index */ +}; + +/* generic format of table entries */ +struct _w31_tabent { + unsigned short w0, w1, w2, w3; +}; + +/* directory tabent: */ +struct _w31_dirent { + unsigned short sibling_idx; /* table index of sibling dirent */ + unsigned short child_idx; /* table index of child dirent */ + unsigned short key_idx; /* table index of key keyent */ + unsigned short value_idx; /* table index of value valent */ +}; + +/* key tabent: */ +struct _w31_keyent { + unsigned short hash_idx; /* hash chain index for string */ + unsigned short refcnt; /* reference count */ + unsigned short length; /* length of string */ + unsigned short string_off; /* offset of string in text table */ +}; + +/* value tabent: */ +struct _w31_valent { + unsigned short hash_idx; /* hash chain index for string */ + unsigned short refcnt; /* reference count */ + unsigned short length; /* length of string */ + unsigned short string_off; /* offset of string in text table */ +}; + +/* recursive helper function to display a directory tree */ +void +__w31_dumptree( unsigned short idx, + unsigned char *txt, + struct _w31_tabent *tab, + struct _w31_header *head, + LPKEYSTRUCT lpkey, + time_t lastmodified, + int level +) { + struct _w31_dirent *dir; + struct _w31_keyent *key; + struct _w31_valent *val; + LPKEYSTRUCT xlpkey; + LPWSTR name,value; + static char tail[400]; + + while (idx!=0) { + dir=(struct _w31_dirent*)&tab[idx]; + + if (dir->key_idx) { + key = (struct _w31_keyent*)&tab[dir->key_idx]; + + memcpy(tail,&txt[key->string_off],key->length); + tail[key->length]='\0'; + /* all toplevel entries AND the entries in the + * toplevel subdirectory belong to \SOFTWARE\Classes + */ + if (!level && !lstrcmp32A(tail,".classes")) { + __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1); + idx=dir->sibling_idx; + continue; + } + name=STRING32_DupAnsiToUni(tail); + + xlpkey=_find_or_add_key(lpkey,name); + + /* only add if leaf node or valued node */ + if (dir->value_idx!=0||dir->child_idx==0) { + if (dir->value_idx) { + val=(struct _w31_valent*)&tab[dir->value_idx]; + memcpy(tail,&txt[val->string_off],val->length); + tail[val->length]='\0'; + value=STRING32_DupAnsiToUni(tail); + _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlen32W(value)*2+2,lastmodified); + } + } + } else { + dprintf_reg(stddeb,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx); + } + __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1); + idx=dir->sibling_idx; + } +} + +void +_w31_loadreg() { + HFILE hf; + struct _w31_header head; + struct _w31_tabent *tab; + unsigned char *txt; + int len; + OFSTRUCT ofs; + BY_HANDLE_FILE_INFORMATION hfinfo; + time_t lastmodified; + HKEY hkey; + LPKEYSTRUCT lpkey; + + hf = OpenFile("reg.dat",&ofs,OF_READ); + if (hf==HFILE_ERROR) + return; + + /* read & dump header */ + if (sizeof(head)!=_lread32(hf,&head,sizeof(head))) { + dprintf_reg(stddeb,"_w31_loadreg:reg.dat is too short.\n"); + _lclose(hf); + return; + } + if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) { + dprintf_reg(stddeb,"_w31_loadreg:reg.dat has bad signature.\n"); + _lclose(hf); + return; + } + + len = head.tabcnt * sizeof(struct _w31_tabent); + /* read and dump index table */ + tab = xmalloc(len); + if (len!=_lread32(hf,tab,len)) { + dprintf_reg(stderr,"_w31_loadreg:couldn't read %d bytes.\n",len); + free(tab); + _lclose(hf); + return; + } + + /* read text */ + txt = xmalloc(head.textsize); + if (-1==_llseek(hf,head.textoff,SEEK_SET)) { + dprintf_reg(stderr,"_w31_loadreg:couldn't seek to textblock.\n"); + free(tab); + free(txt); + _lclose(hf); + return; + } + if (head.textsize!=_lread32(hf,txt,head.textsize)) { + dprintf_reg(stderr,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len,head.textsize); + free(tab); + free(txt); + _lclose(hf); + return; + } + + if (!GetFileInformationByHandle(hf,&hfinfo)) { + dprintf_reg(stderr,"_w31_loadreg:GetFileInformationByHandle failed?.\n"); + free(tab); + free(txt); + _lclose(hf); + return; + } + lastmodified = DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime)); + + if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS) + return; + lpkey = lookup_hkey(hkey); + __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0); + free(tab); + free(txt); + _lclose(hf); + return; +} + void SHELL_LoadRegistry() { char *fn; @@ -1326,13 +1540,13 @@ SHELL_LoadRegistry() { if (key_classes_root==NULL) SHELL_Init(); + /* Load windows 3.1 entries */ + _w31_loadreg(); /* Load windows 95 entries */ _w95_loadreg("C:\\system.1st", key_local_machine); _w95_loadreg("system.dat", key_local_machine); _w95_loadreg("user.dat", key_users); - /* FIXME: win3.1 reg.dat loader still missing */ - /* the global user default is loaded under HKEY_USERS\\.Default */ RegCreateKey16(HKEY_USERS,".Default",&hkey); lpkey = lookup_hkey(hkey); diff --git a/misc/shell.c b/misc/shell.c index 3a96897f31f..2f9cc8b218f 100644 --- a/misc/shell.c +++ b/misc/shell.c @@ -195,29 +195,34 @@ static HINSTANCE16 SHELL_FindExecutable( LPCSTR lpFile, /* extensions; however, it'd make sense to check the programs */ /* section first, so that's what happens here. */ - /* See if it's a program */ - GetProfileString("windows", "programs", "exe pif bat com", - buffer, sizeof(buffer)); /* FIXME check return code! */ + /* See if it's a program - if GetProfileString fails, we skip this + * section. Actually, if GetProfileString fails, we've probably + * got a lot more to worry about than running a program... */ + if ( GetProfileString32A("windows", "programs", "exe pif bat com", + buffer, sizeof(buffer)) > 0 ) + { + for (i=0;i5)) - { - strcat( lpResult, &tok[5]); - } - } - retval=33; + if ( GetProfileString32A( "extensions", extension, "", command, + sizeof(command)) > 0) + { + if (strlen(command)!=0) + { + strcpy( lpResult, command ); + tok=strstr( lpResult, "^" ); /* should be ^.extension? */ + if (tok != NULL) + { + tok[0]='\0'; + strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */ + tok=strstr( command, "^" ); /* see above */ + if ((tok != NULL) && (strlen(tok)>5)) + { + strcat( lpResult, &tok[5]); + } + } + retval=33; /* FIXME - see above */ + } + } } - } dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult); return retval; @@ -804,7 +811,7 @@ DWORD DoEnvironmentSubst(LPSTR str,WORD length) */ int RegisterShellHook(void *ptr) { - fprintf(stdnimp, "RegisterShellHook : Empty Stub !!!\n"); + fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr); return 0; } diff --git a/misc/spy.c b/misc/spy.c index 57ce9d939ab..1b00d39a592 100644 --- a/misc/spy.c +++ b/misc/spy.c @@ -296,7 +296,8 @@ static const char * const MessageTypeNames[SPY_MAX_MSGNUM + 1] = "LB_SETITEMHEIGHT32", /* 0x01a0 */ "LB_GETITEMHEIGHT32", /* 0x01a1 */ "LB_FINDSTRINGEXACT32", /* 0x01a2 */ - NULL, NULL, + "LB_CARETON32", /* 0x01a3 */ + "LB_CARETOFF32", /* 0x01a4 */ "LB_SETLOCALE32", /* 0x01a5 */ "LB_GETLOCALE32", /* 0x01a6 */ "LB_SETCOUNT32", /* 0x01a7 */ diff --git a/misc/user.c b/misc/user.c index 3516a78a661..68a91a510a3 100644 --- a/misc/user.c +++ b/misc/user.c @@ -101,7 +101,7 @@ INT16 InitApp( HINSTANCE16 hInstance ) int queueSize; /* Create task message queue */ - queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 ); + queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 ); if (!SetMessageQueue( queueSize )) return 0; return 1; @@ -112,8 +112,7 @@ INT16 InitApp( HINSTANCE16 hInstance ) */ void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue ) { - /* FIXME: flush send messages (which are not implemented yet), - * empty clipboard if needed, maybe destroy menus (Windows + /* FIXME: empty clipboard if needed, maybe destroy menus (Windows * only complains about them but does nothing); */ @@ -126,18 +125,13 @@ void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue ) /* Patch resident popup menu window */ MENU_SwitchTPWndTo(0); - /* Nuke timers */ - TIMER_RemoveQueueTimers( hQueue ); + QUEUE_FlushMessages( hQueue ); HOOK_FreeQueueHooks( hQueue ); QUEUE_SetDoomedQueue( hQueue ); - - /* Nuke orphaned windows */ - - WIN_DestroyQueueWindows( desktop->child, hQueue ); - + WIN_ResetQueueWindows( desktop->child, hQueue, (HQUEUE16)0); QUEUE_SetDoomedQueue( 0 ); /* Free the message queue */ diff --git a/misc/winsock.c b/misc/winsock.c new file mode 100644 index 00000000000..cb22484ccc0 --- /dev/null +++ b/misc/winsock.c @@ -0,0 +1,1713 @@ +/* + * based on Windows Sockets 1.1 specs + * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT) + * + * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka. + */ + +#include +#include +#include +#include +#include +#include +#if defined(__svr4__) +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windows.h" +#include "winnt.h" +#include "heap.h" +#include "ldt.h" +#include "winsock.h" +#include "stddebug.h" +#include "debug.h" + +#define dump_sockaddr(a) \ + fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \ + ((struct sockaddr_in *)a)->sin_family, \ + inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \ + ntohs(((struct sockaddr_in *)a)->sin_port)) + +extern void SIGNAL_MaskAsyncEvents( BOOL32 ); + +#pragma pack(4) + +/* ----------------------------------- internal data */ + +extern int h_errno; +extern void __sigio(int); + +ws_async_ctl async_ctl; +int async_qid = -1; + +static HANDLE32 _WSHeap = 0; +static unsigned char* _ws_stub = NULL; +static LPWSINFO _wsi_list = NULL; + +#define WS_ALLOC(size) \ + HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) ) +#define WS_FREE(ptr) \ + HeapFree(_WSHeap, 0, (ptr) ) + +#define WS_PTR2HANDLE(ptr) \ + ((short)((int)(ptr) - (int)_ws_stub)) +#define WS_HANDLE2PTR(handle) \ + ((unsigned)((int)_ws_stub + (int)handle)) + +#define WSI_CHECK_RANGE(pwsi, pws) \ + ( ((unsigned)(pws) > (unsigned)(pwsi)) && \ + ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) ) + +static INT16 _ws_sock_ops[] = + { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE, + WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF, + WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 }; +static int _px_sock_ops[] = + { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST, + SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE, + SO_LINGER }; + +static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent); +static int notify_client(ws_socket* pws, unsigned flag); + +static int _check_ws(LPWSINFO pwsi, ws_socket* pws); +static int _check_buffer(LPWSINFO pwsi, int size); + +static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base); +static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base); +static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base); + +static int delete_async_op(ws_socket*); + +static void convert_sockopt(INT16 *level, INT16 *optname) +{ + int i; + switch (*level) + { + case WS_SOL_SOCKET: + *level = SOL_SOCKET; + for(i=0; _ws_sock_ops[i]; i++) + if( _ws_sock_ops[i] == *optname ) break; + if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i]; + else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname); + break; + case WS_IPPROTO_TCP: + *optname = IPPROTO_TCP; + } +} + +static void _ws_global_init() +{ + if( !_ws_stub ) + { + _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768); + if( !(_ws_stub = WS_ALLOC(0x10)) ) + fprintf(stderr,"Fatal: failed to create WinSock heap\n"); + } + if( async_qid == -1 ) + if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 ) + fprintf(stderr,"Fatal: failed to create WinSock resource\n"); +} + +/* ----------------------------------- Per-thread info */ + +static void wsi_link(LPWSINFO pwsi) +{ if( _wsi_list ) _wsi_list->prev = pwsi; + pwsi->next = _wsi_list; _wsi_list = pwsi; +} + +static void wsi_unlink(LPWSINFO pwsi) +{ + if( pwsi == _wsi_list ) _wsi_list = pwsi->next; + else + { pwsi->prev->next = pwsi->next; + if( pwsi->next ) pwsi->next->prev = pwsi->prev; } +} + +static LPWSINFO wsi_find(HTASK16 hTask) +{ LPWSINFO pwsi = _wsi_list; + while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next; + return pwsi; +} + +static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd) +{ + if( pwsi->last_free >= 0 ) + { + int i = pwsi->last_free; + + pwsi->last_free = pwsi->sock[i].flags; + pwsi->sock[i].fd = fd; + pwsi->sock[i].flags = 0; + return &pwsi->sock[i]; + } + return NULL; +} + +static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd) +{ + FD_ZERO(fds); + if(ws) + { + int i; + ws_socket* pws; + for(i=0;i<(ws->fd_count);i++) + { + pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]); + if( _check_ws(pwsi, pws) ) + { + if( pws->fd > *highfd ) *highfd = pws->fd; + FD_SET(pws->fd, fds); + } + } + } +} + +static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws) +{ + if( ws ) + { + int i, j, count = ws->fd_count; + ws_socket* pws; + for( i = 0, j = 0; i < count; i++ ) + { + pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]); + if( _check_ws(pwsi, pws) ) + if( FD_ISSET(pws->fd, fds) ) + { + ws->fd_array[j++] = ws->fd_array[i]; + continue; + } + ws->fd_count--; + } + } +} + +/* ----------------------------------- API ----- + * + * Init / cleanup / error checking. + */ + +INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData) +{ + WSADATA WINSOCK_data = { 0x0101, 0x0101, + "WINE Sockets 1.1", + #ifdef linux + "Linux/i386", + #elif defined(__NetBSD__) + "NetBSD/i386", + #elif defined(sunos) + "SunOS", + #elif defined(__FreeBSD__) + "FreeBSD", + #else + "Unknown", + #endif + WS_MAX_SOCKETS_PER_THREAD, + WS_MAX_UDP_DATAGRAM, NULL }; + HTASK16 tid = GetCurrentTask(); + LPWSINFO pwsi; + + dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested); + + if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 && + HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED; + + if (!lpWSAData) return WSAEINVAL; + + _ws_global_init(); + if( _WSHeap == 0 ) return WSASYSNOTREADY; + + pwsi = wsi_find(GetCurrentTask()); + if( pwsi == NULL ) + { + if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) ) + { + int i = 0; + pwsi->tid = tid; + for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ ) + { + pwsi->sock[i].fd = -1; + pwsi->sock[i].flags = i + 1; + } + pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1; + } + else return WSASYSNOTREADY; + wsi_link(pwsi); + } else pwsi->num_startup++; + + /* return winsock information */ + memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data)); + + dprintf_winsock(stddeb, "WSAStartup: succeeded\n"); + return(0); +} + +INT16 WSACleanup(void) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + /* FIXME: do global cleanup if no current task */ + + dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi); + if( pwsi ) + { + int i, j, n; + + if( pwsi->num_startup-- ) return 0; + + SIGNAL_MaskAsyncEvents( TRUE ); + WINSOCK_cancel_async_op(GetCurrentTask()); + SIGNAL_MaskAsyncEvents( FALSE ); + + wsi_unlink(pwsi); + if( _wsi_list == NULL && async_qid != -1 ) + if( msgctl(async_qid, IPC_RMID, NULL) == -1 ) + { + fprintf(stderr,"failed to delete WS message queue.\n"); + } else async_qid = -1; + + if( pwsi->flags & WSI_BLOCKINGCALL ) + dprintf_winsock(stddeb,"\tinside blocking call!\n"); + if( pwsi->num_async_rq ) + dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq ); + + for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++) + if( pwsi->sock[i].fd != -1 ) + { + n += delete_async_op(&pwsi->sock[i]); + close(pwsi->sock[i].fd); j++; + } + if( j ) + dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n); + + if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer); + WS_FREE(pwsi); + return 0; + } + return SOCKET_ERROR; +} + +INT16 WSAGetLastError(void) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + INT16 ret; + + dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi); + + ret = (pwsi) ? pwsi->errno : WSANOTINITIALISED; + + dprintf_winsock(stddeb, " = %i\n", (int)ret); + return ret; +} + +void WSASetLastError(INT16 iError) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError); + + if( pwsi ) pwsi->errno = iError; +} + +int _check_ws(LPWSINFO pwsi, ws_socket* pws) +{ + if( pwsi ) + if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->errno = WSAEINPROGRESS; + else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1; + else pwsi->errno = WSAENOTSOCK; + return 0; +} + +int _check_buffer(LPWSINFO pwsi, int size) +{ + if( pwsi->buffer && pwsi->buflen >= size ) return 1; + else SEGPTR_FREE(pwsi->buffer); + pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); + return (pwsi->buffer != NULL); +} + +/* ----- socket operations */ + +SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", + (unsigned)pwsi, (UINT16)s); + if( _check_ws(pwsi, pws) ) + { + int sock, fd_flags, addrlen32 = *addrlen16; + + /* this is how block info is supposed to be used - + * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit. + */ + + fd_flags = fcntl(pws->fd, F_GETFL, 0); + if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL; + + if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 ) + { + ws_socket* pnew = wsi_alloc_socket(pwsi, sock); + notify_client(pws, WS_FD_ACCEPT); + if( pnew ) + { + if( pws->p_aop ) + init_async_select(pnew, pws->p_aop->hWnd, + pws->p_aop->uMsg, + pws->p_aop->flags & ~WS_FD_ACCEPT ); + + pwsi->flags &= ~WSI_BLOCKINGCALL; + return (SOCKET16)WS_PTR2HANDLE(pnew); + } + else pwsi->errno = WSAENOBUFS; + } + else pwsi->errno = wsaErrno(); + + pwsi->flags &= ~WSI_BLOCKINGCALL; + } + return INVALID_SOCKET; +} + +INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", + (unsigned)pwsi, s, (int) name, namelen); +#if 0 + dump_sockaddr(name); +#endif + + if ( _check_ws(pwsi, pws) ) + if (namelen >= sizeof(*name)) + if ( ((struct sockaddr_in *)name)->sin_family == AF_INET ) + if ( bind(pws->fd, name, namelen) < 0 ) + { + int loc_errno = errno; + dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno); + errno = loc_errno; + switch(errno) + { + case EBADF: pwsi->errno = WSAENOTSOCK; break; + case EADDRNOTAVAIL: pwsi->errno = WSAEINVAL; break; + default: pwsi->errno = wsaErrno(); + } + } + else return 0; + else pwsi->errno = WSAEAFNOSUPPORT; + else pwsi->errno = WSAEFAULT; + return SOCKET_ERROR; +} + +INT16 WINSOCK_closesocket(SOCKET16 s) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s); + + if( _check_ws(pwsi, pws) ) + { + int fd = pws->fd; + + delete_async_op(pws); + pws->p_aop = NULL; pws->fd = -1; + pws->flags = (unsigned)pwsi->last_free; + pwsi->last_free = pws - &pwsi->sock[0]; + if (close(fd) < 0) pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); + else return 0; + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", + (unsigned)pwsi, s, (int) name, namelen); +#if 0 + dump_sockaddr(name); +#endif + + if( _check_ws(pwsi, pws) ) + { + if (connect(pws->fd, name, namelen) == 0) + { + if( pws->p_aop ) + /* we need to notify handler process if + * connect() succeeded NOT in response to winsock message + */ + notify_client(pws, WS_FD_CONNECTED); + + pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT); + return 0; + } + pwsi->errno = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", + (unsigned)pwsi, s, (int) name, *namelen); + if( _check_ws(pwsi, pws) ) + { + int namelen32 = *namelen; + if (getpeername(pws->fd, name, &namelen32) == 0) + { +#if 0 + dump_sockaddr(name); +#endif + *namelen = (INT16)namelen32; + return 0; + } + pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", + (unsigned)pwsi, s, (int) name, (int) *namelen); + if( _check_ws(pwsi, pws) ) + { + int namelen32 = *namelen; + if (getsockname(pws->fd, name, &namelen32) == 0) + { + *namelen = (INT16)namelen32; + return 0; + } + pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level, + INT16 optname, char *optval, INT16 *optlen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WSA_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", + (unsigned)pwsi, s, level, (int) optval, (int) *optlen); + + if( _check_ws(pwsi, pws) ) + { + int optlen32 = *optlen; + + convert_sockopt(&level, &optname); + if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 ) + { *optlen = (INT16)optlen32; return 0; } + pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); + } + return SOCKET_ERROR; +} + +u_long WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); } +u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); } +u_long WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); } +u_long WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); } +u_short WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); } + +SEGPTR WINSOCK_inet_ntoa(struct in_addr in) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + char* s = inet_ntoa(in); + + if( pwsi ) + { + if( s == NULL ) { pwsi->errno = wsaErrno(); return NULL; } + if( _check_buffer( pwsi, 32 ) ) + { + strncpy(pwsi->buffer, s, 32 ); + return SEGPTR_GET(pwsi->buffer); + } + pwsi->errno = WSAENOBUFS; + } + return (SEGPTR)NULL; +} + +INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", + (unsigned)pwsi, s, cmd, (unsigned) argp); + if( _check_ws(pwsi, pws) ) + { + long newcmd = cmd; + + switch( cmd ) + { + case WS_FIONREAD: newcmd=FIONREAD; break; + case WS_FIONBIO: newcmd=FIONBIO; + if( pws->p_aop && *argp == 0 ) + { + pwsi->errno = WSAEINVAL; + return SOCKET_ERROR; + } + break; + case WS_SIOCATMARK: newcmd=SIOCATMARK; break; + case WS_IOW('f',125,u_long): + fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n"); + pwsi->errno = WSAEINVAL; return SOCKET_ERROR; + default: fprintf(stderr,"Warning: Unknown WS_IOCTL cmd (%08x)\n", cmd); + } + if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0; + pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", + (unsigned)pwsi, s, backlog); + if( _check_ws(pwsi, pws) ) + { + if( !pws->p_aop ) + { + int fd_flags = fcntl(pws->fd, F_GETFL, 0); + if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT; + } + else notify_client(pws, WS_FD_ACCEPT); + + if (listen(pws->fd, backlog) == 0) return 0; + pwsi->errno = wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d", + (unsigned)pwsi, s, (unsigned)buf, len, flags); + if( _check_ws(pwsi, pws) ) + { + int length; + if ((length = recv(pws->fd, buf, len, flags)) >= 0) + { + dprintf_winsock(stddeb, " -> %i bytes\n", length); + notify_client(pws, WS_FD_READ); + return (INT16)length; + } + pwsi->errno = wsaErrno(); + } + dprintf_winsock(stddeb, " -> ERROR\n"); + return SOCKET_ERROR; +} + +INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, + struct sockaddr *from, INT16 *fromlen16) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n", + (unsigned)pwsi, s, (unsigned)buf, len, flags); + if( _check_ws(pwsi, pws) ) + { + int length, fromlen32 = *fromlen16; + if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0) + { + *fromlen16 = fromlen32; + notify_client(pws, WS_FD_READ); + return (INT16)length; + } + pwsi->errno = wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds, + ws_fd_set *ws_writefds, + ws_fd_set *ws_exceptfds, struct timeval *timeout) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", + (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds); + + if( pwsi ) + { + int highfd = 0; + fd_set readfds, writefds, exceptfds; + + fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd); + fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd); + fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd); + + if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 ) + { + if( highfd ) + { + fd_set_update(pwsi, &readfds, ws_readfds); + fd_set_update(pwsi, &writefds, ws_writefds); + fd_set_update(pwsi, &exceptfds, ws_exceptfds); + } + return highfd; + } + pwsi->errno = wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", + (unsigned)pwsi, s, (unsigned) buf, len, flags); + if( _check_ws(pwsi, pws) ) + { + int length; + if ((length = send(pws->fd, buf, len, flags)) < 0 ) + { + length = SOCKET_ERROR; + pwsi->errno = wsaErrno(); + } + notify_client(pws, WS_FD_WRITE); + return (INT16)length; + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags, + struct sockaddr *to, INT16 tolen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n", + (unsigned)pwsi, s, (unsigned) buf, len, flags); + if( _check_ws(pwsi, pws) ) + { + int length; + + if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 ) + { + length = SOCKET_ERROR; + pwsi->errno = wsaErrno(); + } + notify_client(pws, WS_FD_WRITE); + return (INT16)length; + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname, + char *optval, INT16 optlen) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n", + (unsigned)pwsi, s, level, optname, (int) optval, optlen); + if( _check_ws(pwsi, pws) ) + { + int linger32[2]; + convert_sockopt(&level, &optname); + if( optname == SO_LINGER ) + { + INT16* ptr = (INT16*)optval; + linger32[0] = ptr[0]; + linger32[1] = ptr[1]; + optval = (char*)&linger32; + optlen = sizeof(linger32); + } + if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0; + pwsi->errno = wsaErrno(); + } + return SOCKET_ERROR; +} + +INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n", + (unsigned)pwsi, s, how ); + if( _check_ws(pwsi, pws) ) + { + pws->flags = WS_FD_INACTIVE; + delete_async_op(pws); + + if (shutdown(pws->fd, how) == 0) return 0; + pwsi->errno = wsaErrno(); + } + return SOCKET_ERROR; +} + +SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", + (unsigned)pwsi, af, type, protocol); + + if( pwsi ) + { + int sock; + + /* check the socket family */ + switch(af) + { + case AF_INET: + case AF_UNSPEC: break; + default: pwsi->errno = WSAEAFNOSUPPORT; return INVALID_SOCKET; + } + + /* check the socket type */ + switch(type) + { + case SOCK_STREAM: + case SOCK_DGRAM: + case SOCK_RAW: break; + default: pwsi->errno = WSAESOCKTNOSUPPORT; return INVALID_SOCKET; + } + + /* check the protocol type */ + if ( protocol < 0 ) /* don't support negative values */ + { pwsi->errno = WSAEPROTONOSUPPORT; return INVALID_SOCKET; } + + if ( af == AF_UNSPEC) /* did they not specify the address family? */ + switch(protocol) + { + case IPPROTO_TCP: + if (type == SOCK_STREAM) { af = AF_INET; break; } + case IPPROTO_UDP: + if (type == SOCK_DGRAM) { af = AF_INET; break; } + default: pwsi->errno = WSAEPROTOTYPE; return INVALID_SOCKET; + } + + if ((sock = socket(af, type, protocol)) >= 0) + { + ws_socket* pnew = wsi_alloc_socket(pwsi, sock); + +/* printf("created %04x (%i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew)); + */ + if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew); + else pwsi->errno = WSAENOBUFS; + } + + if (errno == EPERM) /* raw socket denied */ + { + fprintf(stderr, "WS_SOCKET: not enough privileges\n"); + pwsi->errno = WSAESOCKTNOSUPPORT; + } pwsi->errno = wsaErrno(); + } + + dprintf_winsock(stddeb, "\t\tfailed!\n"); + return INVALID_SOCKET; +} + + +/* ----- database functions + * + * Note that ws_...ent structures we return have SEGPTR pointers inside them. + */ + +static char* NULL_STRING = "NULL"; + +/* +struct WIN_hostent * +*/ +SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n", + (unsigned)pwsi, (unsigned) addr, len, type); + if( pwsi ) + { + struct hostent* host; + if( (host = gethostbyaddr(addr, len, type)) != NULL ) + if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return NULL; +} + +/* +struct WIN_hostent * +*/ +SEGPTR WINSOCK_gethostbyname(const char *name) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n", + (unsigned)pwsi, (name)?name:"NULL"); + if( pwsi ) + { + struct hostent* host; + if( (host = gethostbyname(name)) != NULL ) + if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return NULL; +} + +INT16 WINSOCK_gethostname(char *name, INT16 namelen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", + (unsigned)pwsi, (name)?name:NULL_STRING, namelen); + if( pwsi ) + { + if (gethostname(name, namelen) == 0) return 0; + pwsi->errno = (errno == EINVAL) ? WSAEFAULT : wsaErrno(); + } + return SOCKET_ERROR; +} + +/* +struct WIN_protoent * +*/ +SEGPTR WINSOCK_getprotobyname(char *name) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n", + (unsigned)pwsi, (name)?name:NULL_STRING); + if( pwsi ) + { + struct protoent* proto; + if( (proto = getprotobyname(name)) != NULL ) + if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return NULL; +} + +/* +struct WIN_protoent * +*/ +SEGPTR WINSOCK_getprotobynumber(INT16 number) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number); + + if( pwsi ) + { + struct protoent* proto; + if( (proto = getprotobynumber(number)) != NULL ) + if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = WSANO_DATA; + } + return NULL; +} + +/* +struct WIN_servent * +*/ +SEGPTR WINSOCK_getservbyname(const char *name, const char *proto) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n", + (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING); + + if( pwsi ) + { + struct servent* serv; + if( (serv = getservbyname(name, proto)) != NULL ) + if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return NULL; +} + +/* +struct WIN_servent * +*/ +SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n", + (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING); + if( pwsi ) + { + struct servent* serv; + if( (serv = getservbyport(port, proto)) != NULL ) + if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) ) + return SEGPTR_GET(pwsi->buffer); + else pwsi->errno = WSAENOBUFS; + else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno(); + } + return NULL; +} + + +/* ----------------------------------- Windows sockets extensions -- * + * * + * ----------------------------------------------------------------- */ + +static int aop_control(ws_async_op* p_aop, int flag ) +{ + unsigned lLength; + + read(p_aop->fd[0], &lLength, sizeof(unsigned)); + if( LOWORD(lLength) ) + if( LOWORD(lLength) <= p_aop->buflen ) + { + char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base); + read(p_aop->fd[0], buffer, LOWORD(lLength)); + switch( p_aop->flags ) + { + case WSMSG_ASYNC_HOSTBYNAME: + case WSMSG_ASYNC_HOSTBYADDR: + fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break; + case WSMSG_ASYNC_PROTOBYNAME: + case WSMSG_ASYNC_PROTOBYNUM: + fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break; + case WSMSG_ASYNC_SERVBYNAME: + case WSMSG_ASYNC_SERVBYPORT: + fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break; + default: + if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n"); + return AOP_CONTROL_REMOVE; + } + } + else lLength = ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16); + +#if 0 + printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n", + p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength); +#endif + + PostMessage(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength); + return AOP_CONTROL_REMOVE; +} + + +static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init, + INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag) +{ + /* queue 'flag' request and fork off its handler */ + + async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op)); + + if( async_ctl.ws_aop ) + { + HANDLE16 handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop); + + if( pipe(async_ctl.ws_aop->fd) == 0 ) + { + async_ctl.ws_aop->init = (char*)init; + async_ctl.lLength = len; + async_ctl.lEvent = type; + + async_ctl.ws_aop->hWnd = hWnd; + async_ctl.ws_aop->uMsg = uMsg; + + async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen; + async_ctl.ws_aop->flags = flag; + async_ctl.ws_aop->aop_control = &aop_control; + WINSOCK_link_async_op( async_ctl.ws_aop ); + + async_ctl.ws_aop->pid = fork(); + if( async_ctl.ws_aop->pid ) + { + close(async_ctl.ws_aop->fd[1]); /* write endpoint */ + + /* Damn, BSD'ish SIGIO doesn't work on pipes/streams + * + * async_io(async_ctl.ws_aop->fd[0], 1); + */ + + dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n", + handle, async_ctl.ws_aop->pid); + return handle; + } else + /* child process */ + { + close(async_ctl.ws_aop->fd[0]); /* read endpoint */ + switch(flag) + { + case WSMSG_ASYNC_HOSTBYADDR: + case WSMSG_ASYNC_HOSTBYNAME: + WS_do_async_gethost(pwsi,flag); + case WSMSG_ASYNC_PROTOBYNUM: + case WSMSG_ASYNC_PROTOBYNAME: + WS_do_async_getproto(pwsi,flag); + case WSMSG_ASYNC_SERVBYPORT: + case WSMSG_ASYNC_SERVBYNAME: + WS_do_async_getserv(pwsi,flag); + } + } + } + WS_FREE(async_ctl.ws_aop); + pwsi->errno = wsaErrno(); + } else pwsi->errno = WSAEWOULDBLOCK; + return 0; +} + +HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr, + INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n", + (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len ); + + if( pwsi ) + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len, + type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR ); + return 0; +} + + +HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, + SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n", + (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen ); + + if( pwsi ) + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0, + 0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME ); + return 0; +} + + +HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, + SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n", + (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING ); + + if( pwsi ) + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0, + 0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME ); + return 0; +} + + +HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, + SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n", + (unsigned)pwsi, hWnd, uMsg, number ); + + if( pwsi ) + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0, + number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM ); + return 0; +} + + +HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, + LPCSTR proto, SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n", + (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING ); + + if( pwsi ) + { + async_ctl.buffer = (char*)proto; + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0, + 0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME ); + } + return 0; +} + + +HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, + LPCSTR proto, SEGPTR sbuf, INT16 buflen) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n", + (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING ); + + if( pwsi ) + return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0, + port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT ); + return 0; +} + +INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_async_op* p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle); + + dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", + (unsigned)pwsi, hAsyncTaskHandle); + if( pwsi ) + if( WINSOCK_check_async_op(p_aop) ) + { + kill(p_aop->pid, SIGKILL); + waitpid(p_aop->pid, NULL, 0); + close(p_aop->fd[0]); + WINSOCK_unlink_async_op(p_aop); + WS_FREE(p_aop); + return 0; + } + else pwsi->errno = WSAEINVAL; + return SOCKET_ERROR; +} + +/* ----- asynchronous select() */ + +int delete_async_op(ws_socket* pws) +{ + if( pws->p_aop ) + { + kill(pws->p_aop->pid, SIGKILL); + waitpid(pws->p_aop->pid, NULL, 0); + WS_FREE(pws->p_aop); return 1; + pws->flags &= WS_FD_INTERNAL; + } + return 0; +} + +void _sigusr1_handler_parent(int sig) +{ + /* child process puts MTYPE_CLIENT data packet into the + * 'async_qid' message queue and signals us with SIGUSR1. + * This handler reads the queue and posts 'uMsg' notification + * message. + */ + + ipc_packet ipack; + + signal( SIGUSR1, _sigusr1_handler_parent); + while( msgrcv(async_qid, (struct msgbuf*)&ipack, + MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 ) + { + if( ipack.wParam && abs((short)ipack.wParam) < 32768 ) + { + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam); + if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 ) + { + pws->flags &= ~(ipack.lParam); +#if 0 + printf("async event - hWnd %04x, uMsg %04x [%08x]\n", + pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam ); +#endif + PostMessage(pws->p_aop->hWnd, pws->p_aop->uMsg, + (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam ); + } + else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam); + } + else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam); + } +} + +int notify_client( ws_socket* pws, unsigned flag ) +{ + if( pws->p_aop && ((pws->p_aop->flags & flag) || + (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) ) + { + async_ctl.ip.mtype = MTYPE_PARENT; + async_ctl.ip.lParam = flag; + while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip), + MTYPE_PARENT_SIZE, 0) == -1 ) + { + if( errno == EINTR ) continue; + else + { + perror("AsyncSelect(parent)"); + delete_async_op(pws); + pws->flags &= WS_FD_INTERNAL; + return 0; + } + } + kill(pws->p_aop->pid, SIGUSR1); + return 1; + } + return 0; +} + +INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent) +{ + ws_async_op* p_aop; + + if( delete_async_op(pws) ) /* delete old async handler if any */ + { + pws->p_aop = NULL; + pws->flags &= WS_FD_INTERNAL; + } + if( lEvent == 0 ) return 0; + + /* setup async handler - some data may be redundant */ + + WINSOCK_unblock_io(pws->fd, 1); + if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) ) + { + p_aop->hWnd = hWnd; + p_aop->uMsg = uMsg; + pws->p_aop = p_aop; + + async_ctl.lEvent = p_aop->flags = lEvent; + async_ctl.ws_sock = pws; + async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws); + async_ctl.ip.lParam = 0; + + p_aop->pid = fork(); + if( p_aop->pid != -1 ) + if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */ + else pws->flags |= lEvent; + + signal( SIGUSR1, _sigusr1_handler_parent ); + return 0; /* Wine process */ + } + return SOCKET_ERROR; +} + +INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent) +{ + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n", + (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent ); + if( _check_ws(pwsi, pws) ) + if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0; + else pwsi->errno = WSAENOBUFS; + return SOCKET_ERROR; +} + +/* ----- miscellaneous */ + +INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set) +{ + int i = set->fd_count; + + dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set); + + while (i--) + if (set->fd_array[i] == fd) return 1; + return 0; +} + +BOOL16 WSAIsBlocking(void) +{ + /* By default WinSock should set all its sockets to non-blocking mode + * and poll in PeekMessage loop when processing "blocking" ones. This + * function * is supposed to tell if program is in this loop. Our + * blocking calls are truly blocking so we always return FALSE. + * + * Note: It is allowed to call this function without prior WSAStartup(). + */ + + dprintf_winsock(stddeb, "WS_IsBlocking()\n"); + return FALSE; +} + +INT16 WSACancelBlockingCall(void) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi); + + if( pwsi ) return 0; + return SOCKET_ERROR; +} + +FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc) +{ + FARPROC16 prev; + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n", + (unsigned)pwsi, (unsigned) lpBlockFunc); + + if( pwsi ) { + prev = pwsi->blocking_hook; + pwsi->blocking_hook = lpBlockFunc; + return prev; + } + return 0; +} + +INT16 WSAUnhookBlockingHook(void) +{ + LPWSINFO pwsi = wsi_find(GetCurrentTask()); + + dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi); + if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL); + return SOCKET_ERROR; +} + +VOID +WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) +{ + fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n", + x1,x2,x3,x4,x5,x6 + ); + fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n", + x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0 + ); + return; +} +/* ----------------------------------- end of API stuff */ + + + +/* ----------------------------------- helper functions */ + +static int list_size(char** l, int item_size) +{ + int i,j = 0; + if(l) + { for(i=0;l[i];i++) + j += (item_size) ? item_size : strlen(l[i]) + 1; + j += (i + 1) * sizeof(char*); } + return j; +} + +static int list_dup(char** l_src, char* ref, char* base, int item_size) +{ + /* base is either either equal to ref or 0 or SEGPTR */ + + char* p = ref; + char** l_to = (char**)ref; + int i,j,k; + + for(j=0;l_src[j];j++) ; + p += (j + 1) * sizeof(char*); + for(i=0;ih_name) + 1; + size += list_size(p_he->h_aliases, 0); + size += list_size(p_he->h_addr_list, p_he->h_length ); } + return size; +} + +int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag) +{ + /* Duplicate hostent structure and flatten data (with its pointers) + * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or + * relative to 0 depending on "flag" value. Return data size (also + * in the pwsi->buflen). + */ + + int size = hostent_size(p_he); + if( size ) + { + char* p_name,*p_aliases,*p_addr,*p_base,*p; + + _check_buffer(pwsi, size); + p = pwsi->buffer; + p_base = (flag & WS_DUP_OFFSET) ? NULL + : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p); + p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent); + p_name = p; + strcpy(p, p_he->h_name); p += strlen(p) + 1; + p_aliases = p; + p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0); + p_addr = p; + list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length); + if( !(flag & WS_DUP_SEGPTR) ) + { struct hostent* p_to = (struct hostent*)pwsi->buffer; + p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length; + p_to->h_name = p_base + (p_name - pwsi->buffer); + p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); + p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); } + else + { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer; + p_to->h_addrtype = (INT16)p_he->h_addrtype; + p_to->h_length = (INT16)p_he->h_length; + p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer)); + p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); + p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer)); + return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); } + } + return size; +} + +void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base) +{ + /* add 'base' to ws_hostent pointers to convert them from offsets */ + + int i; + unsigned* p_aliases,*p_addr; + + p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases); + p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list); + ((unsigned)(p_wshe->h_name)) += (unsigned)base; + ((unsigned)(p_wshe->h_aliases)) += (unsigned)base; + ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base; + for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base; + for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base; +} + +/* ----- protoent */ + +static int protoent_size(struct protoent* p_pe) +{ + int size = 0; + if( p_pe ) + { size = sizeof(struct protoent); + size += strlen(p_pe->p_name) + 1; + size += list_size(p_pe->p_aliases, 0); } + return size; +} + +int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag) +{ + int size = protoent_size(p_pe); + if( size ) + { + char* p_name,*p_aliases,*p_base,*p; + + _check_buffer(pwsi, size); + p = pwsi->buffer; + p_base = (flag & WS_DUP_OFFSET) ? NULL + : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p); + p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent); + p_name = p; + strcpy(p, p_pe->p_name); p += strlen(p) + 1; + p_aliases = p; + list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0); + if( !(flag & WS_DUP_NATIVE) ) + { struct protoent* p_to = (struct protoent*)pwsi->buffer; + p_to->p_proto = p_pe->p_proto; + p_to->p_name = p_base + (p_name - pwsi->buffer); + p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); } + else + { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer; + p_to->p_proto = (INT16)p_pe->p_proto; + p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer); + p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); + return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); } + } + return size; +} + +void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base) +{ + int i; + unsigned* p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases); + ((unsigned)(p_wspe->p_name)) += (unsigned)base; + ((unsigned)(p_wspe->p_aliases)) += (unsigned)base; + for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base; +} + +/* ----- servent */ + +static int servent_size(struct servent* p_se) +{ + int size = 0; + if( p_se ) + { size += sizeof(struct servent); + size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2; + size += list_size(p_se->s_aliases, 0); } + return size; +} + +int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag) +{ + int size = servent_size(p_se); + if( size ) + { + char* p_name,*p_aliases,*p_proto,*p_base,*p; + + _check_buffer(pwsi, size); + p = pwsi->buffer; + p_base = (flag & WS_DUP_OFFSET) ? NULL + : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p); + p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent); + p_name = p; + strcpy(p, p_se->s_name); p += strlen(p) + 1; + p_proto = p; + strcpy(p, p_se->s_proto); p += strlen(p) + 1; + p_aliases = p; + list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0); + + if( !(flag & WS_DUP_SEGPTR) ) + { struct servent* p_to = (struct servent*)pwsi->buffer; + p_to->s_port = p_se->s_port; + p_to->s_name = p_base + (p_name - pwsi->buffer); + p_to->s_proto = p_base + (p_proto - pwsi->buffer); + p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); } + else + { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer; + p_to->s_port = (INT16)p_se->s_port; + p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer)); + p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer)); + p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); + return (size + sizeof(struct ws_servent) - sizeof(struct servent)); } + } + return size; +} + +void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base) +{ + int i; + unsigned* p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases); + ((unsigned)(p_wsse->s_name)) += (unsigned)base; + ((p_wsse->s_proto)) += (unsigned)base; + ((p_wsse->s_aliases)) += (unsigned)base; + for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base; +} + +/* ----------------------------------- error handling */ + +UINT16 wsaErrno(void) +{ + int loc_errno = errno; +#if defined(__FreeBSD__) + dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", + errno, sys_errlist[errno]); +#else + dprintf_winsock(stderr, "winsock: errno %d\n", errno); +#endif + + switch(loc_errno) + { + case EINTR: return WSAEINTR; + case EBADF: return WSAEBADF; + case EACCES: return WSAEACCES; + case EFAULT: return WSAEFAULT; + case EINVAL: return WSAEINVAL; + case EMFILE: return WSAEMFILE; + case EWOULDBLOCK: return WSAEWOULDBLOCK; + case EINPROGRESS: return WSAEINPROGRESS; + case EALREADY: return WSAEALREADY; + case ENOTSOCK: return WSAENOTSOCK; + case EDESTADDRREQ: return WSAEDESTADDRREQ; + case EMSGSIZE: return WSAEMSGSIZE; + case EPROTOTYPE: return WSAEPROTOTYPE; + case ENOPROTOOPT: return WSAENOPROTOOPT; + case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; + case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; + case EOPNOTSUPP: return WSAEOPNOTSUPP; + case EPFNOSUPPORT: return WSAEPFNOSUPPORT; + case EAFNOSUPPORT: return WSAEAFNOSUPPORT; + case EADDRINUSE: return WSAEADDRINUSE; + case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; + case ENETDOWN: return WSAENETDOWN; + case ENETUNREACH: return WSAENETUNREACH; + case ENETRESET: return WSAENETRESET; + case ECONNABORTED: return WSAECONNABORTED; + case ECONNRESET: return WSAECONNRESET; + case ENOBUFS: return WSAENOBUFS; + case EISCONN: return WSAEISCONN; + case ENOTCONN: return WSAENOTCONN; + case ESHUTDOWN: return WSAESHUTDOWN; + case ETOOMANYREFS: return WSAETOOMANYREFS; + case ETIMEDOUT: return WSAETIMEDOUT; + case ECONNREFUSED: return WSAECONNREFUSED; + case ELOOP: return WSAELOOP; + case ENAMETOOLONG: return WSAENAMETOOLONG; + case EHOSTDOWN: return WSAEHOSTDOWN; + case EHOSTUNREACH: return WSAEHOSTUNREACH; + case ENOTEMPTY: return WSAENOTEMPTY; +#ifdef EPROCLIM + case EPROCLIM: return WSAEPROCLIM; +#endif +#ifdef EUSERS + case EUSERS: return WSAEUSERS; +#endif +#ifdef EDQUOT + case EDQUOT: return WSAEDQUOT; +#endif + case ESTALE: return WSAESTALE; + case EREMOTE: return WSAEREMOTE; + + /* just in case we ever get here and there are no problems */ + case 0: return 0; + default: + fprintf(stderr, "winsock: unknown errno %d!\n", errno); + return WSAEOPNOTSUPP; + } +} + +UINT16 wsaHerrno(void) +{ + int loc_errno = h_errno; + +#if defined(__FreeBSD__) + dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", + h_errno, sys_errlist[h_errno]); +#else + dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno); +#ifndef sun + if( debugging_winsock ) herror("wine: winsock: wsaherrno"); +#endif +#endif + + switch(loc_errno) + { + case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND; + case TRY_AGAIN: return WSATRY_AGAIN; + case NO_RECOVERY: return WSANO_RECOVERY; + case NO_DATA: return WSANO_DATA; + + case 0: return 0; + default: + fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno); + return WSAEOPNOTSUPP; + } +} + + diff --git a/misc/winsock_async.c b/misc/winsock_async.c new file mode 100644 index 00000000000..6596b5fc322 --- /dev/null +++ b/misc/winsock_async.c @@ -0,0 +1,486 @@ +/* + * asynchronous winsock services + * + * (C) 1996 Alex Korobka. + * + * FIXME: telftp16 (ftp part) stalls on AsyncSelect with FD_ACCEPT. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windows.h" +#include "winsock.h" +#include "debug.h" + +#define __WS_ASYNC_DEBUG 0 + +static int _async_io_max_fd = 0; +static fd_set __async_io_fdset; +static ws_async_op* __async_op_list = NULL; + +extern ws_async_ctl async_ctl; +extern int async_qid; + +fd_set fd_read, fd_write, fd_excp; + +/* ----------------------------------- async/non-blocking I/O */ + +int WINSOCK_async_io(int fd, int async) +{ + int fd_flags; + + fcntl(fd, F_SETOWN, getpid()); + + fd_flags = fcntl(fd, F_GETFL, 0); + if (fcntl(fd, F_SETFL, (async)? fd_flags | FASYNC + : fd_flags & ~FASYNC ) != -1) return 0; + return -1; +} + +int WINSOCK_unblock_io(int fd, int noblock) +{ + int fd_flags; + + fd_flags = fcntl(fd, F_GETFL, 0); + if (fcntl(fd, F_SETFL, (noblock)? fd_flags | O_NONBLOCK + : fd_flags & ~O_NONBLOCK ) != -1) return 0; + return -1; +} + +int WINSOCK_check_async_op(ws_async_op* p_aop) +{ + ws_async_op* p = __async_op_list; + while( p ) if( p == p_aop ) return 1; + else p = p->next; + return 0; +} + +void WINSOCK_cancel_async_op(HTASK16 hTask) +{ + ws_async_op* p = __async_op_list; + while( p ) + if(hTask == GetWindowTask16(p->hWnd)) + p->flags = 0; +} + +void WINSOCK_link_async_op(ws_async_op* p_aop) +{ + if( __async_op_list ) __async_op_list->prev = p_aop; + else FD_ZERO(&__async_io_fdset); + + p_aop->next = __async_op_list; + p_aop->prev = NULL; + __async_op_list = p_aop; + + FD_SET(p_aop->fd[0], &__async_io_fdset); + if( p_aop->fd[0] > _async_io_max_fd ) + _async_io_max_fd = p_aop->fd[0]; +} + +void WINSOCK_unlink_async_op(ws_async_op* p_aop) +{ + if( p_aop == __async_op_list ) __async_op_list = p_aop->next; + else + { p_aop->prev->next = p_aop->next; + if( p_aop->next ) p_aop->next->prev = p_aop->prev; } + FD_CLR(p_aop->fd[0], &__async_io_fdset); + if( p_aop->fd[0] == _async_io_max_fd ) + _async_io_max_fd--; +} + +/* ----------------------------------- SIGIO handler - + * + * link_async_op/unlink_async_op allow to install generic + * async IO handlers (provided that aop_control function is defined). + * + * Note: AsyncGetXbyY expilicitly raise it. + */ + +void WINSOCK_sigio(int signal) +{ + struct timeval timeout; + fd_set check_set; + ws_async_op* p_aop; + + check_set = __async_io_fdset; + bzero(&timeout,sizeof(timeout)); + + while( select(_async_io_max_fd + 1, + &check_set, NULL, NULL, &timeout) > 0) + { + for( p_aop = __async_op_list; + p_aop ; p_aop = p_aop->next ) + if( FD_ISSET(p_aop->fd[0], &check_set) ) + if( p_aop->aop_control(p_aop, AOP_IO) == AOP_CONTROL_REMOVE ) + { + if( p_aop->pid ) + { + kill(p_aop->pid, SIGKILL); + waitpid(p_aop->pid, NULL, 0); + } + WINSOCK_unlink_async_op( p_aop ); + } + check_set = __async_io_fdset; + } +} + +/* ----------------------------------- child process IPC */ + +static void _sigusr1_handler_child(int sig) +{ + /* read message queue to decide which + * async_ctl parameters to update + * + * Note: we don't want to have SA_RESTART on this signal + * handler, otherwise select() won't notice changed fd sets. + */ + + signal( SIGUSR1, _sigusr1_handler_child ); + while( msgrcv(async_qid, (struct msgbuf*)&async_ctl.ip, + MTYPE_PARENT_SIZE, MTYPE_PARENT, IPC_NOWAIT) != -1 ) + { + /* only ip.lParam is updated */ +#if __WS_ASYNC_DEBUG + printf("handler - event %08x\n", async_ctl.ip.lParam ); +#endif + + switch( async_ctl.ip.lParam ) + { + /* These are events we are notified of. + */ + + case WS_FD_CONNECTED: async_ctl.lEvent &= ~WS_FD_CONNECT; + FD_SET(async_ctl.ws_sock->fd, &fd_read); + FD_SET(async_ctl.ws_sock->fd, &fd_write); + break; + + case WS_FD_ACCEPT: async_ctl.ws_sock->flags |= WS_FD_ACCEPT; + FD_SET(async_ctl.ws_sock->fd, &fd_read); + FD_SET(async_ctl.ws_sock->fd, &fd_write); + break; + case WS_FD_OOB: async_ctl.lEvent |= WS_FD_OOB; + FD_SET(async_ctl.ws_sock->fd, &fd_excp); + break; + case WS_FD_READ: async_ctl.lEvent |= WS_FD_READ; + FD_SET(async_ctl.ws_sock->fd, &fd_read); + break; + case WS_FD_WRITE: async_ctl.lEvent |= WS_FD_WRITE; + FD_SET(async_ctl.ws_sock->fd, &fd_write); + break; + default: + } + } +} + +static int notify_parent( unsigned flag ) +{ + if( flag & WSMSG_ASYNC_SELECT ) + { + async_ctl.ip.mtype = MTYPE_CLIENT; + while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip), + MTYPE_CLIENT_SIZE, 0) == -1 ) + { + if( errno == EINTR ) continue; + else if( errno == EIDRM ) _exit(0); + else + { + perror("AsyncSelect(child)"); + return 0; + } + } + kill(getppid(), SIGUSR1); + +#if __WS_ASYNC_DEBUG + printf("handler - notify [%08x]\n", async_ctl.ip.lParam); +#endif + } + else /* use half-duplex pipe to handle variable length packets */ + { + write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) ); + write(async_ctl.ws_aop->fd[1], async_ctl.buffer, async_ctl.lLength ); + kill(getppid(), SIGIO); /* simulate async I/O */ +#if __WS_ASYNC_DEBUG + printf("handler - notify aop [%d, buf %d]\n", async_ctl.lLength, async_ctl.ws_aop->buflen); +#endif + pause(); + } + return 1; +} + +/* ----------------------------------- async select */ + +static void setup_fd_sets() +{ + FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_excp); + + if( async_ctl.lEvent & WS_FD_OOB) + FD_SET(async_ctl.ws_sock->fd, &fd_excp); + if( async_ctl.lEvent & (WS_FD_ACCEPT | WS_FD_READ | + WS_FD_CONNECT | WS_FD_CLOSE) ) + FD_SET(async_ctl.ws_sock->fd, &fd_read); + if( async_ctl.lEvent & (WS_FD_WRITE | WS_FD_CONNECT) ) + FD_SET(async_ctl.ws_sock->fd, &fd_write); +} + +static void setup_sig_sets(sigset_t* sig_block) +{ + sigemptyset(sig_block); + sigaddset(sig_block, SIGUSR1); + sigprocmask( SIG_BLOCK, sig_block, NULL); + signal( SIGUSR1, _sigusr1_handler_child ); +} + +void WINSOCK_do_async_select() +{ + sigset_t sig_block; + int bytes; + + setup_sig_sets(&sig_block); + setup_fd_sets(); + + while(1) + { + int val; + + sigprocmask( SIG_UNBLOCK, &sig_block, NULL); + +#if __WS_ASYNC_DEBUG + printf("select(2)[%i,%i,%i]... ", + FD_ISSET(async_ctl.ws_sock->fd, &fd_read), + FD_ISSET(async_ctl.ws_sock->fd, &fd_write), + FD_ISSET(async_ctl.ws_sock->fd, &fd_excp)); +#endif + if( (val = select(async_ctl.ws_sock->fd + 1, + &fd_read, &fd_write, &fd_excp, NULL)) == -1 ) + if( errno == EINTR ) continue; +#if __WS_ASYNC_DEBUG + printf("got %i events\n", val); +#endif + +#if __WS_ASYNC_DEBUG + if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) ) + printf("handler - read is READY! [%08x]\n", async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE)); +#endif + + sigprocmask( SIG_BLOCK, &sig_block, NULL); + async_ctl.ip.lParam = 0; + if( async_ctl.ws_sock->flags & WS_FD_ACCEPT ) + { + /* listening socket */ + + FD_CLR(async_ctl.ws_sock->fd, &fd_read); + FD_CLR(async_ctl.ws_sock->fd, &fd_write); + + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 ); + notify_parent( WSMSG_ASYNC_SELECT ); + continue; + } + else /* I/O socket */ + { + if( async_ctl.lEvent & WS_FD_CONNECT ) + { + if( FD_ISSET(async_ctl.ws_sock->fd, &fd_write) ) + { + /* success - reinit fd sets to start I/O */ + + if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE)) + FD_SET(async_ctl.ws_sock->fd, &fd_read); + else FD_CLR(async_ctl.ws_sock->fd, &fd_read); + if( async_ctl.lEvent & WS_FD_WRITE ) + FD_SET(async_ctl.ws_sock->fd, &fd_write); + else FD_CLR(async_ctl.ws_sock->fd, &fd_write); + + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 ); + async_ctl.lEvent &= ~WS_FD_CONNECT; /* one-shot */ + } + else if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) ) + { + /* failure - do read() to get correct errno */ + + if( read(async_ctl.ws_sock->fd, &bytes, 4) == -1 ) + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() ); + else continue; + } else continue; /* OOB?? */ + + notify_parent( WSMSG_ASYNC_SELECT ); + } + else /* connected socket */ + { + + if( async_ctl.lEvent & WS_FD_OOB ) + if( FD_ISSET(async_ctl.ws_sock->fd, &fd_excp) ) + { + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_OOB, 0 ); + async_ctl.lEvent &= ~WS_FD_OOB; + FD_CLR(async_ctl.ws_sock->fd, &fd_excp); + notify_parent( WSMSG_ASYNC_SELECT ); + } + else FD_SET(async_ctl.ws_sock->fd, &fd_excp); + + if( async_ctl.lEvent & WS_FD_WRITE ) + if( FD_ISSET( async_ctl.ws_sock->fd, &fd_write ) ) + { + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_WRITE, 0 ); + async_ctl.lEvent &= ~WS_FD_WRITE; + FD_CLR(async_ctl.ws_sock->fd, &fd_write); + notify_parent( WSMSG_ASYNC_SELECT ); + } + else FD_SET(async_ctl.ws_sock->fd, &fd_write); + + if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE) ) + if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) ) + { + if( ioctl( async_ctl.ws_sock->fd, FIONREAD, (char*)&bytes) != -1 ) + { + if( bytes ) /* got data */ + { +#if __WS_ASYNC_DEBUG + printf("\t%i bytes pending\n", bytes ); +#endif + if( async_ctl.lEvent & WS_FD_READ ) + { + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, 0 ); + async_ctl.lEvent &= ~WS_FD_READ; + if( !(async_ctl.lEvent & WS_FD_CLOSE) ) + FD_CLR( async_ctl.ws_sock->fd, &fd_read ); + } + else if( !(async_ctl.lEvent & (WS_FD_WRITE | WS_FD_OOB)) ) + { + sigprocmask( SIG_UNBLOCK, &sig_block, NULL); + pause(); + sigprocmask( SIG_BLOCK, &sig_block, NULL); + } + else continue; + } + else /* 0 bytes to read */ + { + val = read( async_ctl.ws_sock->fd, (char*)&bytes, 4); + if( errno == EWOULDBLOCK || errno == EINTR ) + { +#if __WS_ASYNC_DEBUG + printf("\twould block..\n"); +#endif + continue; + } + switch( val ) + { + case 0: errno = ENETDOWN; /* ENETDOWN */ + case -1: /* ECONNRESET */ + async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() ); + break; + default: continue; + } + async_ctl.lEvent &= ~(WS_FD_CLOSE | WS_FD_READ); /* one-shot */ + FD_ZERO(&fd_read); FD_ZERO(&fd_write); + } + } + else async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() ); + + notify_parent( WSMSG_ASYNC_SELECT ); + } + else FD_SET(async_ctl.ws_sock->fd, &fd_read); + + } /* connected socket */ + } /* I/O socket */ + } /* while */ +} + + +/* ----------------------------------- getXbyY requests */ + +static void _async_fail() +{ + async_ctl.lLength = + (h_errno < 0) ? (unsigned)WSAMAKEASYNCREPLY( 0, wsaErrno() ) + : (unsigned)WSAMAKEASYNCREPLY( 0, wsaHerrno() ); + write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) ); + kill(getppid(), SIGIO); /* simulate async I/O */ + pause(); +} + +void dump_ws_hostent_offset(struct ws_hostent* wshe) +{ + int i; + char* base = (char*)wshe; + unsigned* ptr; + + printf("h_name = %08x\t[%s]\n", (unsigned)wshe->h_name, base + (unsigned)wshe->h_name); + printf("h_aliases = %08x\t[%08x]\n", (unsigned)wshe->h_aliases, + (unsigned)(base + (unsigned)wshe->h_aliases)); + ptr = (unsigned*)(base + (unsigned)wshe->h_aliases); + for(i = 0; ptr[i]; i++ ) + { + printf("%i - %08x ", i + 1, ptr[i]); + printf(" [%s]\n", ((char*)base) + ptr[i]); + } + printf("h_length = %i\n", wshe->h_length); +} + +void WS_do_async_gethost(LPWSINFO pwsi, unsigned flag ) +{ + int size = 0; + struct hostent* p_he; + + close(async_ctl.ws_aop->fd[0]); + p_he = (flag & WSMSG_ASYNC_HOSTBYNAME) + ? gethostbyname(async_ctl.ws_aop->init) + : gethostbyaddr(async_ctl.ws_aop->init, + async_ctl.lLength, async_ctl.lEvent); + if( p_he ) size = WS_dup_he(pwsi, p_he, WS_DUP_SEGPTR | WS_DUP_OFFSET ); + if( size ) + { + async_ctl.buffer = pwsi->buffer; + async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 ); + notify_parent( flag ); + } + else _async_fail(); + _exit(0); +} + +void WS_do_async_getproto(LPWSINFO pwsi, unsigned flag ) +{ + int size = 0; + struct protoent* p_pe; + + close(async_ctl.ws_aop->fd[0]); + p_pe = (flag & WSMSG_ASYNC_PROTOBYNAME) + ? getprotobyname(async_ctl.ws_aop->init) + : getprotobynumber(async_ctl.lEvent); + if( p_pe ) size = WS_dup_pe(pwsi, p_pe, WS_DUP_SEGPTR | WS_DUP_OFFSET ); + if( size ) + { + async_ctl.buffer = pwsi->buffer; + async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 ); + notify_parent( flag ); + } + else _async_fail(); + _exit(0); +} + +void WS_do_async_getserv(LPWSINFO pwsi, unsigned flag ) +{ + int size = 0; + struct servent* p_se; + + close(async_ctl.ws_aop->fd[0]); + p_se = (flag & WSMSG_ASYNC_SERVBYNAME) + ? getservbyname(async_ctl.ws_aop->init, async_ctl.buffer) + : getservbyport(async_ctl.lEvent, async_ctl.ws_aop->init); + if( p_se ) size = WS_dup_se(pwsi, p_se, WS_DUP_SEGPTR | WS_DUP_OFFSET ); + if( size ) + { + async_ctl.buffer = pwsi->buffer; + async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 ); + notify_parent( flag ); + } + else _async_fail(); + _exit(0); +} + diff --git a/misc/winsocket.c b/misc/winsocket.c deleted file mode 100644 index 1507a5ed964..00000000000 --- a/misc/winsocket.c +++ /dev/null @@ -1,1697 +0,0 @@ -/* - * based on Windows Sockets 1.1 specs - * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT) - * - * (C) 1993,1994 John Brezak, Erik Bos. - */ - -#include -#include -#include -#include -#include -#include -#if defined(__svr4__) -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#include "winsock.h" -#include "global.h" -#include "stddebug.h" -#include "debug.h" - -#ifdef _SCO_DS -#define _IOR _IOSR -#define _IOW _IOSW -#endif - -static WORD wsa_errno; -static int wsa_initted; -static key_t wine_key = 0; -static FARPROC16 BlockFunction; -static fd_set fd_in_use; - -extern int h_errno; - -struct ipc_packet { - long mtype; - HANDLE16 handle; - HWND hWnd; - WORD wMsg; - LONG lParam; -}; - -#ifndef WINELIB -#pragma pack(1) -#endif - -#define WINSOCK_MAX_SOCKETS 256 -#define WINSOCK_MAX_UDPDG 1024 - -/* we are out by two with the following, is it due to byte alignment? - * #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long)) - */ -#define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long) - 2) -/*#define MTYPE 0xb0b0eb05*/ -#define MTYPE 0x30b0eb05 - -/* These structures are Win16 only */ - -struct WIN_hostent { - SEGPTR h_name WINE_PACKED; /* official name of host */ - SEGPTR h_aliases WINE_PACKED; /* alias list */ - INT h_addrtype WINE_PACKED; /* host address type */ - INT h_length WINE_PACKED; /* length of address */ - char **h_addr_list WINE_PACKED; /* list of addresses from name server */ - char *names[2]; - char hostname[200]; -}; - -struct WIN_protoent { - SEGPTR p_name WINE_PACKED; /* official protocol name */ - SEGPTR p_aliases WINE_PACKED; /* alias list */ - INT p_proto WINE_PACKED; /* protocol # */ -}; - -struct WIN_servent { - SEGPTR s_name WINE_PACKED; /* official service name */ - SEGPTR s_aliases WINE_PACKED; /* alias list */ - INT s_port WINE_PACKED; /* port # */ - SEGPTR s_proto WINE_PACKED; /* protocol to use */ -}; - -typedef struct WinSock_fd_set { - u_short fd_count; /* how many are SET? */ - SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */ -} WinSock_fd_set; - -struct WinSockHeap { - char ntoa_buffer[32]; - - struct WIN_hostent hostent_addr; - struct WIN_hostent hostent_name; - struct WIN_protoent protoent_name; - struct WIN_protoent protoent_number; - struct WIN_servent servent_name; - struct WIN_servent servent_port; - - struct WIN_hostent WSAhostent_addr; - struct WIN_hostent WSAhostent_name; - struct WIN_protoent WSAprotoent_name; - struct WIN_protoent WSAprotoent_number; - struct WIN_servent WSAservent_name; - struct WIN_servent WSAservent_port; - /* 8K scratch buffer for aliases and friends are hopefully enough */ - char scratch[8192]; -}; -static struct WinSockHeap *Heap; -static HGLOBAL16 HeapHandle; -#ifndef WINELIB32 -static int ScratchPtr; -#endif - -#ifndef WINELIB -#define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \ - GlobalHandleToSel(HeapHandle)) -#else -#define GET_SEG_PTR(x) ((SEGPTR)x) -#endif - -#ifndef WINELIB -#pragma pack(4) -#endif - -#define dump_sockaddr(a) \ - fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \ - ((struct sockaddr_in *)a)->sin_family, \ - inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \ - ntohs(((struct sockaddr_in *)a)->sin_port)) - -#ifndef WINELIB32 -static void ResetScratch() -{ - ScratchPtr=0; -} - -static void *scratch_alloc(int size) -{ - char *ret; - if(ScratchPtr+size > sizeof(Heap->scratch)) - return 0; - ret = Heap->scratch + ScratchPtr; - ScratchPtr += size; - return ret; -} - -static SEGPTR scratch_strdup(char * s) -{ - char *ret=scratch_alloc(strlen(s)+1); - strcpy(ret,s); - return GET_SEG_PTR(ret); -} -#endif - -static WORD wsaerrno(void) -{ -#ifdef DEBUG_WINSOCK -#ifndef sun -#if defined(__FreeBSD__) - fprintf(stderr, "winsock: errno %d, (%s).\n", - errno, sys_errlist[errno]); -#else - fprintf(stderr, "winsock: errno %d\n", errno); -#endif -#else - fprintf(stderr, "winsock: errno %d\n", errno); -#endif -#endif - - switch(errno) - { - case EINTR: return WSAEINTR; - case EBADF: return WSAEBADF; - case EACCES: return WSAEACCES; - case EFAULT: return WSAEFAULT; - case EINVAL: return WSAEINVAL; - case EMFILE: return WSAEMFILE; - case EWOULDBLOCK: return WSAEWOULDBLOCK; - case EINPROGRESS: return WSAEINPROGRESS; - case EALREADY: return WSAEALREADY; - case ENOTSOCK: return WSAENOTSOCK; - case EDESTADDRREQ: return WSAEDESTADDRREQ; - case EMSGSIZE: return WSAEMSGSIZE; - case EPROTOTYPE: return WSAEPROTOTYPE; - case ENOPROTOOPT: return WSAENOPROTOOPT; - case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; - case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; - case EOPNOTSUPP: return WSAEOPNOTSUPP; - case EPFNOSUPPORT: return WSAEPFNOSUPPORT; - case EAFNOSUPPORT: return WSAEAFNOSUPPORT; - case EADDRINUSE: return WSAEADDRINUSE; - case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; - case ENETDOWN: return WSAENETDOWN; - case ENETUNREACH: return WSAENETUNREACH; - case ENETRESET: return WSAENETRESET; - case ECONNABORTED: return WSAECONNABORTED; - case ECONNRESET: return WSAECONNRESET; - case ENOBUFS: return WSAENOBUFS; - case EISCONN: return WSAEISCONN; - case ENOTCONN: return WSAENOTCONN; - case ESHUTDOWN: return WSAESHUTDOWN; - case ETOOMANYREFS: return WSAETOOMANYREFS; - case ETIMEDOUT: return WSAETIMEDOUT; - case ECONNREFUSED: return WSAECONNREFUSED; - case ELOOP: return WSAELOOP; - case ENAMETOOLONG: return WSAENAMETOOLONG; - case EHOSTDOWN: return WSAEHOSTDOWN; - case EHOSTUNREACH: return WSAEHOSTUNREACH; - case ENOTEMPTY: return WSAENOTEMPTY; -#ifdef EPROCLIM - case EPROCLIM: return WSAEPROCLIM; -#endif -#ifdef EUSERS - case EUSERS: return WSAEUSERS; -#endif -#ifdef EDQUOT - case EDQUOT: return WSAEDQUOT; -#endif - case ESTALE: return WSAESTALE; - case EREMOTE: return WSAEREMOTE; -/* just in case we ever get here and there are no problems */ - case 0: return 0; - - default: - fprintf(stderr, "winsock: unknown errorno %d!\n", errno); - return WSAEOPNOTSUPP; - } -} - -static void errno_to_wsaerrno(void) -{ - wsa_errno = wsaerrno(); -} - - -static WORD wsaherrno(void) -{ -#if DEBUG_WINSOCK -#ifndef sun -#if defined(__FreeBSD__) - fprintf(stderr, "winsock: h_errno %d, (%s).\n", - h_errno, sys_errlist[h_errno]); -#else - fprintf(stderr, "winsock: h_errno %d.\n", h_errno); - herror("wine: winsock: wsaherrno"); -#endif -#else - fprintf(stderr, "winsock: h_errno %d\n", h_errno); -#endif -#endif - - switch(h_errno) - { - case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND; - case TRY_AGAIN: return WSATRY_AGAIN; - case NO_RECOVERY: return WSANO_RECOVERY; - case NO_DATA: return WSANO_DATA; -/* just in case we ever get here and there are no problems */ - case 0: return 0; - - - default: - fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno); - return WSAEOPNOTSUPP; - } -} - - -static void herrno_to_wsaerrno(void) -{ - wsa_errno = wsaherrno(); -} - - -static void convert_sockopt(INT *level, INT *optname) -{ -/* $%#%!#! why couldn't they use the same values for both winsock and unix ? */ - - switch (*level) { - case -1: - *level = SOL_SOCKET; - switch (*optname) { - case 0x01: *optname = SO_DEBUG; - break; - case 0x04: *optname = SO_REUSEADDR; - break; - case 0x08: *optname = SO_KEEPALIVE; - break; - case 0x10: *optname = SO_DONTROUTE; - break; - case 0x20: *optname = SO_BROADCAST; - break; - case 0x80: *optname = SO_LINGER; - break; - case 0x100: *optname = SO_OOBINLINE; - break; - case 0x1001: *optname = SO_SNDBUF; - break; - case 0x1002: *optname = SO_RCVBUF; - break; - case 0x1007: *optname = SO_ERROR; - break; - case 0x1008: *optname = SO_TYPE; - break; - default: - fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname); - break; - } - break; - case 6: *optname = IPPROTO_TCP; - } -} - -#ifndef WINELIB -static SEGPTR copy_stringlist(char **list) -{ - SEGPTR *s_list; - int i; - for(i=0;list[i];i++) - ; - s_list = scratch_alloc(sizeof(SEGPTR)*(i+1)); - for(i=0;list[i];i++) - { - void *copy = scratch_alloc(strlen(list[i])+1); - strcpy(copy,list[i]); - s_list[i]=GET_SEG_PTR(copy); - } - s_list[i]=0; - return GET_SEG_PTR(s_list); -} - - -static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host) -{ - SEGPTR *addr_list; - int i; - ResetScratch(); - strcpy(heapent->hostname,host->h_name); - heapent->h_name = GET_SEG_PTR(heapent->hostname); - /* Convert aliases. Have to create array with FAR pointers */ - if(!host->h_aliases) - heapent->h_aliases = 0; - else - heapent->h_aliases = copy_stringlist(host->h_aliases); - - heapent->h_addrtype = host->h_addrtype; - heapent->h_length = host->h_length; - for(i=0;host->h_addr_list[i];i++) - ; - addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1)); - heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list); - for(i=0;host->h_addr_list[i];i++) - { - void *addr=scratch_alloc(host->h_length); - memcpy(addr,host->h_addr_list[i],host->h_length); - addr_list[i]=GET_SEG_PTR(addr); - } - addr_list[i]=0; -} - -static void CONVERT_PROTOENT(struct WIN_protoent *heapent, - struct protoent *proto) -{ - ResetScratch(); - heapent->p_name= scratch_strdup(proto->p_name); - heapent->p_aliases=proto->p_aliases ? - copy_stringlist(proto->p_aliases) : 0; - heapent->p_proto = proto->p_proto; -} - -static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv) -{ - ResetScratch(); - heapent->s_name = scratch_strdup(serv->s_name); - heapent->s_aliases = serv->s_aliases ? - copy_stringlist(serv->s_aliases) : 0; - heapent->s_port = serv->s_port; - heapent->s_proto = scratch_strdup(serv->s_proto); -} -#else -#define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a)) -#define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a)) -#define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a)) -#endif - -SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen) -{ - int sock; - - dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return INVALID_SOCKET; - } - - if ((sock = accept(s, addr, (int *) addrlen)) < 0) { - errno_to_wsaerrno(); - return INVALID_SOCKET; - } - return sock; -} - -INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen) -{ - - dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); - dump_sockaddr(name); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (namelen < sizeof(*name)) { - WSASetLastError(WSAEFAULT); - return SOCKET_ERROR; - } - - /* check the socket family */ - if ( ((struct sockaddr_in *)name)->sin_family != AF_INET ) { - WSASetLastError(WSAEAFNOSUPPORT); - return SOCKET_ERROR; - } - - if (bind(s, name, namelen) < 0) { - switch(errno) { - case EBADF: - WSASetLastError(WSAENOTSOCK); - break; - case EADDRNOTAVAIL: - WSASetLastError(WSAEINVAL); - break; - default: - errno_to_wsaerrno(); - break; - } - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_closesocket(SOCKET s) -{ - dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - FD_CLR(s, &fd_in_use); - - if (close(s) < 0) { - if (errno == EBADF) - WSASetLastError(WSAENOTSOCK); - else - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen) -{ - dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); - dump_sockaddr(name); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (connect(s, name, namelen) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen) -{ - dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen); - dump_sockaddr(name); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (getpeername(s, name, (int *) namelen) < 0) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen) -{ - dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (getsockname(s, name, (int *) namelen) < 0) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return SOCKET_ERROR; - } - return 0; -} - -INT -WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen) -{ - dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - convert_sockopt(&level, &optname); - - if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) { - if (errno == EBADF) - WSASetLastError(WSAENOTSOCK); - else - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -u_long WINSOCK_htonl(u_long hostlong) -{ - return( htonl(hostlong) ); -} - -u_short WINSOCK_htons(u_short hostshort) -{ - return( htons(hostshort) ); -} - -u_long WINSOCK_inet_addr(char *cp) -{ - return( inet_addr(cp) ); -} - -char *WINSOCK_inet_ntoa(struct in_addr in) -{ - char *s; - -/* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/ - - if ((s = inet_ntoa(in)) == NULL) { - errno_to_wsaerrno(); - return NULL; - } - - strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) ); - - return (char *) GET_SEG_PTR(&Heap->ntoa_buffer); -} - -INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp) -{ - long newcmd; - u_long *newargp; - char *ctlname; - dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - /* Why can't they all use the same ioctl numbers */ - newcmd=cmd; - newargp=argp; - ctlname=0; - if(cmd == _IOR('f',127,u_long)) - { - ctlname="FIONREAD"; - newcmd=FIONREAD; - }else - if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long)) - { - ctlname="FIONBIO"; - newcmd=FIONBIO; - }else - if(cmd == _IOW('f',125,u_long)) - { - ctlname="FIOASYNC"; - newcmd=FIOASYNC; - } - - if(!ctlname) - fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n"); - else - dprintf_winsock(stddeb,"Recognized as %s\n", ctlname); - - - if (ioctl(s, newcmd, newargp) < 0) { - if (errno == EBADF) - WSASetLastError(WSAENOTSOCK); - else - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_listen(SOCKET s, INT backlog) -{ - dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (listen(s, backlog) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -u_long WINSOCK_ntohl(u_long netlong) -{ - return( ntohl(netlong) ); -} - -u_short WINSOCK_ntohs(u_short netshort) -{ - return( ntohs(netshort) ); -} - -INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags) -{ - int length; - - dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if ((length = recv(s, buf, len, flags)) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return length; -} - -INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *from, int *fromlen) -{ - int length; - - dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return length; -} - -INT WINSOCK_select(INT nfds, WinSock_fd_set *ws_readfds, - WinSock_fd_set *ws_writefds, WinSock_fd_set *ws_exceptfds, - struct timeval *timeout) -{ - int ret; - int i; - int count; - int highfd; - fd_set readfds,writefds,exceptfds; - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - - dprintf_winsock(stddeb, "WSA_select called: nfds %d (ignored), ptr %8lx, ptr %8lx, ptr %8lx\n", nfds, (unsigned long) ws_readfds, (unsigned long) ws_writefds, (unsigned long) ws_exceptfds); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - dprintf_winsock(stddeb, "WSA_select: returning error WSANOTINITIALISED\n"); - return SOCKET_ERROR; - } - -/* In some sort of attempt to be BSD-compatible, MS-Winsock accepts and - discards the nfds parameter. However, the format of windoze's fd_sets - is totally different from the BSD standard. So much for compatibility. - Hence, we must convert the winsock array-of-ints fd_set to the UNIX - bitmapped format. */ - - if(ws_readfds!=NULL) { - dprintf_winsock(stddeb, "readfds: (%d) ",ws_readfds->fd_count); - for(i=0;i<(ws_readfds->fd_count);i++) { - dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_readfds)[2]) )[i]); - /*FD_SET(((SOCKET *)&(((char *)ws_readfds)[2]))[i], &readfds);*/ - FD_SET(ws_readfds->fd_array[i], &readfds); - } - dprintf_winsock(stddeb, "\n"); - } else { - dprintf_winsock(stddeb, "readfds: (null)\n"); - } - if(ws_writefds!=NULL) { - dprintf_winsock(stddeb, "writefds: (%d) ",ws_writefds->fd_count); - for(i=0;i<(ws_writefds->fd_count);i++) { - dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_writefds)[2]) )[i]); - /*FD_SET(((SOCKET *)&(((char *)ws_writefds)[2]))[i], &writefds);*/ - FD_SET(ws_writefds->fd_array[i], &writefds); - } - dprintf_winsock(stddeb, "\n"); - } else { - dprintf_winsock(stddeb, "writefds: (null)\n"); - } - if(ws_exceptfds!=NULL) { - dprintf_winsock(stddeb, "exceptfds: (%d) ",ws_exceptfds->fd_count); - for(i=0;i<(ws_exceptfds->fd_count);i++) { - dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_exceptfds)[2]) )[i]); - /*FD_SET(((SOCKET *)&(((char *)ws_exceptfds)[2]))[i], &exceptfds);*/ - FD_SET(ws_exceptfds->fd_array[i], &exceptfds); - } - dprintf_winsock(stddeb, "\n"); - } else { - dprintf_winsock(stddeb, "exceptfds: (null)\n"); - } - - /* Make the select() call */ - dprintf_winsock(stddeb, "WSA_select: calling select()\n"); - highfd=256; /* We should count them, but this works */ - ret=select(highfd, &readfds, &writefds, &exceptfds, timeout); - dprintf_winsock(stddeb, "WSA_select: select() returned %d\n",ret); - if(ret<0) { - errno_to_wsaerrno(); - dprintf_winsock(stddeb, "WSA_select returning: Error %d\n",SOCKET_ERROR); - return SOCKET_ERROR; - } - - /* update the winsock fd sets */ - if(ws_readfds!=NULL) { - dprintf_winsock(stddeb, "readfds: "); - count=0; - for(i=0;ifd_array[count++]=i; - } - } - dprintf_winsock(stddeb, " (%d)\n",count); - ws_readfds->fd_count=count; - } else { - dprintf_winsock(stddeb, "readfds: (null)\n"); - } - if(ws_writefds!=NULL) { - dprintf_winsock(stddeb, "writefds: "); - count=0; - for(i=0;ifd_array[count++]=i; - } - } - dprintf_winsock(stddeb, " (%d)\n",count); - ws_writefds->fd_count=count; - } else { - dprintf_winsock(stddeb, "writefds: (null)\n"); - } - if(ws_exceptfds!=NULL) { - dprintf_winsock(stddeb, "exceptfds: "); - count=0; - for(i=0;ifd_array[count++]=i; - } - } - dprintf_winsock(stddeb, " (%d)\n",count); - ws_exceptfds->fd_count=count; - } else { - dprintf_winsock(stddeb, "exceptfds: (null)\n"); - } - - dprintf_winsock(stddeb, "WSA_select returning: %d\n",ret); - return(ret); -} - -INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags) -{ - int length; - - dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if ((length = send(s, buf, len, flags)) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return length; -} - -INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *to, INT tolen) -{ - int length; - - dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return length; -} - -INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval, - INT optlen) -{ - dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen); - convert_sockopt(&level, &optname); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (setsockopt(s, level, optname, optval, optlen) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -INT WINSOCK_shutdown(SOCKET s, INT how) -{ - dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (shutdown(s, how) < 0) { - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -SOCKET WINSOCK_socket(INT af, INT type, INT protocol) -{ - int sock; - - dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return INVALID_SOCKET; - } - - /* check the socket family */ - switch(af) { - case AF_INET: - case AF_UNSPEC: - break; - default: - WSASetLastError(WSAEAFNOSUPPORT); - return INVALID_SOCKET; - break; - } - - /* check the socket type */ - switch(type) { - case SOCK_STREAM: - case SOCK_DGRAM: - case SOCK_RAW: - break; - default: - WSASetLastError(WSAESOCKTNOSUPPORT); - return INVALID_SOCKET; - break; - } - - /* check the protocol type */ - if ( protocol < 0 ) { /* don't support negative values */ - WSASetLastError(WSAEPROTONOSUPPORT); - return INVALID_SOCKET; - } - - if ( af == AF_UNSPEC) { /* did they not specify the address family? */ - switch(protocol) { - case IPPROTO_TCP: - if (type == SOCK_STREAM) { - af = AF_INET; - break; - } - case IPPROTO_UDP: - if (type == SOCK_DGRAM) { - af = AF_INET; - break; - } - default: - WSASetLastError(WSAEPROTOTYPE); - return INVALID_SOCKET; - break; - } - } - - if ((sock = socket(af, type, protocol)) < 0) { - if (errno == EPERM) { - /* non super-user wants a raw socket */ - fprintf(stderr, "WSA_socket: not enough privileges\n"); - WSASetLastError(WSAESOCKTNOSUPPORT); - } else - errno_to_wsaerrno(); - dprintf_winsock(stddeb, "WSA_socket: failed !\n"); - return INVALID_SOCKET; - } - - if (sock > WINSOCK_MAX_SOCKETS) { - /* we only support socket numbers up to WINSOCK_MAX_SOCKETS. - * The return value indicates no more descriptors are available - */ - WSASetLastError(WSAEMFILE); - return INVALID_SOCKET; - } - - FD_SET(sock, &fd_in_use); - - dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock); - return sock; -} - -/* -struct WIN_hostent * -*/ -SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type) -{ - struct hostent *host; - - dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((host = gethostbyaddr(addr, len, type)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return NULL; - } - CONVERT_HOSTENT(&Heap->hostent_addr, host); - - return GET_SEG_PTR(&Heap->hostent_addr); -} - -/* -struct WIN_hostent * -*/ -SEGPTR WINSOCK_gethostbyname(const char *name) -{ - struct hostent *host; - - dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((host = gethostbyname(name)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return NULL; - } - CONVERT_HOSTENT(&Heap->hostent_name, host); - - return GET_SEG_PTR(&Heap->hostent_name); -} - -INT WINSOCK_gethostname(char *name, INT namelen) -{ - dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (gethostname(name, namelen) < 0) { - if (errno == EINVAL) - WSASetLastError(WSAEFAULT); - else - errno_to_wsaerrno(); - return SOCKET_ERROR; - } - return 0; -} - -/* -struct WIN_protoent * -*/ -SEGPTR WINSOCK_getprotobyname(char *name) -{ - struct protoent *proto; - - dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((proto = getprotobyname(name)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return NULL; - } - CONVERT_PROTOENT(&Heap->protoent_name, proto); - - return GET_SEG_PTR(&Heap->protoent_name); -} - -/* -struct WIN_protoent * -*/ -SEGPTR WINSOCK_getprotobynumber(INT number) -{ - struct protoent *proto; - - dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((proto = getprotobynumber(number)) == NULL) { -#if 0 - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } -#endif - WSASetLastError(WSANO_DATA); - return NULL; - } - CONVERT_PROTOENT(&Heap->protoent_number, proto); - - return GET_SEG_PTR(&Heap->protoent_number); -} - -/* -struct WIN_servent * -*/ -SEGPTR WINSOCK_getservbyname(const char *name, const char *proto) -{ - struct servent *service; - - if (proto == NULL) - proto = "tcp"; - - dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((service = getservbyname(name, proto)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return NULL; - } - CONVERT_SERVENT(&Heap->servent_name, service); - - return GET_SEG_PTR(&Heap->servent_name); -} - -/* -struct WIN_servent * -*/ -SEGPTR WINSOCK_getservbyport(INT port, const char *proto) -{ - struct servent *service; - - dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - if ((service = getservbyport(port, proto)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - return NULL; - } - CONVERT_SERVENT(&Heap->servent_port, service); - - return GET_SEG_PTR(&Heap->servent_port); -} - -/******************** winsock specific functions ************************ - * - */ -static HANDLE16 new_handle = 1; - -static HANDLE16 AllocWSAHandle(void) -{ - return new_handle++; -} - -static void recv_message(int sig) -{ - static struct ipc_packet message; - int message_is_valid = 0; - BOOL result; - - message.mtype = MTYPE; - - signal(SIGUSR1, recv_message); - while (1) { - - if (!message_is_valid) { - if (msgrcv(wine_key, (struct msgbuf*)&(message), - IPC_PACKET_SIZE, 0 /*MTYPE*/, IPC_NOWAIT) == -1) { - perror("wine: winsock: msgrcv"); - break; - } - } - - result = PostMessage(message.hWnd, message.wMsg, - (WPARAM16)message.handle, message.lParam); - if (result != FALSE) { - message_is_valid = 1; - break; - } - else - message_is_valid = 0; - - } - - if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1) - perror("wine: winsock: msgget"); -} - - -static void send_message( HWND hWnd, u_int wMsg, HANDLE16 handle, long lParam) -{ - struct ipc_packet message; - - message.mtype = MTYPE; - message.handle = handle; - message.hWnd = hWnd; - message.wMsg = wMsg; - message.lParam = lParam; - - if (msgsnd(wine_key, (struct msgbuf*)&(message), - IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1) - perror("wine: winsock: msgsnd"); - - kill(getppid(), SIGUSR1); -} - - -HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr, - INT len, INT type, LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct hostent *host; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((host = gethostbyaddr(addr, len, type)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, host, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - - -HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, LPCSTR name, - LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct hostent *host; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((host = gethostbyname(name)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, host, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - - -HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, LPCSTR name, - LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct protoent *proto; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((proto = getprotobyname(name)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, proto, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - - -HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, - LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct protoent *proto; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((proto = getprotobynumber(number)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, proto, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - - -HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg, LPCSTR name, - LPCSTR proto, LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct servent *service; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((service = getservbyname(name, proto)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, service, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - - -HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, LPCSTR proto, - LPSTR buf, INT buflen) -{ - HANDLE16 handle; - struct servent *service; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return 0; - } - - handle = AllocWSAHandle(); - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return handle; - } else { - if ((service = getservbyport(port, proto)) == NULL) { - if (h_errno < 0) { - errno_to_wsaerrno(); - } else { - herrno_to_wsaerrno(); - } - send_message(hWnd, wMsg, handle, wsaerrno() << 16); - exit(0); - } - memcpy(buf, service, buflen); - send_message(hWnd, wMsg, handle, 0); - exit(0); - } -} - -INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent) -{ - long event; - fd_set read_fds, write_fds, except_fds; - int errors = 0; - int newpid; - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %04x, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent); - - /* remove outstanding asyncselect() processes */ - /* kill */ - - if (wMsg == 0 && lEvent == 0) - return 0; - - newpid = fork(); - if (newpid) { - dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid); - return 0; - } else { - while (1) { - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - FD_ZERO(&except_fds); - - if (lEvent & FD_READ) - FD_SET(s, &read_fds); - if (lEvent & FD_WRITE) - FD_SET(s, &write_fds); - - fcntl(s, F_SETFL, O_NONBLOCK); - if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) { - errors = wsaerrno(); - } - - event = 0; - if (FD_ISSET(s, &read_fds)) - event |= FD_READ; - if (FD_ISSET(s, &write_fds)) - event |= FD_WRITE; - send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors)); - } - } -} - -INT WSAFDIsSet(SOCKET fd, WinSock_fd_set *set) -{ - int i = set->fd_count; - - dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set); - - while (i--) - { - if (set->fd_array[i] == fd) - { - dprintf_winsock(stddeb, "__WSAFDIsSet returning 1\n"); - return 1; - } - } - dprintf_winsock(stddeb, "__WSAFDIsSet returning 0\n"); - return 0; -} - -INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle) -{ - dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %04x\n", hAsyncTaskHandle); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - return 0; -} - -INT WSACancelBlockingCall(void) -{ - dprintf_winsock(stddeb, "WSA_CancelBlockCall\n"); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - return 0; -} - -INT WSAGetLastError(void) -{ - dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno); - - return wsa_errno; -} - -void WSASetLastError(INT iError) -{ - dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError); - - /* technically, we should make sure that WINESockets - * has been started up correctly. But since this function - * is also used internally, it makes no sense. - * - *if (!wsa_initted) { - * WSASetLastError(WSANOTINITIALISED); - * return SOCKET_ERROR; - *} - */ - - wsa_errno = iError; -} - -BOOL WSAIsBlocking(void) -{ - dprintf_winsock(stddeb, "WSA_IsBlocking\n"); - - return 0; -} - -FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc) -{ - dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - BlockFunction = lpBlockFunc; - - return (FARPROC16) lpBlockFunc; -} - -INT WSAUnhookBlockingHook(void) -{ - dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n"); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return NULL; - } - - BlockFunction = NULL; - - return 0; -} - -#ifdef 0 -WSADATA WINSOCK_data = { - 0x0101, - 0x0101, - "WINE Sockets", -#ifdef linux - "LINUX/i386", -#elif defined(__NetBSD__) - "NetBSD/i386", -#elif defined(sunos) - "SunOS", -#elif defined(__FreeBSD__) - "FreeBSD", -#else - "Unknown", -#endif - WINSOCK_MAX_SOCKETS, - WINSOCK_MAX_UDPDG, - NULL -}; -#endif - -INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) -{ - - WSADATA WINSOCK_data = { - 0x0101, - 0x0101, - "WINE Sockets", - #ifdef linux - "Linux/i386", - #elif defined(__NetBSD__) - "NetBSD/i386", - #elif defined(sunos) - "SunOS", - #elif defined(__FreeBSD__) - "FreeBSD", - #else - "Unknown", - #endif - WINSOCK_MAX_SOCKETS, - WINSOCK_MAX_UDPDG, - NULL - }; - - dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested); - - if (LOBYTE(wVersionRequested) < 1 || - (LOBYTE(wVersionRequested) == 1 && - HIBYTE(wVersionRequested) < 1)) - return WSAVERNOTSUPPORTED; - - if (!lpWSAData) - return WSAEINVAL; - - /* alloc winsock heap */ - - if ((HeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0) - return WSASYSNOTREADY; - - Heap = (struct WinSockHeap *) GlobalLock16(HeapHandle); - - /* return winsock information */ - memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data)); - - /* ipc stuff */ - - if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1) - perror("wine: winsock: msgget"); - - signal(SIGUSR1, recv_message); - - /* clear */ - - FD_ZERO(&fd_in_use); - - /* increment our usage count */ - wsa_initted++; - dprintf_winsock(stddeb, "WSAStartup: succeeded\n"); - return(0); -} - -INT WSACleanup(void) -{ - int fd; - - dprintf_winsock(stddeb, "WSACleanup (%d)\n",getpid()); - - if (!wsa_initted) { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - /* decrement usage count */ - wsa_initted--; - - if (wsa_initted == 0) { - if (wine_key) - if (msgctl(wine_key, IPC_RMID, NULL) == -1) - perror("wine: winsock: msgctl"); - - for (fd = 0; fd != FD_SETSIZE; fd++) - if (FD_ISSET(fd, &fd_in_use)) - close(fd); - - } - return 0; -} - -VOID -WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) { - fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n", - x1,x2,x3,x4,x5,x6 - ); - fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n", - x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0 - ); - return; -} diff --git a/miscemu/int21.c b/miscemu/int21.c index 1a4cc96b9d2..d2a5fb54740 100644 --- a/miscemu/int21.c +++ b/miscemu/int21.c @@ -649,7 +649,6 @@ static int INT21_GetCurrentDirectory( SIGCONTEXT *context ) } lstrcpyn32A( ptr, DRIVE_GetDosCwd(drive), 64 ); - if (!ptr[0]) strcpy( ptr, "\\" ); return 1; } diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c index c8a066a103b..44c4bb4614e 100644 --- a/multimedia/mmsystem.c +++ b/multimedia/mmsystem.c @@ -91,7 +91,7 @@ BOOL sndPlaySound(LPCSTR lpszSoundName, UINT uFlags) MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE); if (hmmio == 0) { dprintf_mmsys(stddeb, "sndPlaySound // searching in SystemSound List !\n"); - GetProfileString("Sounds", (LPSTR)lpszSoundName, "", str, sizeof(str)); + GetProfileString32A("Sounds", (LPSTR)lpszSoundName, "", str, sizeof(str)); if (strlen(str) == 0) return FALSE; if ( (ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0'; hmmio = mmioOpen(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE); @@ -586,7 +586,7 @@ DWORD mciOpen(DWORD dwParam, LPMCI_OPEN_PARMS lp16Parms) s=(char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName); t=strrchr(s,'.'); if (t) { - GetProfileString("mci extensions",t+1,"*",str,sizeof(str)); + GetProfileString32A("mci extensions",t+1,"*",str,sizeof(str)); AnsiUpper(str); if (strcmp(str, "CDAUDIO") == 0) { uDevTyp = MCI_DEVTYPE_CD_AUDIO; @@ -745,7 +745,7 @@ DWORD mciSysInfo(DWORD dwFlags, LPMCI_SYSINFO_PARMS lpParms) InstalledCount = 0; InstalledListLen = 0; ptr = lpInstallNames = xmalloc(2048); - GetPrivateProfileString("mci", NULL, "", lpInstallNames, 2000, SysFile); + GetPrivateProfileString32A("mci", NULL, "", lpInstallNames, 2000, SysFile); while(strlen(ptr) > 0) { dprintf_mci(stddeb, "---> '%s' \n", ptr); len = strlen(ptr) + 1; diff --git a/objects/clipping.c b/objects/clipping.c index c7f55fc3e2c..787991b08ec 100644 --- a/objects/clipping.c +++ b/objects/clipping.c @@ -418,6 +418,24 @@ INT32 GetClipBox32( HDC32 hdc, LPRECT32 rect ) return ret; } +/*********************************************************************** + * GetClipRgn32 (GDI32.163) + */ +INT32 GetClipRgn32( HDC32 hdc, HRGN32 hRgn ) +{ + DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); + if( dc && hRgn ) + if( dc->w.hClipRgn ) + { + /* this assumes that dc->w.hClipRgn is in coordinates + relative to the DC origin (not device) */ + + if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR ) + return 1; + } + else return 0; + return -1; +} /*********************************************************************** * SaveVisRgn (GDI.129) diff --git a/objects/dc.c b/objects/dc.c index 834e0f88e54..70c035597d1 100644 --- a/objects/dc.c +++ b/objects/dc.c @@ -718,20 +718,37 @@ WORD SetTextAlign( HDC16 hdc, WORD textAlign ) } +/*********************************************************************** + * GetDCOrgEx (GDI32.168) + */ +BOOL32 GetDCOrgEx(HDC32 hDC, LPPOINT32 lpp) +{ + DC * dc = (DC *) GDI_GetObjPtr( hDC, DC_MAGIC ); + if (!dc || !lpp) return FALSE; + + if (!(dc->w.flags & DC_MEMORY)) + { + Window root; + int w, h, border, depth; + + XGetGeometry( display, dc->u.x.drawable, &root, + &lpp->x, &lpp->y, &w, &h, &border, &depth ); + } + else lpp->x = lpp->y = 0; + lpp->x += dc->w.DCOrgX; lpp->y += dc->w.DCOrgY; + return TRUE; +} + + /*********************************************************************** * GetDCOrg (GDI.79) */ DWORD GetDCOrg( HDC16 hdc ) { - Window root; - int x, y, w, h, border, depth; - - DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); - if (!dc) return 0; - if (dc->w.flags & DC_MEMORY) return 0; - XGetGeometry( display, dc->u.x.drawable, &root, - &x, &y, &w, &h, &border, &depth ); - return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y ); + POINT32 pt; + if( GetDCOrgEx( hdc, &pt) ) + return MAKELONG( (WORD)pt.x, (WORD)pt.y ); + return 0; } diff --git a/objects/dcvalues.c b/objects/dcvalues.c index e32996a9f26..b497558ec2a 100644 --- a/objects/dcvalues.c +++ b/objects/dcvalues.c @@ -86,7 +86,6 @@ DC_GET_X_Y( DWORD, GetWindowExt, WndExtX, WndExtY ) /* GDI.96 */ DC_GET_X_Y( DWORD, GetWindowOrg, WndOrgX, WndOrgY ) /* GDI.97 */ DC_GET_VAL( HRGN32, InquireVisRgn, hVisRgn ) /* GDI.131 */ DC_GET_X_Y( DWORD, GetBrushOrg, brushOrgX, brushOrgY ) /* GDI.149 */ -DC_GET_VAL( HRGN32, GetClipRgn, hClipRgn ) /* GDI.173 */ DC_GET_VAL( WORD, GetTextAlign, textAlign ) /* GDI.345 */ DC_GET_VAL( HFONT16, GetCurLogFont, hFont ) /* GDI.411 */ DC_GET_VAL_EX( GetBrushOrgEx, brushOrgX, brushOrgY ) /* GDI.469 */ @@ -95,3 +94,9 @@ DC_GET_VAL_EX( GetViewportExtEx, VportExtX, VportExtY ) /* GDI.472 */ DC_GET_VAL_EX( GetViewportOrgEx, VportOrgX, VportOrgY ) /* GDI.473 */ DC_GET_VAL_EX( GetWindowExtEx, WndExtX, WndExtY ) /* GDI.474 */ DC_GET_VAL_EX( GetWindowOrgEx, WndOrgX, WndOrgY ) /* GDI.475 */ + +/* this one is wrong - Windows returns region that + is relative to the device and not to the DC origin */ + +DC_GET_VAL( HRGN16, GetClipRgn16, hClipRgn ) /* GDI.173 */ + diff --git a/objects/font.c b/objects/font.c index df3b10968ca..061e5cc234c 100644 --- a/objects/font.c +++ b/objects/font.c @@ -94,7 +94,8 @@ BOOL32 FONT_Init( void ) FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica"; FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica"; FontNames[6].window = "roman"; FontNames[6].x11 = "*-times"; - FontSize = 7; + FontNames[7].window = "system"; FontNames[7].x11 = "*-helvetica"; + FontSize = 8; } return TRUE; } @@ -220,6 +221,20 @@ static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc ) family = "*-*"; break; } + sprintf( pattern, "-%s-%s-*-normal-*-*-*-*-*-*-*-%s", + family, weight, charset); + dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern ); + names = XListFonts( display, pattern, 1, &count ); + if (names) XFreeFontNames( names ); + else + { + if (strcmp(family, "*-*") == 0) + { + fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern); + return NULL; + } + else family = "*-*"; + } oldheight = height; oldspacing = spacing; while (TRUE) { @@ -1197,133 +1212,145 @@ void InitFontsList(void) XFreeFontNames(names); } - /************************************************************************* * EnumFonts [GDI.70] + * We reuse EnumFontFamilies* for the callback function get the same + * structs (+ extra stuff at the end which will be ignored by the enum funcs) */ -INT EnumFonts(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData) +INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData) { - HLOCAL16 hLog; - HLOCAL16 hMet; - HFONT16 hFont; - HFONT16 hOldFont; - LPLOGFONT16 lpLogFont; - LPTEXTMETRIC16 lptm; - LPSTR lpOldName; - char FaceName[LF_FACESIZE]; - int nRet = 0; - int i; - - dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n", - hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData); - if (lpEnumFunc == 0) return 0; - hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE ); - lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog); - if (lpLogFont == NULL) { - fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n"); - return 0; - } - hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) ); - lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet); - if (lptm == NULL) { - GDI_HEAP_FREE(hLog); - fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n"); - return 0; - } - if (lpFaceName != NULL) { - strcpy(FaceName, lpFaceName); - AnsiUpper(FaceName); - } - lpOldName = NULL; - - if (lpLogFontList[0] == NULL) InitFontsList(); - for(i = 0; lpLogFontList[i] != NULL; i++) { - if (lpFaceName == NULL) { - if (lpOldName != NULL) { - if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue; - } - lpOldName = lpLogFontList[i]->lfFaceName; - } else { - if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue; - } - dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName); - dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]); - memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE); - hFont = CreateFontIndirect16(lpLogFont); - hOldFont = SelectObject32(hDC, hFont); - GetTextMetrics16(hDC, lptm); - SelectObject32(hDC, hOldFont); - DeleteObject32(hFont); - dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm); - nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet), - 0, (LONG)lpData ); - if (nRet == 0) { - dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n"); - break; - } - } - GDI_HEAP_FREE(hMet); - GDI_HEAP_FREE(hLog); - return nRet; + return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData); } +/************************************************************************* + * EnumFontsA [GDI32.84] + */ +INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData) +{ + return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData); +} + +/************************************************************************* + * EnumFontsA [GDI32.84] + */ +INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData) +{ + return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData); +} /************************************************************************* * EnumFontFamilies [GDI.330] */ INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData) +{ + LOGFONT16 LF; + + if (lpszFamily) + strcpy(LF.lfFaceName,lpszFamily); + else + LF.lfFaceName[0]='\0'; + LF.lfCharSet = DEFAULT_CHARSET; + + return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0); +} + +/************************************************************************* + * EnumFontFamiliesA [GDI32.80] + */ +INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData) +{ + LOGFONT32A LF; + + if (lpszFamily) + strcpy(LF.lfFaceName,lpszFamily); + else + LF.lfFaceName[0]='\0'; + LF.lfCharSet = DEFAULT_CHARSET; + + return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0); +} + +/************************************************************************* + * EnumFontFamiliesW [GDI32.83] + */ +INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData) +{ + LOGFONT32W LF; + + if (lpszFamilyW) + lstrcpy32W(LF.lfFaceName,lpszFamilyW); + else + LF.lfFaceName[0]=0; + LF.lfCharSet = DEFAULT_CHARSET; + return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0); +} + +/************************************************************************* + * EnumFontFamiliesEx [GDI.618] + * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures. + * (applies to all EnumFontFamiliesEx*) + * winelib/16 support. + */ +INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved) { HLOCAL16 hLog; HLOCAL16 hMet; HFONT16 hFont; HFONT16 hOldFont; - LPENUMLOGFONT16 lpEnumLogFont; - LPTEXTMETRIC16 lptm; + LPENUMLOGFONTEX16 lpEnumLogFont; + LPNEWTEXTMETRICEX16 lptm; LPSTR lpOldName; char FaceName[LF_FACESIZE]; int nRet = 0; int i; - dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n", - hDC, lpszFamily, (DWORD)lpEnumFunc, lpData); + dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n", + hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved); if (lpEnumFunc == 0) return 0; - hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) ); - lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog); + hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) ); + lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog); if (lpEnumLogFont == NULL) { - fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n"); + fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n"); return 0; } - hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) ); - lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet); + hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) ); + lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet); if (lptm == NULL) { GDI_HEAP_FREE(hLog); - fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n"); + fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n"); return 0; } lpOldName = NULL; - if (lpszFamily != NULL) { - strcpy(FaceName, lpszFamily); - AnsiUpper(FaceName); - } + strcpy(FaceName,lpLF->lfFaceName); + AnsiUpper(lpLF->lfFaceName); + if (lpLogFontList[0] == NULL) InitFontsList(); for(i = 0; lpLogFontList[i] != NULL; i++) { - if (lpszFamily == NULL) { - if (lpOldName != NULL) { - if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue; - } - lpOldName = lpLogFontList[i]->lfFaceName; + /* lfCharSet */ + if (lpLF->lfCharSet!=DEFAULT_CHARSET) + if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet) + continue; + + /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */ + /* lfFaceName */ + if (FaceName[0]) { + if (strcmp(FaceName,lpLogFontList[i]->lfFaceName)) + continue; } else { - if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue; + if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName)) + continue; + lpOldName=lpLogFontList[i]->lfFaceName; } + memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16)); strcpy(lpEnumLogFont->elfFullName,""); strcpy(lpEnumLogFont->elfStyle,""); hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont); hOldFont = SelectObject32(hDC, hFont); - GetTextMetrics16(hDC, lptm); + GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm); SelectObject32(hDC, hOldFont); DeleteObject32(hFont); - dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm); + dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm); nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet), 0, lpData ); @@ -1338,66 +1365,74 @@ INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc } /************************************************************************* - * EnumFontFamiliesA [GDI32.80] + * EnumFontFamiliesExA [GDI32.81] + * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*) */ -INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData) +INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved) { HLOCAL16 hLog; HLOCAL16 hMet; HFONT32 hFont; HFONT32 hOldFont; - LPENUMLOGFONT32A lpEnumLogFont; - LPTEXTMETRIC32A lptm; + LPENUMLOGFONTEX32A lpEnumLogFont; + LPNEWTEXTMETRICEX32A lptm; LPSTR lpOldName; char FaceName[LF_FACESIZE]; int nRet = 0; int i; - dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx)\n", - hDC, lpszFamily, (DWORD)lpEnumFunc, lpData); + dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n", + hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved); if (lpEnumFunc == 0) return 0; - hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT32A) ); - lpEnumLogFont = (LPENUMLOGFONT32A) GDI_HEAP_LIN_ADDR(hLog); + hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) ); + lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog); if (lpEnumLogFont == NULL) { fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n"); return 0; } - hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC32A) ); - lptm = (LPTEXTMETRIC32A) GDI_HEAP_LIN_ADDR(hMet); + hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) ); + lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet); if (lptm == NULL) { GDI_HEAP_FREE(hLog); fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n"); return 0; } lpOldName = NULL; - if (lpszFamily != NULL) { - strcpy(FaceName, lpszFamily); - AnsiUpper(FaceName); - } + strcpy(FaceName,lpLF->lfFaceName); + AnsiUpper(lpLF->lfFaceName); + if (lpLogFontList[0] == NULL) InitFontsList(); for(i = 0; lpLogFontList[i] != NULL; i++) { - if (lpszFamily == NULL) { - if (lpOldName != NULL) { - if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue; - } - lpOldName = lpLogFontList[i]->lfFaceName; + /* lfCharSet */ + if (lpLF->lfCharSet!=DEFAULT_CHARSET) + if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet) + continue; + + /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */ + /* lfFaceName */ + if (FaceName[0]) { + if (strcmp(FaceName,lpLogFontList[i]->lfFaceName)) + continue; } else { - if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue; + if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName)) + continue; + lpOldName=lpLogFontList[i]->lfFaceName; } + FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont)); strcpy(lpEnumLogFont->elfFullName,""); strcpy(lpEnumLogFont->elfStyle,""); + strcpy(lpEnumLogFont->elfScript,""); hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont); hOldFont = SelectObject32(hDC, hFont); - GetTextMetrics32A(hDC, lptm); + GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm); SelectObject32(hDC, hOldFont); DeleteObject32(hFont); - dprintf_font(stddeb, "EnumFontFamilies32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm); + dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm); - nRet = lpEnumFunc( GDI_HEAP_LIN_ADDR(hLog), GDI_HEAP_LIN_ADDR(hMet), - 0, lpData ); + nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData); if (nRet == 0) { - dprintf_font(stddeb,"EnumFontFamilies32A // EnumEnd requested by application !\n"); + dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n"); break; } } @@ -1406,66 +1441,76 @@ INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFu return nRet; } + /************************************************************************* - * EnumFontFamiliesW [GDI32.83] + * EnumFontFamiliesW [GDI32.82] */ -INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData) +INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved) { HLOCAL16 hLog; HLOCAL16 hMet; HFONT32 hFont; HFONT32 hOldFont; - LPENUMLOGFONT32W lpEnumLogFont; - LPTEXTMETRIC32W lptm; + LPENUMLOGFONTEX32W lpEnumLogFont; + LPNEWTEXTMETRICEX32W lptm; LPSTR lpOldName; - char FaceName[LF_FACESIZE]; int nRet = 0; int i; - LPCSTR lpszFamily=lpszFamilyW?STRING32_DupUniToAnsi(lpszFamilyW):NULL; + LPSTR lpszFamily=STRING32_DupUniToAnsi(lpLF->lfFaceName); - dprintf_font(stddeb,"EnumFontFamilies32W(%04x, %p, %08lx, %08lx)\n", - hDC, lpszFamily, (DWORD)lpEnumFunc, lpData); - if (lpEnumFunc == 0) return 0; - hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT32W) ); - lpEnumLogFont = (LPENUMLOGFONT32W) GDI_HEAP_LIN_ADDR(hLog); - if (lpEnumLogFont == NULL) { - fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n"); + dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n", + hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved); + if (lpEnumFunc == 0) { + free(lpszFamily); return 0; } - hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC32W) ); - lptm = (LPTEXTMETRIC32W) GDI_HEAP_LIN_ADDR(hMet); + hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) ); + lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog); + if (lpEnumLogFont == NULL) { + fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n"); + free(lpszFamily); + return 0; + } + hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) ); + lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet); if (lptm == NULL) { GDI_HEAP_FREE(hLog); fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n"); + free(lpszFamily); return 0; } lpOldName = NULL; - if (lpszFamily != NULL) { - strcpy(FaceName, lpszFamily); - AnsiUpper(FaceName); - } + AnsiUpper(lpszFamily); if (lpLogFontList[0] == NULL) InitFontsList(); for(i = 0; lpLogFontList[i] != NULL; i++) { - if (lpszFamily == NULL) { - if (lpOldName != NULL) { - if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue; - } - lpOldName = lpLogFontList[i]->lfFaceName; + /* lfCharSet */ + if (lpLF->lfCharSet!=DEFAULT_CHARSET) + if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet) + continue; + + /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */ + /* lfFaceName */ + if (lpszFamily[0]) { + if (strcmp(lpszFamily,lpLogFontList[i]->lfFaceName)) + continue; } else { - if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue; + if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName)) + continue; + lpOldName=lpLogFontList[i]->lfFaceName; } + FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont)); lstrcpynAtoW(lpEnumLogFont->elfFullName,"",1); lstrcpynAtoW(lpEnumLogFont->elfStyle,"",1); + lstrcpynAtoW(lpEnumLogFont->elfScript,"",1); hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont); hOldFont = SelectObject32(hDC, hFont); - GetTextMetrics32W(hDC, lptm); + GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm); SelectObject32(hDC, hOldFont); DeleteObject32(hFont); dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm); - nRet = lpEnumFunc( GDI_HEAP_LIN_ADDR(hLog), GDI_HEAP_LIN_ADDR(hMet), - 0, lpData ); + nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData); if (nRet == 0) { dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n"); break; @@ -1473,6 +1518,7 @@ INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnum } GDI_HEAP_FREE(hMet); GDI_HEAP_FREE(hLog); + free(lpszFamily); return nRet; } diff --git a/objects/pen.c b/objects/pen.c index bb147914d94..83f70c7dd19 100644 --- a/objects/pen.c +++ b/objects/pen.c @@ -13,7 +13,7 @@ static const char PEN_dash[] = { 5,3 }; /* ----- ----- ----- */ -static const char PEN_dot[] = { 2,2 }; /* -- -- -- -- -- -- */ +static const char PEN_dot[] = { 1,1 }; /* -- -- -- -- -- -- */ static const char PEN_dashdot[] = { 4,3,2,3 }; /* ---- -- ---- -- */ static const char PEN_dashdotdot[] = { 4,2,2,2,2,2 }; /* ---- -- -- ---- */ diff --git a/objects/text.c b/objects/text.c index 782fe70231a..fd2450f699d 100644 --- a/objects/text.c +++ b/objects/text.c @@ -283,7 +283,7 @@ INT16 DrawText16( HDC16 hdc, LPCSTR str, INT16 i_count, rect->right = rect->left + max_width; rect->bottom = y; } - return 1; + return y - rect->top; } diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c index aefda90e6a3..54e0a8d520a 100644 --- a/programs/winhelp/winhelp.c +++ b/programs/winhelp/winhelp.c @@ -592,7 +592,7 @@ static LRESULT WINHELP_TextWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM l { BOOL update = TRUE; RECT rect; - INT16 Min, Max; + INT Min, Max; INT CurPos = GetScrollPos(hWnd, SB_VERT); GetScrollRange(hWnd, SB_VERT, &Min, &Max); GetClientRect(hWnd, &rect); diff --git a/win32/file.c b/win32/file.c index 925de51dc75..e60bc6189bf 100644 --- a/win32/file.c +++ b/win32/file.c @@ -60,20 +60,16 @@ HANDLE32 CreateFileMapping32A(HANDLE32 h,LPSECURITY_ATTRIBUTES ats, SetLastError(ErrnoToLastError(errno)); return INVALID_HANDLE_VALUE; } - hfile = _lcreat(lpName,1); - if(hfile == HFILE_ERROR) { - SetLastError(ErrnoToLastError(errno)); - return INVALID_HANDLE_VALUE; - } filemap_obj=(FILEMAP_OBJECT *)CreateKernelObject(sizeof(FILEMAP_OBJECT)); if(filemap_obj == NULL) { - _lclose(hfile); SetLastError(ERROR_UNKNOWN); return 0; } + if (h==INVALID_HANDLE_VALUE) + h=_lcreat(lpName,1);/*FIXME*/ filemap_obj->common.magic = KERNEL_OBJECT_FILEMAP; - filemap_obj->hfile = hfile; + filemap_obj->hfile = h; filemap_obj->prot = TranslateProtectionFlags(pot); filemap_obj->size = hlow; return (HANDLE32)filemap_obj;; @@ -97,7 +93,6 @@ HANDLE32 CreateFileMapping32W(HANDLE32 h,LPSECURITY_ATTRIBUTES ats, /*********************************************************************** * MapViewOfFile (KERNEL32.385) - * */ LPVOID MapViewOfFile(HANDLE32 handle, DWORD access, DWORD offhi, DWORD offlo, DWORD size) @@ -112,13 +107,25 @@ LPVOID MapViewOfFile(HANDLE32 handle, DWORD access, DWORD offhi, LPVOID MapViewOfFileEx(HANDLE32 handle, DWORD access, DWORD offhi, DWORD offlo, DWORD size, DWORD st) { - if (!size) size = ((FILEMAP_OBJECT *)handle)->size; - return mmap ((caddr_t)st, size, ((FILEMAP_OBJECT *)handle)->prot, + FILEMAP_OBJECT *fmap = (FILEMAP_OBJECT*)handle; + + if (!size) size = fmap->size; + if (!size) size = 1; + return mmap ((caddr_t)st, size, fmap->prot, MAP_ANON|MAP_PRIVATE, - FILE_GetUnixHandle(((FILEMAP_OBJECT *)handle)->hfile), + FILE_GetUnixHandle(fmap->hfile), offlo); } +/*********************************************************************** + * UnmapViewOfFile (KERNEL32.385) + */ +BOOL32 UnmapViewOfFile(LPVOID address) { + munmap(address,/*hmm*/1); /* FIXME: size? */ + return TRUE; +} + + /*********************************************************************** * GetFileInformationByHandle (KERNEL32.219) diff --git a/windows/caret.c b/windows/caret.c index 99c955ff2c0..055bb1b2ec9 100644 --- a/windows/caret.c +++ b/windows/caret.c @@ -150,7 +150,7 @@ BOOL16 CreateCaret( HWND32 hwnd, HBITMAP32 bitmap, INT32 width, INT32 height ) Caret.x = 0; Caret.y = 0; - Caret.timeout = GetProfileInt( "windows", "CursorBlinkRate", 750 ); + Caret.timeout = GetProfileInt32A( "windows", "CursorBlinkRate", 750 ); return TRUE; } diff --git a/windows/dce.c b/windows/dce.c index 5a7c9e0e404..1f038323413 100644 --- a/windows/dce.c +++ b/windows/dce.c @@ -282,7 +282,8 @@ HRGN32 DCE_GetVisRgn( HWND hwnd, WORD flags ) /* Get visible rectangle and create a region with it. * do we really need to calculate vis rgns for X windows? - * - yes, to clip child windows. + * - yes, to clip child windows but we should skip + * siblings in this case. */ if (!wndPtr || !DCE_GetVisRect( wndPtr, !(flags & DCX_WINDOW), &rect )) @@ -377,7 +378,41 @@ static void DCE_SetDrawable( WND *wndPtr, DC *dc, WORD flags ) dc->u.x.drawable = wndPtr->window; } } +/*********************************************************************** + * DCE_ExcludeRgn + * + * Translate given region from the wnd client to the DC coordinates + * and add it to the clipping region. + */ +INT16 DCE_ExcludeRgn( HDC32 hDC, WND* wnd, HRGN32 hRgn ) +{ + INT16 ret; + POINT32 pt = {0, 0}; + HRGN32 hRgnClip = GetClipRgn16( hDC ); + DCE *dce = firstDCE; + while (dce && (dce->hDC != hDC)) dce = dce->next; + if( dce ) + { + MapWindowPoints32( wnd->hwndSelf, dce->hwndCurrent, &pt, 1); + if( dce->DCXflags & DCX_WINDOW ) + { + wnd = WIN_FindWndPtr(dce->hwndCurrent); + pt.x += wnd->rectClient.left - wnd->rectWindow.left; + pt.y += wnd->rectClient.top - wnd->rectWindow.top; + } + } + else return ERROR; + OffsetRgn32(hRgn, pt.x, pt.y); + if( hRgnClip ) ret = CombineRgn32( hRgnClip, hRgnClip, hRgn, RGN_DIFF ); + else + { + hRgnClip = InquireVisRgn( hDC ); + ret = CombineRgn32( hRgn, hRgnClip, hRgn, RGN_DIFF ); + SelectClipRgn32( hDC, hRgn ); + } + return ret; +} /*********************************************************************** * GetDCEx16 (USER.359) diff --git a/windows/defwnd.c b/windows/defwnd.c index 03b82c3020f..b201881087d 100644 --- a/windows/defwnd.c +++ b/windows/defwnd.c @@ -376,7 +376,7 @@ LRESULT DefWindowProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, if (wParam && wndPtr->text) { lstrcpyn32A( (LPSTR)PTR_SEG_TO_LIN(lParam), wndPtr->text, wParam ); - result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) ) + 1; + result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) ); } break; @@ -442,7 +442,7 @@ LRESULT DefWindowProc32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, if (wParam && wndPtr->text) { lstrcpyn32A( (LPSTR)lParam, wndPtr->text, wParam ); - result = (LRESULT)strlen( (LPSTR)lParam ) + 1; + result = (LRESULT)strlen( (LPSTR)lParam ); } break; diff --git a/windows/dialog.c b/windows/dialog.c index 03a0ddf6fe4..7f51666cb24 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -4,11 +4,13 @@ * Copyright 1993, 1994, 1996 Alexandre Julliard */ +#include #include #include #include #include "windows.h" #include "dialog.h" +#include "drive.h" #include "heap.h" #include "win.h" #include "ldt.h" @@ -16,6 +18,7 @@ #include "user.h" #include "winproc.h" #include "message.h" +#include "sysmetrics.h" #include "stddebug.h" #include "debug.h" @@ -534,8 +537,22 @@ static HWND DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate, { rect.left += template.x * xUnit / 4; rect.top += template.y * yUnit / 8; - if ( !(template.style & DS_ABSALIGN) && !(template.style & WS_CHILD) ) - ClientToScreen16( owner, (POINT16 *)&rect ); + if ( !(template.style & WS_CHILD) ) + { + INT16 dX, dY; + + if( !(template.style & DS_ABSALIGN) ) + ClientToScreen16( owner, (POINT16 *)&rect ); + + /* try to fit it into the desktop */ + + if( (dX = rect.left + rect.right + SYSMETRICS_CXDLGFRAME + - SYSMETRICS_CXSCREEN) > 0 ) rect.left -= dX; + if( (dY = rect.top + rect.bottom + SYSMETRICS_CYDLGFRAME + - SYSMETRICS_CYSCREEN) > 0 ) rect.top -= dY; + if( rect.left < 0 ) rect.left = 0; + if( rect.top < 0 ) rect.top = 0; + } } if (procType != WIN_PROC_16) @@ -569,6 +586,9 @@ static HWND DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate, dlgInfo->msgResult = 0; /* This is used to store the default button id */ dlgInfo->hDialogHeap = 0; + if (dlgInfo->hUserFont) + SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 ); + /* Create controls */ if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems, @@ -581,8 +601,6 @@ static HWND DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate, /* Send initialisation messages and set focus */ dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE ); - if (dlgInfo->hUserFont) - SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 ); if (SendMessage32A( hwnd, WM_INITDIALOG, (WPARAM32)dlgInfo->hwndFocus, param )) SetFocus32( dlgInfo->hwndFocus ); @@ -1390,6 +1408,96 @@ static BOOL32 DIALOG_DlgDirSelect( HWND32 hwnd, LPSTR str, INT32 len, } +/********************************************************************** + * DIALOG_DlgDirList + * + * Helper function for DlgDirList* + */ +static INT32 DIALOG_DlgDirList( HWND32 hDlg, LPCSTR spec, INT32 idLBox, + INT32 idStatic, UINT32 attrib, BOOL32 combo ) +{ + int drive; + HWND32 hwnd; + +#define SENDMSG(msg,wparam,lparam) \ + ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \ + : SendMessage32A( hwnd, msg, wparam, lparam )) + + dprintf_dialog( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n", + hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib ); + + if (spec && spec[0] && (spec[1] == ':')) + { + drive = toupper( spec[0] ) - 'A'; + spec += 2; + if (!DRIVE_SetCurrentDrive( drive )) return FALSE; + } + else drive = DRIVE_GetCurrentDrive(); + + if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0)) + { + /* If the path exists and is a directory, chdir to it */ + if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*"; + else + { + const char *p, *p2; + p = spec; + if ((p2 = strrchr( p, '\\' ))) p = p2 + 1; + if ((p2 = strrchr( p, '/' ))) p = p2 + 1; + if (p != spec) + { + BOOL32 ret = FALSE; + char *dir = HeapAlloc( SystemHeap, 0, p - spec ); + if (dir) + { + lstrcpyn32A( dir, spec, p - spec ); + ret = DRIVE_Chdir( drive, dir ); + HeapFree( SystemHeap, 0, dir ); + } + if (!ret) return FALSE; + spec = p; + } + } + + dprintf_dialog( stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n", + 'A' + drive, DRIVE_GetDosCwd(drive), spec ); + + SENDMSG( combo ? CB_RESETCONTENT32 : LB_RESETCONTENT32, 0, 0 ); + if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE)) + { + if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, + attrib & ~(DDL_DIRECTORY | DDL_DRIVES), + (LPARAM)spec ) == LB_ERR) + return FALSE; + if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, + (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE, + (LPARAM)"*.*" ) == LB_ERR) + return FALSE; + } + else + { + if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, attrib, + (LPARAM)spec ) == LB_ERR) + return FALSE; + } + } + + if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0)) + { + char temp[512]; + int drive = DRIVE_GetCurrentDrive(); + strcpy( temp, "A:\\" ); + temp[0] += drive; + lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 ); + AnsiLower( temp ); + /* Can't use PostMessage() here, because the string is on the stack */ + SetDlgItemText32A( hDlg, idStatic, temp ); + } + return TRUE; +#undef SENDMSG +} + + /********************************************************************** * DlgDirSelect (USER.99) */ @@ -1460,3 +1568,73 @@ BOOL32 DlgDirSelectComboBoxEx32W( HWND32 hwnd, LPWSTR str, INT32 len, INT32 id) { return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, TRUE ); } + + +/********************************************************************** + * DlgDirList16 (USER.100) + */ +INT16 DlgDirList16( HWND16 hDlg, LPCSTR spec, INT16 idLBox, INT16 idStatic, + UINT16 attrib ) +{ + return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE ); +} + + +/********************************************************************** + * DlgDirList32A (USER32.142) + */ +INT32 DlgDirList32A( HWND32 hDlg, LPCSTR spec, INT32 idLBox, INT32 idStatic, + UINT32 attrib ) +{ + return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE ); +} + + +/********************************************************************** + * DlgDirList32W (USER32.145) + */ +INT32 DlgDirList32W( HWND32 hDlg, LPCWSTR spec, INT32 idLBox, INT32 idStatic, + UINT32 attrib ) +{ + INT32 ret; + LPSTR specA = NULL; + if (spec) specA = STRING32_DupUniToAnsi(spec); + ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic, attrib, FALSE ); + if (specA) free( specA ); + return ret; +} + + +/********************************************************************** + * DlgDirListComboBox16 (USER.195) + */ +INT16 DlgDirListComboBox16( HWND16 hDlg, LPCSTR spec, INT16 idCBox, + INT16 idStatic, UINT16 attrib ) +{ + return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE ); +} + + +/********************************************************************** + * DlgDirListComboBox32A (USER32.143) + */ +INT32 DlgDirListComboBox32A( HWND32 hDlg, LPCSTR spec, INT32 idCBox, + INT32 idStatic, UINT32 attrib ) +{ + return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE ); +} + + +/********************************************************************** + * DlgDirListComboBox32W (USER32.144) + */ +INT32 DlgDirListComboBox32W( HWND32 hDlg, LPCWSTR spec, INT32 idCBox, + INT32 idStatic, UINT32 attrib ) +{ + INT32 ret; + LPSTR specA = NULL; + if (spec) specA = STRING32_DupUniToAnsi(spec); + ret = DIALOG_DlgDirList( hDlg, specA, idCBox, idStatic, attrib, FALSE ); + if (specA) free( specA ); + return ret; +} diff --git a/windows/event.c b/windows/event.c index 20100520990..49d325ac12a 100644 --- a/windows/event.c +++ b/windows/event.c @@ -37,6 +37,7 @@ #include "shell.h" #include "registers.h" #include "xmalloc.h" +#include "keyboard.h" #include "stddebug.h" #include "debug.h" #include "dde_proc.h" @@ -62,13 +63,9 @@ static XContext winContext = 0; /* State variables */ BOOL MouseButtonsStates[NB_BUTTONS]; BOOL AsyncMouseButtonsStates[NB_BUTTONS]; -BYTE KeyStateTable[256]; -BYTE AsyncKeyStateTable[256]; +BYTE InputKeyStateTable[256]; -WPARAM16 lastEventChar = 0; /* this will have to be changed once - * ToAscii starts working */ - static HWND32 captureWnd = 0; static BOOL32 InputEnabled = TRUE; @@ -128,8 +125,8 @@ typedef union unsigned long count : 16; unsigned long code : 8; unsigned long extended : 1; - unsigned long : 2; - unsigned long reserved : 2; + unsigned long unused : 2; + unsigned long win_internal : 2; unsigned long context : 1; unsigned long previous : 1; unsigned long transition : 1; @@ -188,7 +185,7 @@ void EVENT_ProcessEvent( XEvent *event ) { WND *pWnd; - if (XFindContext( display, ((XAnyEvent *)event)->window, winContext, + if (XFindContext( display, event->xany.window, winContext, (char **)&pWnd ) != 0) return; /* Not for a registered window */ @@ -521,8 +518,16 @@ static void EVENT_key( XKeyEvent *event ) int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs); Str[ascii_chars] = '\0'; - dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n", - keysym, ascii_chars, Str[0], Str); + if (debugging_key) + { + char *ksname; + + ksname = XKeysymToString(keysym); + if (!ksname) + ksname = "No Name"; + fprintf(stddeb, "WM_KEY??? : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", + keysym, ksname, ascii_chars, Str[0], Str); + } /* Ctrl-Alt-Return enters the debugger */ if ((keysym == XK_Return) && (event->type == KeyPress) && @@ -556,6 +561,27 @@ static void EVENT_key( XKeyEvent *event ) vkey = modifier_key[key - 0xE1]; else if (key == 0xFF) /* DEL key */ vkey = VK_DELETE; + /* extended must also be set for ALT_R, CTRL_R, + INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys, + keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */ + switch (keysym) + { + case XK_Control_R : + case XK_Alt_R : + case XK_Insert : + case XK_Delete : + case XK_Home : + case XK_End : + case XK_Page_Up : + case XK_Page_Down : + case XK_Left : + case XK_Up : + case XK_Right : + case XK_Down : + case XK_KP_Divide : + case XK_KP_Enter : + extended = 1; + } } else if (key_type == 0) /* character key */ { @@ -568,24 +594,7 @@ static void EVENT_key( XKeyEvent *event ) { #define vkcase(k,val) case k: vkey = val; break; #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break; - - /* I wish I had a bit-paired keyboard! */ - vkcase('!','1'); vkcase('@','2'); vkcase('#','3'); - vkcase('$','4'); vkcase('%','5'); vkcase('^','6'); - vkcase('&','7'); vkcase('*','8'); vkcase('(','9'); - vkcase(')','0'); - - vkcase2('`','~',0xc0); - vkcase2('-','_',0xbd); - vkcase2('=','+',0xbb); - vkcase2('[','{',0xdb); - vkcase2(']','}',0xdd); - vkcase2(';',':',0xba); - vkcase2('\'','\"',0xde); - vkcase2(',','<',0xbc); - vkcase2('.','>',0xbe); - vkcase2('/','?',0xbf); - vkcase2('\\','|',0xdc); + WINE_VKEY_MAPPINGS #undef vkcase #undef vkcase2 default: @@ -596,50 +605,41 @@ static void EVENT_key( XKeyEvent *event ) if (event->type == KeyPress) { - if (!(KeyStateTable[vkey] & 0x80)) - KeyStateTable[vkey] ^= 0x01; - KeyStateTable[vkey] |= 0x80; + if (!(InputKeyStateTable[vkey] & 0x80)) + InputKeyStateTable[vkey] ^= 0x01; + InputKeyStateTable[vkey] |= 0x80; keylp.lp1.count = 1; keylp.lp1.code = LOBYTE(event->keycode) - 8; keylp.lp1.extended = (extended ? 1 : 0); - keylp.lp1.reserved = (ascii_chars ? 1 : 0); + keylp.lp1.win_internal = 0; keylp.lp1.context = ( (event->state & Mod1Mask) || - (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0; + (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0; keylp.lp1.previous = (KeyDown ? 0 : 1); keylp.lp1.transition = 0; dprintf_key(stddeb," wParam=%X, lParam=%lX\n", vkey, keylp.lp2 ); - dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]); - hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN, + dprintf_key(stddeb," InputKeyState=%X\n", InputKeyStateTable[vkey]); + hardware_event( InputKeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN, vkey, keylp.lp2, event->x_root - desktopX, event->y_root - desktopY, event->time - MSG_WineStartTicks, 0 ); KeyDown = TRUE; - - /* Currently we use reserved field in the scan-code byte to - * make it possible for TranslateMessage to recognize character keys - * and get them from lastEventChar global variable. - * - * ToAscii should handle it. - */ - - if( ascii_chars ) lastEventChar = Str[0]; } else { - UINT sysKey = KeyStateTable[VK_MENU]; + UINT sysKey = InputKeyStateTable[VK_MENU]; - KeyStateTable[vkey] &= ~0x80; + InputKeyStateTable[vkey] &= ~0x80; keylp.lp1.count = 1; keylp.lp1.code = LOBYTE(event->keycode) - 8; keylp.lp1.extended = (extended ? 1 : 0); - keylp.lp1.reserved = 0; + keylp.lp1.win_internal = 0; keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0); keylp.lp1.previous = 1; keylp.lp1.transition = 1; dprintf_key(stddeb," wParam=%X, lParam=%lX\n", vkey, keylp.lp2 ); - dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]); + dprintf_key(stddeb," InputKeyState=%X\n", InputKeyStateTable[vkey]); hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP, vkey, keylp.lp2, event->x_root - desktopX, event->y_root - desktopY, diff --git a/windows/graphics.c b/windows/graphics.c index 40d1c304954..5003f17c232 100644 --- a/windows/graphics.c +++ b/windows/graphics.c @@ -834,7 +834,7 @@ void DrawFocusRect16( HDC16 hdc, const RECT16* rc ) { RECT32 rect32; CONV_RECT16TO32( rc, &rect32 ); - return DrawFocusRect32( hdc, &rect32 ); + DrawFocusRect32( hdc, &rect32 ); } diff --git a/windows/hook.c b/windows/hook.c index dcc5fdfe3c3..ef81d3ab909 100644 --- a/windows/hook.c +++ b/windows/hook.c @@ -133,7 +133,6 @@ static HANDLE16 HOOK_SetHook( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, data->ownerQueue = hQueue; data->ownerModule = hInst; data->inHookProc = 0; - dprintf_hook( stddeb, "Setting hook %d: ret=%04x\n", id, handle ); /* Insert it in the correct linked list */ @@ -148,6 +147,8 @@ static HANDLE16 HOOK_SetHook( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, data->next = HOOK_systemHooks[id - WH_MINHOOK]; HOOK_systemHooks[id - WH_MINHOOK] = handle; } + dprintf_hook( stddeb, "Setting hook %d: ret=%04x [next=%04x]\n", + id, handle, data->next ); return handle; } @@ -188,7 +189,7 @@ static BOOL32 HOOK_RemoveHook( HANDLE16 hook ) while (*prevHook && *prevHook != hook) prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next; - if (!*prevHook) return FALSE; + if (!*prevHook) return FALSE; *prevHook = data->next; USER_HEAP_FREE( hook ); return TRUE; @@ -250,6 +251,33 @@ LRESULT HOOK_CallHooks( INT16 id, INT16 code, WPARAM16 wParam, LPARAM lParam ) } +/*********************************************************************** + * HOOK_ResetQueueHooks + */ +void HOOK_ResetQueueHooks( HQUEUE16 hQueue ) +{ + MESSAGEQUEUE *queue; + + if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL) + { + HOOKDATA* data; + HHOOK hook; + int id; + for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ ) + { + hook = queue->hooks[id - WH_MINHOOK]; + while( hook ) + { + if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) ) + { + data->ownerQueue = hQueue; + hook = data->next; + } else break; + } + } + } +} + /*********************************************************************** * HOOK_FreeModuleHooks */ diff --git a/windows/keyboard.c b/windows/keyboard.c index ccc815be87b..10e3ed0acf5 100644 --- a/windows/keyboard.c +++ b/windows/keyboard.c @@ -3,47 +3,60 @@ * * Copyright 1993 Bob Amstadt */ +#include #include #include "win.h" #include "windows.h" +#include "debug.h" extern BOOL MouseButtonsStates[3]; extern BOOL AsyncMouseButtonsStates[3]; -extern BYTE KeyStateTable[256]; -extern BYTE AsyncKeyStateTable[256]; +extern BYTE InputKeyStateTable[256]; +BYTE AsyncKeyStateTable[256]; + +extern BYTE QueueKeyStateTable[256]; /********************************************************************** * GetKeyState [USER.106] + * An application calls the GetKeyState function in response to a + * keyboard-input message. This function retrieves the state of the key + * at the time the input message was generated. (SDK 3.1 Vol 2. p 390) */ INT GetKeyState(INT keycode) { INT retval; + if (keycode >= 'a' && keycode <= 'z') + keycode += 'A' - 'a'; switch(keycode) { case VK_LBUTTON: - return MouseButtonsStates[0]; + retval = MouseButtonsStates[0]; case VK_MBUTTON: - return MouseButtonsStates[1]; + retval = MouseButtonsStates[1]; case VK_RBUTTON: - return MouseButtonsStates[2]; + retval = MouseButtonsStates[2]; default: - retval = ( (INT)(KeyStateTable[keycode] & 0x80) << 8 ) | - (INT)(KeyStateTable[keycode] & 0x01); + retval = ( (INT)(QueueKeyStateTable[keycode] & 0x80) << 8 ) | + (INT)(QueueKeyStateTable[keycode] & 0x01); } + dprintf_key(stddeb, "GetKeyState(%x) -> %x\n", keycode, retval); return retval; } /********************************************************************** * GetKeyboardState [USER.222] + * An application calls the GetKeyboardState function in response to a + * keyboard-input message. This function retrieves the state of the keyboard + * at the time the input message was generated. (SDK 3.1 Vol 2. p 387) */ void GetKeyboardState(BYTE *lpKeyState) { if (lpKeyState != NULL) { - KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8; - KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8; - KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8; - memcpy(lpKeyState, KeyStateTable, 256); + QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8; + QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8; + QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8; + memcpy(lpKeyState, QueueKeyStateTable, 256); } } @@ -53,10 +66,10 @@ void GetKeyboardState(BYTE *lpKeyState) void SetKeyboardState(BYTE *lpKeyState) { if (lpKeyState != NULL) { - memcpy(KeyStateTable, lpKeyState, 256); - MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON]? 0x8000: 0; - MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON]? 0x8000: 0; - MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON]? 0x8000: 0; + memcpy(QueueKeyStateTable, lpKeyState, 256); + MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0; + MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0; + MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0; } } @@ -92,13 +105,13 @@ int GetAsyncKeyState(int nKey) break; default: retval = AsyncKeyStateTable[nKey] | - (KeyStateTable[nKey] ? 0x8000 : 0); + (InputKeyStateTable[nKey] ? 0x8000 : 0); break; } memset( AsyncMouseButtonsStates, 0, 3 ); /* all states to false */ memset( AsyncKeyStateTable, 0, 256 ); + dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval); return retval; } - diff --git a/windows/message.c b/windows/message.c index 4ac32f3fb89..77ee2f9fb13 100644 --- a/windows/message.c +++ b/windows/message.c @@ -32,16 +32,15 @@ #define HWND_BROADCAST16 ((HWND16)0xffff) #define HWND_BROADCAST32 ((HWND32)0xffffffff) -#define ASCII_CHAR_HACK 0x0800 - typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, SYSQ_MSG_ACCEPT } SYSQ_STATUS; -extern WPARAM16 lastEventChar; /* event.c */ extern BOOL MouseButtonsStates[3]; extern BOOL AsyncMouseButtonsStates[3]; -extern BYTE KeyStateTable[256]; +extern BYTE InputKeyStateTable[256]; extern BYTE AsyncKeyStateTable[256]; +BYTE QueueKeyStateTable[256]; + extern MESSAGEQUEUE *pCursorQueue; /* queue.c */ extern MESSAGEQUEUE *pActiveQueue; @@ -292,24 +291,10 @@ static void MSG_JournalRecordMsg( MSG16 *msg ) SEGPTR_FREE(event); } -/***************************************************************** - * MSG_JournalPlayBackIsAscii - */ -static BOOL MSG_JournalPlayBackIsAscii(WPARAM16 wParam) -{ - return ((wParam>VK_HELP && wParammessage == WM_KEYDOWN || tmpMsg->message == WM_SYSKEYDOWN) { for (keyDown=i=0; i<256 && !keyDown; i++) - if (KeyStateTable[i] & 0x80) + if (InputKeyStateTable[i] & 0x80) keyDown++; if (!keyDown) lParam |= 0x40000000; - AsyncKeyStateTable[wParam]=KeyStateTable[wParam] |= 0x80; - if (MSG_JournalPlayBackIsAscii(wParam)) - { - lastEventChar= wParam; /* control TranslateMessage() */ - lParam |= (LONG)((LONG)ASCII_CHAR_HACK*0x10000L); - - if (!(KeyStateTable[VK_SHIFT] & 0x80) && - !(KeyStateTable[VK_CAPITAL] & 0x80)) - lastEventChar= tolower(lastEventChar); - if (KeyStateTable[VK_CONTROL] & 0x80) - lastEventChar&=0x1f; - } + AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] |= 0x80; } else /* WM_KEYUP, WM_SYSKEYUP */ { lParam |= 0xC0000000; - AsyncKeyStateTable[wParam]=KeyStateTable[wParam] &= ~0x80; + AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] &= ~0x80; } - if (KeyStateTable[VK_MENU] & 0x80) + if (InputKeyStateTable[VK_MENU] & 0x80) lParam |= 0x20000000; if (tmpMsg->paramH & 0x8000) /*special_key bit*/ lParam |= 0x01000000; @@ -373,9 +347,9 @@ static int MSG_JournalPlayBackMsg(void) case WM_RBUTTONDOWN:MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=1;break; case WM_RBUTTONUP: MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=0;break; } - AsyncKeyStateTable[VK_LBUTTON]= KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] << 8; - AsyncKeyStateTable[VK_MBUTTON]= KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] << 8; - AsyncKeyStateTable[VK_RBUTTON]= KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] << 8; + AsyncKeyStateTable[VK_LBUTTON]= InputKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] << 8; + AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] << 8; + AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] << 8; SetCursorPos(tmpMsg->paramL,tmpMsg->paramH); lParam=MAKELONG(tmpMsg->paramL,tmpMsg->paramH); wParam=0; @@ -644,7 +618,7 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last, /* First handle a message put by SendMessage() */ - if (msgQueue->wakeBits & QS_SENDMESSAGE) + while (msgQueue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( msgQueue ); /* Now handle a WM_QUIT message @@ -661,6 +635,7 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last, msg->message = WM_QUIT; msg->wParam = msgQueue->wExitCode; msg->lParam = 0; + if( !peek ) msgQueue->wPostQMsg = 0; break; } @@ -695,7 +670,7 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last, /* Check again for SendMessage */ - if (msgQueue->wakeBits & QS_SENDMESSAGE) + while (msgQueue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( msgQueue ); /* Now find a WM_PAINT message */ @@ -734,7 +709,7 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last, if (!(flags & PM_NOYIELD)) { UserYield(); - if (msgQueue->wakeBits & QS_SENDMESSAGE) + while (msgQueue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( msgQueue ); } if ((msgQueue->wakeBits & mask) & QS_TIMER) @@ -752,6 +727,21 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last, } /* We got a message */ + if (flags & PM_REMOVE) + { + WORD message = msg->message; + + if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) + { + BYTE *p = &QueueKeyStateTable[msg->wParam & 0xff]; + + if (!(*p & 0x80)) + *p ^= 0x01; + *p |= 0x80; + } + else if (message == WM_KEYUP || message == WM_SYSKEYUP) + QueueKeyStateTable[msg->wParam & 0xff] &= ~0x80; + } if (peek) return TRUE; else return (msg->message != WM_QUIT); } @@ -1013,7 +1003,7 @@ LRESULT SendMessage32A(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam) if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1) return 0; ret = SendMessage16( hwnd, msg16, wParam16, lParam ); - WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam ); + WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam ); return ret; } @@ -1088,32 +1078,42 @@ void WaitMessage( void ) /*********************************************************************** * TranslateMessage (USER.113) * - * This should call ToAscii but it is currently broken + * TranlateMessage translate virtual-key messages into character-messages, + * as follows : + * WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message. + * ditto replacing WM_* with WM_SYS* + * This produces WM_CHAR messages only for keys mapped to ASCII characters + * by the keyboard driver. */ BOOL TranslateMessage( LPMSG16 msg ) { UINT message = msg->message; - /* BYTE wparam[2]; */ + BYTE wparam[2]; - if ((message == WM_KEYDOWN) || (message == WM_KEYUP) || - (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP)) + if ((debugging_msg + && message != WM_MOUSEMOVE && message != WM_TIMER) + || (debugging_key + && message >= WM_KEYFIRST && message <= WM_KEYLAST)) + fprintf(stddeb, "TranslateMessage(%s, %04x, %08lx)\n", + SPY_GetMsgName(msg->message), msg->wParam, msg->lParam); + if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN)) { - dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam, - HIWORD(msg->lParam) ); + if (debugging_msg || debugging_key) + fprintf(stddeb, "Translating key %04x, scancode %04x\n", + msg->wParam, HIWORD(msg->lParam) ); - if( HIWORD(msg->lParam) & ASCII_CHAR_HACK ) - - /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable, - wparam, 0 ) ) - */ + /* FIXME : should handle ToAscii yielding 2 */ + if (ToAscii(msg->wParam, HIWORD(msg->lParam), (LPSTR)&QueueKeyStateTable, + wparam, 0)) { - message += 2 - (message & 0x0001); + /* Map WM_KEY* to WM_*CHAR */ + message += 2 - (message & 0x0001); - PostMessage( msg->hwnd, message, lastEventChar, msg->lParam ); + PostMessage( msg->hwnd, message, wparam[0], msg->lParam ); - return TRUE; + return TRUE; } } return FALSE; diff --git a/windows/painting.c b/windows/painting.c index b41a6e9944a..43af442660d 100644 --- a/windows/painting.c +++ b/windows/painting.c @@ -590,20 +590,28 @@ INT16 GetUpdateRgn( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase ) */ INT16 ExcludeUpdateRgn( HDC32 hdc, HWND32 hwnd ) { - INT32 retval = ERROR; - HRGN32 hrgn; + RECT16 rect; WND * wndPtr; if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR; - if ((hrgn = CreateRectRgn32( 0, 0, 0, 0 )) != 0) + + if (wndPtr->hrgnUpdate) { - retval = CombineRgn32( hrgn, InquireVisRgn(hdc), - (wndPtr->hrgnUpdate>1) ? wndPtr->hrgnUpdate : 0, - (wndPtr->hrgnUpdate>1) ? RGN_DIFF : RGN_COPY ); - if (retval) SelectVisRgn( hdc, hrgn ); + INT16 ret; + HRGN32 hrgn = CreateRectRgn32(wndPtr->rectWindow.left - wndPtr->rectClient.left, + wndPtr->rectWindow.top - wndPtr->rectClient.top, + wndPtr->rectClient.right - wndPtr->rectClient.left, + wndPtr->rectClient.bottom - wndPtr->rectClient.top); + if( wndPtr->hrgnUpdate > 1 ) + CombineRgn32(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY); + + /* do ugly coordinate translations in dce.c */ + + ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn ); DeleteObject32( hrgn ); - } - return retval; + return ret; + } + return GetClipBox16(hdc, &rect); } diff --git a/windows/queue.c b/windows/queue.c index aeff35cb3fa..83a8c7d2327 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -5,10 +5,12 @@ */ #include +#include #include "module.h" #include "queue.h" #include "task.h" #include "win.h" +#include "hook.h" #include "stddebug.h" #include "debug.h" @@ -22,6 +24,8 @@ static MESSAGEQUEUE *sysMsgQueue = NULL; static MESSAGEQUEUE *pMouseQueue = NULL; /* Queue for last mouse message */ static MESSAGEQUEUE *pKbdQueue = NULL; /* Queue for last kbd message */ +extern void SIGNAL_MaskAsyncEvents(BOOL32); + MESSAGEQUEUE *pCursorQueue = NULL; MESSAGEQUEUE *pActiveQueue = NULL; @@ -137,6 +141,9 @@ static HQUEUE16 QUEUE_CreateMsgQueue( int size ) * QUEUE_DeleteMsgQueue * * Unlinks and deletes a message queue. + * + * Note: We need to mask asynchronous events to make sure PostMessage works + * even in the signal handler. */ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ) { @@ -165,6 +172,8 @@ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ) senderQ = sq->hPrevSendingTask; } + SIGNAL_MaskAsyncEvents( TRUE ); + pPrev = &hFirstQueue; while (*pPrev && (*pPrev != hQueue)) { @@ -173,6 +182,9 @@ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ) } if (*pPrev) *pPrev = msgQueue->next; msgQueue->self = 0; + + SIGNAL_MaskAsyncEvents( FALSE ); + GlobalFree16( hQueue ); return 1; } @@ -333,6 +345,39 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue ) dprintf_msg(stddeb,"ReceiveMessage: done!\n"); } +/*********************************************************************** + * QUEUE_FlushMessage + * + * Try to reply to all pending sent messages on exit. + */ +void QUEUE_FlushMessages( HQUEUE16 hQueue ) +{ + MESSAGEQUEUE *queue = (MESSAGEQUEUE*)GlobalLock16( hQueue ); + + if( queue ) + { + MESSAGEQUEUE *senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask); + QSMCTRL* CtrlPtr = queue->smResultCurrent; + + while( senderQ ) + { + if( !(queue->hSendingTask = senderQ->hPrevSendingTask) ) + queue->wakeBits &= ~QS_SENDMESSAGE; + QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE ); + + queue->smResultCurrent = CtrlPtr; + while( senderQ->wakeBits & QS_SMRESULT ) OldYield(); + + senderQ->SendMessageReturn = 0; + senderQ->smResult = queue->smResultCurrent; + QUEUE_SetWakeBit( senderQ, QS_SMRESULT); + + if( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask)) ) + CtrlPtr = senderQ->smResultInit; + } + queue->InSendMessageHandle = 0; + } +} /*********************************************************************** * QUEUE_AddMsg @@ -344,12 +389,15 @@ BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG16 * msg, DWORD extraInfo ) int pos; MESSAGEQUEUE *msgQueue; + SIGNAL_MaskAsyncEvents( TRUE ); + if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE; pos = msgQueue->nextFreeMessage; /* Check if queue is full */ if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0)) { + SIGNAL_MaskAsyncEvents( FALSE ); fprintf(stderr,"MSG_AddMsg // queue is full !\n"); return FALSE; } @@ -361,6 +409,9 @@ BOOL32 QUEUE_AddMsg( HQUEUE16 hQueue, MSG16 * msg, DWORD extraInfo ) else pos = 0; msgQueue->nextFreeMessage = pos; msgQueue->msgCount++; + + SIGNAL_MaskAsyncEvents( FALSE ); + QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE ); return TRUE; } @@ -403,6 +454,8 @@ int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND32 hwnd, int first, int last ) */ void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos ) { + SIGNAL_MaskAsyncEvents( TRUE ); + if (pos >= msgQueue->nextMessage) { for ( ; pos > msgQueue->nextMessage; pos--) @@ -420,6 +473,8 @@ void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos ) } msgQueue->msgCount--; if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE; + + SIGNAL_MaskAsyncEvents( FALSE ); } @@ -633,12 +688,18 @@ BOOL SetMessageQueue( int size ) } queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue ); + SIGNAL_MaskAsyncEvents( TRUE ); + /* Copy data and free the old message queue */ if ((hQueue = GetTaskQueue(0)) != 0) { MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue ); memcpy( &queuePtr->reserved2, &oldQ->reserved2, (int)oldQ->messages - (int)(&oldQ->reserved2) ); + HOOK_ResetQueueHooks( hNewQueue ); + if( WIN_GetDesktop()->hmemTaskQ == hQueue ) + WIN_GetDesktop()->hmemTaskQ = hNewQueue; + WIN_ResetQueueWindows( WIN_GetDesktop()->child, hQueue, hNewQueue ); QUEUE_DeleteMsgQueue( hQueue ); } @@ -648,8 +709,9 @@ BOOL SetMessageQueue( int size ) hFirstQueue = hNewQueue; if( !queuePtr->next ) pCursorQueue = queuePtr; - SetTaskQueue( 0, hNewQueue ); + + SIGNAL_MaskAsyncEvents( FALSE ); return TRUE; } diff --git a/windows/scroll.c b/windows/scroll.c index 71ecc9826b9..b416537a500 100644 --- a/windows/scroll.c +++ b/windows/scroll.c @@ -162,7 +162,7 @@ BOOL32 ScrollDC32( HDC32 hdc, INT32 dx, INT32 dy, const RECT32 *rc, if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom ) return FALSE; - hrgnClip = GetClipRgn(hdc); + hrgnClip = GetClipRgn16(hdc); hrgnScrollClip = CreateRectRgnIndirect32(&rectClip); if( hrgnClip ) diff --git a/windows/syscolor.c b/windows/syscolor.c index 7441be16317..596eceb394b 100644 --- a/windows/syscolor.c +++ b/windows/syscolor.c @@ -137,7 +137,7 @@ void SYSCOLOR_Init(void) for (i = 0, p = DefSysColors; i < NUM_SYS_COLORS; i++, p += 2) { - GetProfileString( "colors", p[0], p[1], buffer, 100 ); + GetProfileString32A( "colors", p[0], p[1], buffer, 100 ); if (!sscanf( buffer, " %d %d %d", &r, &g, &b )) r = g = b = 0; SYSCOLOR_SetColor( i, RGB(r,g,b) ); } diff --git a/windows/sysmetrics.c b/windows/sysmetrics.c index 64b80dc836a..5325a86b486 100644 --- a/windows/sysmetrics.c +++ b/windows/sysmetrics.c @@ -51,15 +51,15 @@ void SYSMETRICS_Init(void) sysMetrics[SM_CYMIN] = SYSMETRICS_CYMIN; sysMetrics[SM_CXSIZE] = SYSMETRICS_CXSIZE; sysMetrics[SM_CYSIZE] = SYSMETRICS_CYSIZE; - sysMetrics[SM_CXFRAME] = GetProfileInt( "windows", "BorderWidth", 4 ); + sysMetrics[SM_CXFRAME] = GetProfileInt32A( "windows", "BorderWidth", 4 ); sysMetrics[SM_CYFRAME] = sysMetrics[SM_CXFRAME]; sysMetrics[SM_CXMINTRACK] = SYSMETRICS_CXMINTRACK; sysMetrics[SM_CYMINTRACK] = SYSMETRICS_CYMINTRACK; - sysMetrics[SM_CXDOUBLECLK] = (GetProfileInt( "windows","DoubleClickWidth", 4) + 1) & ~1; - sysMetrics[SM_CYDOUBLECLK] = (GetProfileInt( "windows","DoubleClickHeight", 4) + 1) & ~1; - sysMetrics[SM_CXICONSPACING] = GetProfileInt( "desktop","IconSpacing", 75); - sysMetrics[SM_CYICONSPACING] = GetProfileInt( "desktop","IconVerticalSpacing", 72); - sysMetrics[SM_MENUDROPALIGNMENT] = GetProfileInt( "windows","MenuDropAlignment", 0 ); + sysMetrics[SM_CXDOUBLECLK] = (GetProfileInt32A( "windows","DoubleClickWidth", 4) + 1) & ~1; + sysMetrics[SM_CYDOUBLECLK] = (GetProfileInt32A( "windows","DoubleClickHeight", 4) + 1) & ~1; + sysMetrics[SM_CXICONSPACING] = GetProfileInt32A( "desktop","IconSpacing", 75); + sysMetrics[SM_CYICONSPACING] = GetProfileInt32A( "desktop","IconVerticalSpacing", 72); + sysMetrics[SM_MENUDROPALIGNMENT] = GetProfileInt32A( "windows","MenuDropAlignment", 0 ); sysMetrics[SM_PENWINDOWS] = 0; sysMetrics[SM_DBCSENABLED] = 0; sysMetrics[SM_CMETRICS] = SM_CMETRICS; diff --git a/windows/win.c b/windows/win.c index f9b70eecfae..2b48de3f6db 100644 --- a/windows/win.c +++ b/windows/win.c @@ -374,24 +374,24 @@ static void WIN_DestroyWindow( WND* wndPtr ) USER_HEAP_FREE( hwnd ); } - /*********************************************************************** - * WIN_DestroyQueueWindows + * WIN_ResetQueueWindows */ -void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue ) +void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew ) { WND* next; while (wnd) { next = wnd->next; - if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf ); - else WIN_DestroyQueueWindows( wnd->child, hQueue ); + if (wnd->hmemTaskQ == hQueue) + if( hNew ) wnd->hmemTaskQ = hNew; + else DestroyWindow( wnd->hwndSelf ); + else WIN_ResetQueueWindows( wnd->child, hQueue, hNew ); wnd = next; } } - /*********************************************************************** * WIN_CreateDesktopWindow * @@ -736,8 +736,12 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom, } else wndPtr->wIDmenu = (UINT)cs->hMenu; - /* Send the WM_CREATE message */ + /* Send the WM_CREATE message + * Perhaps we shouldn't allow width/height changes as well. + * See p327 in "Internals". + */ + maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top; if (unicode) { if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1; @@ -745,6 +749,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom, { WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow, NULL, NULL, 0, &wndPtr->rectClient ); + OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left, + maxPos.y - wndPtr->rectWindow.top); wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs ); } } @@ -755,6 +761,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom, { WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow, NULL, NULL, 0, &wndPtr->rectClient ); + OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left, + maxPos.y - wndPtr->rectWindow.top); wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs ); } } @@ -799,7 +807,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom, { /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */ - POINT16 maxSize, maxPos, minTrack, maxTrack; NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack ); SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y, ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED ); diff --git a/windows/winproc.c b/windows/winproc.c index aa212e77f48..2fa5f5dbbe1 100644 --- a/windows/winproc.c +++ b/windows/winproc.c @@ -964,6 +964,82 @@ INT32 WINPROC_MapMsg32ATo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16, case BM_SETSTYLE32: *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32); return 0; + case LB_CARETOFF32: + case LB_CARETON32: + case LB_DELETESTRING32: + case LB_GETANCHORINDEX32: + case LB_GETCARETINDEX32: + case LB_GETCOUNT32: + case LB_GETCURSEL32: + case LB_GETHORIZONTALEXTENT32: + case LB_GETITEMDATA32: + case LB_GETITEMHEIGHT32: + case LB_GETSEL32: + case LB_GETSELCOUNT32: + case LB_GETTEXTLEN32: + case LB_GETTOPINDEX32: + case LB_RESETCONTENT32: + case LB_SELITEMRANGE32: + case LB_SELITEMRANGEEX32: + case LB_SETANCHORINDEX32: + case LB_SETCARETINDEX32: + case LB_SETCOLUMNWIDTH32: + case LB_SETCURSEL32: + case LB_SETHORIZONTALEXTENT32: + case LB_SETITEMDATA32: + case LB_SETITEMHEIGHT32: + case LB_SETSEL32: + case LB_SETTOPINDEX32: + *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32); + return 0; + case LB_ADDSTRING32: + case LB_FINDSTRING32: + case LB_FINDSTRINGEXACT32: + case LB_INSERTSTRING32: + case LB_SELECTSTRING32: + case LB_DIR32: + case LB_ADDFILE32: +/* case LB_GETTEXT32: FIXME */ + { + LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam ); + if (!str) return -1; + *plparam = (LPARAM)SEGPTR_GET(str); + } + *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32); + return 1; + case LB_GETITEMRECT32: + { + RECT16 *rect; + rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) ); + if (!rect) return -1; + *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */ + *plparam = (LPARAM)SEGPTR_GET(rect); + } + return 1; + case LB_GETSELITEMS32: + { + LPINT16 items; + *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */ + if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16) + + sizeof(LPARAM)))) return -1; + *((LPARAM *)items)++ = *plparam; /* Store the previous lParam */ + *plparam = (LPARAM)SEGPTR_GET(items); + } + return 1; + case LB_SETTABSTOPS32: + if (wParam32) + { + INT32 i; + LPINT16 stops; + *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */ + if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16) + + sizeof(LPARAM)))) return -1; + for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i); + *plparam = (LPARAM)SEGPTR_GET(stops); + return 1; + } + *pmsg16 = LB_SETTABSTOPS16; + return 0; case WM_ACTIVATE: case WM_CHARTOITEM: case WM_COMMAND: @@ -1173,15 +1249,41 @@ INT32 WINPROC_MapMsg32ATo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16, * * Unmap a message that was mapped from 32-bit Ansi to 16-bit. */ -void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam ) +void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam ) { switch(msg) { + case LB_ADDFILE32: + case LB_ADDSTRING32: + case LB_DIR32: + case LB_FINDSTRING32: + case LB_FINDSTRINGEXACT32: + case LB_INSERTSTRING32: + case LB_SELECTSTRING32: + case LB_SETTABSTOPS32: case WM_COMPAREITEM: case WM_DELETEITEM: case WM_DRAWITEM: + case WM_SETTEXT: SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) ); break; + case LB_GETITEMRECT32: + { + RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(lParam); + lParam = *(LPARAM *)(rect + 1); + CONV_RECT16TO32( rect, (RECT32 *)lParam ); + SEGPTR_FREE( rect ); + } + break; + case LB_GETSELITEMS32: + { + INT32 i; + LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam); + lParam = *((LPARAM *)items - 1); + for (i = 0; i < wParam; i++) *((LPINT32)lParam + i) = items[i]; + SEGPTR_FREE( (LPARAM *)items - 1 ); + } + break; case WM_MEASUREITEM: { MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam); @@ -1242,9 +1344,6 @@ void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam ) SEGPTR_FREE( cs ); } break; - case WM_SETTEXT: - SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) ); - break; case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: { @@ -1269,6 +1368,22 @@ INT32 WINPROC_MapMsg32WTo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16, { switch(msg32) { + case LB_ADDSTRING32: + case LB_FINDSTRING32: + case LB_FINDSTRINGEXACT32: + case LB_INSERTSTRING32: + case LB_SELECTSTRING32: + case LB_DIR32: + case LB_ADDFILE32: + { + LPSTR str = SEGPTR_ALLOC( lstrlen32W((LPWSTR)*plparam) + 1 ); + if (!str) return -1; + STRING32_UniToAnsi( str, (LPWSTR)*plparam ); + *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32); + *pwparam16 = (WPARAM16)LOWORD(wParam32); + *plparam = (LPARAM)SEGPTR_GET(str); + } + return 1; case WM_NCCREATE: case WM_CREATE: { @@ -1344,7 +1459,7 @@ INT32 WINPROC_MapMsg32WTo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16, * * Unmap a message that was mapped from 32-bit Unicode to 16-bit. */ -void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam ) +void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam ) { switch(msg) { @@ -1461,7 +1576,7 @@ static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd, if (wndPtr) CURRENT_DS = wndPtr->hInstance; result = CallWndProc16( func, hwnd, msg16, wParam16, lParam ); CURRENT_DS = ds; - WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam ); + WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam ); return result; } @@ -1486,7 +1601,7 @@ static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd, if (wndPtr) CURRENT_DS = wndPtr->hInstance; result = CallWndProc16( func, hwnd, msg16, wParam16, lParam ); CURRENT_DS = ds; - WINPROC_UnmapMsg32WTo16( msg16, wParam16, lParam ); + WINPROC_UnmapMsg32WTo16( msg, wParam16, lParam ); return result; } diff --git a/wine.man b/wine.man index 3e71c1a7e7b..02471645145 100644 --- a/wine.man +++ b/wine.man @@ -9,7 +9,7 @@ wine \- run Windows programs under Unix ] .I program_name [ -.I arguments +.I program_name... ] .SH DESCRIPTION .B wine