]> git.saurik.com Git - wxWidgets.git/commitdiff
1. wxThread changes (detached/joinable) for MSW and docs updates
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 27 Nov 1999 22:57:06 +0000 (22:57 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 27 Nov 1999 22:57:06 +0000 (22:57 +0000)
2. wxUSE_GUI=0 compilation for MSW (use vc6dll.t with tmake) and many small
   fixes related to this
3. an attempt to make wxLog more MT friendly
4. a small fix for wxRegConfig: it doesn't create empty unused keys any
   more (SetPath() would always create a key, now it's deleted if it was
   empty)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4712 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

24 files changed:
distrib/msw/tmake/filelist.txt
distrib/msw/tmake/vc6.t
distrib/msw/tmake/vc6base.t [new file with mode: 0644]
distrib/msw/tmake/vc6dll.t
include/wx/app.h
include/wx/msw/private.h
include/wx/msw/winundef.h
include/wx/thread.h
include/wx/utils.h
samples/console/console.cpp
samples/thread/test.cpp
src/common/appcmn.cpp
src/common/event.cpp
src/common/init.cpp
src/common/log.cpp
src/common/mimetype.cpp
src/common/string.cpp
src/msw/app.cpp
src/msw/main.cpp
src/msw/regconf.cpp
src/msw/thread.cpp
src/msw/utils.cpp
src/msw/utilsexc.cpp
src/unix/threadpsx.cpp

index 5b66d38147bd2528a9b0e42e8f26d61af6aed945..1d196a9b9156319ee56da659e91a742b6daf66f8 100644 (file)
@@ -239,7 +239,7 @@ iniconf.cpp M       16
 joystick.cpp   M
 listbox.cpp    M
 listctrl.cpp   M       32
-main.cpp       M
+main.cpp       M       B
 mdi.cpp        M
 menu.cpp       M
 menuitem.cpp   M
@@ -258,9 +258,9 @@ printdlg.cpp        M
 printwin.cpp   M
 radiobox.cpp   M
 radiobut.cpp   M
-regconf.cpp    M       32
+regconf.cpp    M       32,B
 region.cpp     M
-registry.cpp   M       32
+registry.cpp   M       32,B
 scrolbar.cpp   M
 settings.cpp   M
 slider95.cpp   M       32
@@ -277,12 +277,12 @@ taskbar.cpp       M       32
 tbar95.cpp     M       32
 tbarmsw.cpp    M       16
 textctrl.cpp   M
-thread.cpp     M       32
+thread.cpp     M       32,B
 timer.cpp      M
 tooltip.cpp    M       32
 treectrl.cpp   M       32
-utils.cpp      M
-utilsexc.cpp   M
+utils.cpp      M       B
+utilsexc.cpp   M       B
 uuid.cpp       M       O
 wave.cpp       M
 window.cpp     M
@@ -292,7 +292,7 @@ gsocket.c   M       S
 dialup.cpp     U
 fontenum.cpp   U
 fontutil.cpp   U
-threadpsx.cpp  U
+threadpsx.cpp  U       B
 utilsunx.cpp   U       B
 gsocket.c      U
 
index 79796d7e75d1e24be29a5450d7412de915a1f749..fb73d3dee89ba8103b12de4846aacccf43bd226e 100644 (file)
@@ -81,7 +81,7 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
+# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=1 /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
 # ADD BASE RSC /l 0x409
 # ADD RSC /l 0x409
 BSC32=bscmake.exe
@@ -104,7 +104,7 @@ LIB32=link.exe -lib
 # PROP Intermediate_Dir "Debug"
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
+# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D wxUSE_GUI=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
 # ADD BASE RSC /l 0x409
 # ADD RSC /l 0x409
 BSC32=bscmake.exe
diff --git a/distrib/msw/tmake/vc6base.t b/distrib/msw/tmake/vc6base.t
new file mode 100644 (file)
index 0000000..35ad0ad
--- /dev/null
@@ -0,0 +1,145 @@
+#!#############################################################################
+#! File:    vc6base.t
+#! Purpose: tmake template file from which wxBase.dsp is generated by running
+#!          tmake -t vc6base wxwin.pro -o wxBase.dsp
+#! Author:  Vadim Zeitlin
+#! Created: 27.11.99
+#! Version: $Id$
+#!#############################################################################
+#${
+    #! include the code which parses filelist.txt file and initializes
+    #! %wxCommon, %wxGeneric and %wxMSW hashes.
+    IncludeTemplate("filelist.t");
+
+    #! now transform these hashes into $project tags
+    foreach $file (sort keys %wxCommon) {
+       next if $wxCommon{$file} !~ /\bB\b/;
+
+        my $tag = $file =~ /\.c$/ ? "WXCSRCS" : "WXCOMMONSRCS";
+        $project{$tag} .= $file . " "
+    }
+
+    foreach $file (sort keys %wxMSW) {
+       next if $wxMSW{$file} !~ /\bB\b/;
+
+        my $tag = $file =~ /\.c$/ ? "WXMSWCSRCS" : "WXMSWSRCS";
+        $project{$tag} .= $file . " "
+    }
+
+    foreach $file (sort keys %wxBase) {
+        my $tag = $file =~ /\.c$/ ? "WXCSRCS" : "WXCOMMONSRCS";
+        $project{$tag} .= $file . " "
+    }
+#$}
+# Microsoft Developer Studio Project File - Name="wxBase" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=wxBase - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "wxBase.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "wxBase.mak" CFG="wxBase - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "wxBase - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "wxBase - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "wxBase - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /Zi /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=0 /D WIN95=1 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN32__" /Yu"wx/wxprec.h" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "wxBase - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W4 /Zi /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D DEBUG=1 /D WXDEBUG=1 /D "__WXDEBUG__" /D wxUSE_GUI=0 /D "__WIN95__" /D "WIN32" /D "_WIN32" /D WINVER=0x400 /D "__WINDOWS__" /D "__WIN32__" /D "__WXMSW__" /Fr /Yu"wx/wxprec.h" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /o"lib/wxBase.bsc"
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "wxBase - Win32 Release"
+# Name "wxBase - Win32 Debug"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\msw\dummy.cpp
+# ADD CPP /Yc"wx/wxprec.h"
+# End Source File
+#$ ExpandGlue("WXCOMMONSRCS", "# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# End Source File\n");
+#$ ExpandGlue("WXMSWSRCS", "# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# End Source File\n");
+#$ ExpandGlue("WXCSRCS", "# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n");
+#$ ExpandGlue("WXMSWCSRCS", "# Begin Source File\n\nSOURCE=.\\src\\msw\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n# Begin Source File\n\nSOURCE=.\\src\\common\\", "\n# SUBTRACT CPP /YX /Yc /Yu\n# End Source File\n");
+
+# Begin Source File
+
+SOURCE=.\src\common\y_tab.c
+
+!IF  "$(CFG)" == "wxBase - Win32 Release"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "wxBase - Win32 Debug"
+
+# ADD CPP /W1
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF 
+
+# End Source File
+# End Target
+# End Project
index ce5182d4f9a8b4ffc8b6ca1ee40b8b62b3b7fc37..fb98ecfa6be33f3fca8ca193bb90f67dcc76086f 100644 (file)
@@ -83,7 +83,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MT /W4 /GX /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /c
+# ADD CPP /nologo /MT /W4 /GX /O2 /I "$(wx)\include" /I "$(wx)\src\zlib" /D "NDEBUG" /D wxUSE_GUI=1 /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -109,7 +109,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /ZI /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D "__WXDEBUG__" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /ZI /Od /I "$(wx)\include" /I "$(wx)\src\zlib" /D "_DEBUG" /D "__WXDEBUG__" /D wxUSE_GUI=1 /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WXWINDLL_EXPORTS" /D "__WXMSW__" /D "__WIN95__" /D "__WINDOWS__" /D "__WIN32__" /D "WXMAKINGDLL" /Yu"wx/wxprec.h" /FD /GZ /c
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
index 51d126b8ea444cba04972a5224c5febbb64a2b9a..5341e7d2b12ca0b153017fd564a9c34c7172819b 100644 (file)
@@ -282,7 +282,10 @@ protected:
         #include "wx/stubs/app.h"
     #endif
 #else // !GUI
-    typedef wxAppBase wxApp;
+    // can't use typedef because wxApp forward declared as a class
+    class WXDLLEXPORT wxApp : public wxAppBase
+    {
+    };
 #endif // GUI/!GUI
 
 // ----------------------------------------------------------------------------
@@ -322,13 +325,13 @@ inline void WXDLLEXPORT wxPostEvent(wxEvtHandler *dest, wxEvent& event)
     dest->AddPendingEvent(event);
 }
 
-#endif // wxUSE_GUI/!wxUSE_GUI
+#endif // wxUSE_GUI
 
 // console applications may avoid using DECLARE_APP and IMPLEMENT_APP macros
 // and call these functions instead at the program startup and termination
 // -------------------------------------------------------------------------
 
-#if wxUSE_NOGUI
+#if !wxUSE_GUI
 
 // initialize the library (may be called as many times as needed, but each
 // call to wxInitialize() must be matched by wxUninitialize())
@@ -338,7 +341,7 @@ extern bool WXDLLEXPORT wxInitialize();
 // wxUninitialize()
 extern void WXDLLEXPORT wxUninitialize();
 
-#endif // wxUSE_NOGUI
+#endif // !wxUSE_GUI
 
 // ----------------------------------------------------------------------------
 // macros for dynamic creation of the application object
index 981189b3ffe551646d0828ecced02bff5ef3ba2b..d43c09dd936602a4305f04688efed23f5c0be57e 100644 (file)
@@ -43,6 +43,8 @@ static const double pt2mm = (1/(METRIC_CONVERSION_CONSTANT*72));
 // standard icons from the resources
 // ---------------------------------------------------------------------------
 
+#if wxUSE_GUI
+
 WXDLLEXPORT_DATA(extern HICON) wxSTD_FRAME_ICON;
 WXDLLEXPORT_DATA(extern HICON) wxSTD_MDIPARENTFRAME_ICON;
 WXDLLEXPORT_DATA(extern HICON) wxSTD_MDICHILDFRAME_ICON;
@@ -51,6 +53,8 @@ WXDLLEXPORT_DATA(extern HICON) wxDEFAULT_MDIPARENTFRAME_ICON;
 WXDLLEXPORT_DATA(extern HICON) wxDEFAULT_MDICHILDFRAME_ICON;
 WXDLLEXPORT_DATA(extern HFONT) wxSTATUS_LINE_FONT;
 
+#endif // wxUSE_GUI
+
 // ---------------------------------------------------------------------------
 // define things missing from some compilers' headers
 // ---------------------------------------------------------------------------
@@ -268,9 +272,13 @@ private:
 // global data
 // ---------------------------------------------------------------------------
 
+#if 0 // where is this??
 // The MakeProcInstance version of the function wxSubclassedGenericControlProc
 WXDLLEXPORT_DATA(extern FARPROC) wxGenericControlSubClassProc;
+#endif // 0
+
 WXDLLEXPORT_DATA(extern wxChar*) wxBuffer;
+
 WXDLLEXPORT_DATA(extern HINSTANCE) wxhInstance;
 
 // ---------------------------------------------------------------------------
@@ -279,11 +287,13 @@ WXDLLEXPORT_DATA(extern HINSTANCE) wxhInstance;
 
 extern "C"
 {
-WXDLLEXPORT HINSTANCE wxGetInstance();
+    WXDLLEXPORT HINSTANCE wxGetInstance();
 }
 
 WXDLLEXPORT void wxSetInstance(HINSTANCE hInst);
 
+#if wxUSE_GUI
+
 WXDLLEXPORT wxWindow* wxFindWinFromHandle(WXHWND hWnd);
 
 WXDLLEXPORT void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font);
@@ -316,5 +326,7 @@ inline bool wxStyleHasBorder(long style)
                    wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
 }
 
+#endif // wxUSE_GUI
+
 #endif
     // _WX_PRIVATE_H_
index 04ab36ae4da5f713142a207114ec0ba721ef270b..e580f2465070e6e03dd274880b0da3bf979f3a88 100644 (file)
     }
 #endif
 
+// FindResource
+#ifdef FindResource
+    #undef FindResource
+    inline HRSRC FindResource(HMODULE hModule, LPCTSTR lpName, LPCTSTR lpType)
+    {
+    #ifdef _UNICODE
+        return FindResourceW(hModule, lpName, lpType);
+    #else
+        return FindResourceA(hModule, lpName, lpType);
+    #endif
+    }
+#endif
+
 // IsMaximized
 
 #ifdef IsMaximized
index 641ce6330b823a4d62b32a45aa3200b043571c12..3f1415adc7830ec7563d2bd61b7104a36f084dbc 100644 (file)
@@ -53,9 +53,16 @@ enum wxThreadError
   wxTHREAD_NO_RESOURCE,       // No resource left to create a new thread
   wxTHREAD_RUNNING,           // The thread is already running
   wxTHREAD_NOT_RUNNING,       // The thread isn't running
+  wxTHREAD_KILLED,            // Thread we waited for had to be killed
   wxTHREAD_MISC_ERROR         // Some other error
 };
 
+enum wxThreadKind
+{
+    wxTHREAD_DETACHED,
+    wxTHREAD_JOINABLE
+};
+
 // defines the interval of priority
 enum
 {
@@ -231,15 +238,18 @@ private:
 };
 
 // ----------------------------------------------------------------------------
-// Thread management class
+// Thread class
 // ----------------------------------------------------------------------------
 
-// FIXME Thread termination model is still unclear. Delete() should probably
-//       have a timeout after which the thread must be Kill()ed.
+// there are two different kinds of threads: joinable and detached (default)
+// ones. Only joinable threads can return a return code and only detached
+// threads auto-delete themselves - the user should delete the joinable
+// threads manually.
 
 // NB: in the function descriptions the words "this thread" mean the thread
 //     created by the wxThread object while "main thread" is the thread created
 //     during the process initialization (a.k.a. the GUI thread)
+
 class wxThreadInternal;
 class WXDLLEXPORT wxThread
 {
@@ -266,34 +276,52 @@ public:
         // NB: at least under MSW worker threads can not call ::wxSleep()!
     static void Sleep(unsigned long milliseconds);
 
-    // default constructor
-    wxThread();
+    // constructor only creates the C++ thread object and doesn't create (or
+    // start) the real thread
+    wxThread(wxThreadKind kind = wxTHREAD_DETACHED);
+
+    // functions that change the thread state: all these can only be called
+    // from _another_ thread (typically the thread that created this one, e.g.
+    // the main thread), not from the thread itself
 
-    // function that change the thread state
         // create a new thread - call Run() to start it
     wxThreadError Create();
 
-        // starts execution of the thread - from the moment Run() is called the
-        // execution of wxThread::Entry() may start at any moment, caller
+        // starts execution of the thread - from the moment Run() is called
+        // the execution of wxThread::Entry() may start at any moment, caller
         // shouldn't suppose that it starts after (or before) Run() returns.
     wxThreadError Run();
 
-        // stops the thread if it's running and deletes the wxThread object
-        // freeing its memory. This function should also be called if the
-        // Create() or Run() fails to free memory (otherwise it will be done by
-        // the thread itself when it terminates). The return value is the
-        // thread exit code if the thread was gracefully terminated, 0 if it
-        // wasn't running and -1 if an error occured.
-    ExitCode Delete();
+        // stops the thread if it's running and deletes the wxThread object if
+        // this is a detached thread freeing its memory - otherwise (for
+        // joinable threads) you still need to delete wxThread object
+        // yourself.
+        //
+        // this function only works if the thread calls TestDestroy()
+        // periodically - the thread will only be deleted the next time it
+        // does it!
+        //
+        // will fill the rc pointer with the thread exit code if it's !NULL
+    wxThreadError Delete(ExitCode *rc = (ExitCode *)NULL);
+
+        // waits for a joinable thread to finish and returns its exit code
+        //
+        // Returns (ExitCode)-1 on error (for example, if the thread is not
+        // joinable)
+    ExitCode Wait();
 
         // kills the thread without giving it any chance to clean up - should
         // not be used in normal circumstances, use Delete() instead. It is a
         // dangerous function that should only be used in the most extreme
-        // cases! The wxThread object is deleted by Kill() if thread was
-        // killed (i.e. no errors occured).
+        // cases!
+        //
+        // The wxThread object is deleted by Kill() if the thread is
+        // detachable, but you still have to delete it manually for joinable
+        // threads.
     wxThreadError Kill();
 
-        // pause a running thread
+        // pause a running thread: as Delete(), this only works if the thread
+        // calls TestDestroy() regularly
     wxThreadError Pause();
 
         // resume a paused thread
@@ -308,10 +336,6 @@ public:
         // Get the current priority.
     unsigned int GetPriority() const;
 
-    // Get the thread ID - a platform dependent number which uniquely
-    // identifies a thread inside a process
-    unsigned long GetID() const;
-
     // thread status inquiries
         // Returns true if the thread is alive: i.e. running or suspended
     bool IsAlive() const;
@@ -320,11 +344,22 @@ public:
         // Returns true if the thread is suspended
     bool IsPaused() const;
 
+        // is the thread of detached kind?
+    bool IsDetached() const { return m_isDetached; }
+
+    // Get the thread ID - a platform dependent number which uniquely
+    // identifies a thread inside a process
+    unsigned long GetId() const;
+
     // called when the thread exits - in the context of this thread
     //
     // NB: this function will not be called if the thread is Kill()ed
     virtual void OnExit() { }
 
+    // dtor is public, but the detached threads should never be deleted - use
+    // Delete() instead (or leave the thread terminate by itself)
+    virtual ~wxThread();
+
 protected:
     // Returns TRUE if the thread was asked to terminate: this function should
     // be called by the thread from time to time, otherwise the main thread
@@ -332,14 +367,7 @@ protected:
     bool TestDestroy();
 
     // exits from the current thread - can be called only from this thread
-    void Exit(void *exitcode = 0);
-
-    // destructor is private - user code can't delete thread objects, they will
-    // auto-delete themselves (and thus must be always allocated on the heap).
-    // Use Delete() or Kill() instead.
-    //
-    // NB: derived classes dtors shouldn't be public neither!
-    virtual ~wxThread();
+    void Exit(ExitCode exitcode = 0);
 
     // entry point for the thread - called by Run() and executes in the context
     // of this thread.
@@ -357,6 +385,9 @@ private:
 
     // protects access to any methods of wxThreadInternal object
     wxCriticalSection m_critsect;
+
+    // true if the thread is detached, false if it is joinable
+    bool m_isDetached;
 };
 
 // ----------------------------------------------------------------------------
@@ -369,9 +400,9 @@ void WXDLLEXPORT wxMutexGuiLeave();
 
 // macros for entering/leaving critical sections which may be used without
 // having to take them inside "#if wxUSE_THREADS"
-#define wxENTER_CRIT_SECT(cs)   (cs)->Enter()
-#define wxLEAVE_CRIT_SECT(cs)   (cs)->Leave()
-#define wxCRIT_SECT_LOCKER(name, cs)  wxCriticalSectionLocker name(*cs)
+#define wxENTER_CRIT_SECT(cs)   (cs).Enter()
+#define wxLEAVE_CRIT_SECT(cs)   (cs).Leave()
+#define wxCRIT_SECT_LOCKER(name, cs)  wxCriticalSectionLocker name(cs)
 
 #else // !wxUSE_THREADS
 
index 48ee355683904a59392ea61138a4ffa8b90eff51..73b50a162bd9e2822951a72eeaa4283c8c105ab0 100644 (file)
@@ -172,7 +172,7 @@ WXDLLEXPORT int wxKill(long pid, wxSignal sig = wxSIGTERM);
 // If no command then just the shell
 WXDLLEXPORT bool wxShell(const wxString& command = wxEmptyString);
 
-// Sleep for nSecs seconds under UNIX, do nothing under Windows
+// Sleep for nSecs seconds
 WXDLLEXPORT void wxSleep(int nSecs);
 
 // Sleep for a given amount of milliseconds
index ed86aa6d79c980dbd902649e4df17a90d2d0c1c0..09e453695481cb7488373dfdc5608a0a77e9dc93 100644 (file)
@@ -30,8 +30,8 @@
 // what to test?
 
 //#define TEST_ARRAYS
-#define TEST_LOG
-//#define TEST_THREADS
+//#define TEST_LOG
+#define TEST_THREADS
 
 // ============================================================================
 // implementation
 
 static size_t gs_counter = (size_t)-1;
 static wxCriticalSection gs_critsect;
+static wxCondition gs_cond;
 
-class MyThread : public wxThread
+class MyJoinableThread : public wxThread
 {
 public:
-    MyThread(char ch);
+    MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
+        { m_n = n; Create(); }
 
     // thread execution starts here
-    virtual void *Entry();
+    virtual ExitCode Entry();
 
-    // and stops here
-    virtual void OnExit();
-
-public:
-    char m_ch;
+private:
+    size_t m_n;
 };
 
-MyThread::MyThread(char ch)
+wxThread::ExitCode MyJoinableThread::Entry()
 {
-    m_ch = ch;
+    unsigned long res = 1;
+    for ( size_t n = 1; n < m_n; n++ )
+    {
+        res *= n;
+
+        // it's a loooong calculation :-)
+        Sleep(100);
+    }
 
-    Create();
+    return (ExitCode)res;
 }
 
-void *MyThread::Entry()
+class MyDetachedThread : public wxThread
+{
+public:
+    MyDetachedThread(char ch) { m_ch = ch; Create(); }
+
+    // thread execution starts here
+    virtual ExitCode Entry();
+
+    // and stops here
+    virtual void OnExit();
+
+private:
+    char m_ch;
+};
+
+wxThread::ExitCode MyDetachedThread::Entry()
 {
     {
         wxCriticalSectionLocker lock(gs_critsect);
@@ -80,7 +101,8 @@ void *MyThread::Entry()
             gs_counter++;
     }
 
-    for ( size_t n = 0; n < 10; n++ )
+    static const size_t nIter = 10;
+    for ( size_t n = 0; n < nIter; n++ )
     {
         if ( TestDestroy() )
             break;
@@ -91,13 +113,14 @@ void *MyThread::Entry()
         wxThread::Sleep(100);
     }
 
-    return NULL;
+    return 0;
 }
 
-void MyThread::OnExit()
+void MyDetachedThread::OnExit()
 {
     wxCriticalSectionLocker lock(gs_critsect);
-    gs_counter--;
+    if ( !--gs_counter )
+        gs_cond.Signal();
 }
 
 #endif // TEST_THREADS
@@ -178,33 +201,44 @@ int main(int argc, char **argv)
     printf(msg);
 
     // but this one will because log functions use fixed size buffer
-    wxLogMessage("A very very long message 2: '%s', the end!\n", s.c_str());
+    // (note that it doesn't need '\n' at the end neither - will be added
+    //  by wxLog anyhow)
+    wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
 #endif // TEST_LOG
 
 #ifdef TEST_THREADS
+    puts("Testing detached threads...");
+
     static const size_t nThreads = 3;
-    MyThread *threads[nThreads];
+    MyDetachedThread *threads[nThreads];
     size_t n;
     for ( n = 0; n < nThreads; n++ )
     {
-        threads[n] = new MyThread('+' + n);
-        threads[n]->Run();
+        threads[n] = new MyDetachedThread('A' + n);
     }
 
-    // wait until all threads terminate
-    for ( ;; )
-    {
-        wxCriticalSectionLocker lock(gs_critsect);
-        if ( !gs_counter )
-            break;
-    }
-
-    puts("\nThat's all, folks!");
+    threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
+    threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
 
     for ( n = 0; n < nThreads; n++ )
     {
-        threads[n]->Delete();
+        threads[n]->Run();
     }
+
+    // wait until all threads terminate
+    wxMutex mutex;
+    mutex.Lock();
+    gs_cond.Wait(mutex);
+    mutex.Unlock();
+
+    puts("\n\nTesting a joinable thread used for a loooong calculation...");
+
+    // calc 10! in the background
+    MyJoinableThread thread(10);
+    thread.Run();
+
+    printf("\nThread terminated with exit code %lu.\n",
+           (unsigned long)thread.Wait());
 #endif // TEST_THREADS
 
     wxUninitialize();
index 1d8d3423bee504b8028877a04642b6dd76766be1..f43a48d9190ffd9220d578898ff52e5d9b6a9818 100644 (file)
@@ -150,7 +150,7 @@ void *MyThread::Entry()
     wxString text;
 
     text.Printf("Thread 0x%x started (priority = %d).\n",
-                GetID(), GetPriority());
+                GetId(), GetPriority());
     WriteText(text);
 
     for ( m_count = 0; m_count < 10; m_count++ )
@@ -159,14 +159,14 @@ void *MyThread::Entry()
         if ( TestDestroy() )
             break;
 
-        text.Printf("[%u] Thread 0x%x here.\n", m_count, GetID());
+        text.Printf("[%u] Thread 0x%x here.\n", m_count, GetId());
         WriteText(text);
 
         // wxSleep() can't be called from non-GUI thread!
         wxThread::Sleep(1000);
     }
 
-    text.Printf("Thread 0x%x finished.\n", GetID());
+    text.Printf("Thread 0x%x finished.\n", GetId());
     WriteText(text);
 
     return NULL;
@@ -266,17 +266,18 @@ MyThread *MyFrame::CreateThread()
 
 void MyFrame::OnStartThreads(wxCommandEvent& WXUNUSED(event) )
 {
-    static wxString s_str;
-    s_str = wxGetTextFromUser("How many threads to start: ",
-                              "wxThread sample",
-                              s_str, this);
-    if ( s_str.IsEmpty() )
-        return;
+    static long s_num = 10;
+
+    s_num = wxGetNumberFromUser("How many threads to start: ", "",
+                                "wxThread sample", s_num, 1, 10000, this);
+    if ( s_num == -1 )
+    {
+        s_num = 10;
 
-    size_t count, n;
-    sscanf(s_str, "%u", &count);
-    if ( count == 0 )
         return;
+    }
+
+    size_t count = (size_t)s_num, n;
 
     wxArrayThread threads;
 
index ee097b6b70edb53bbfae19f147610e13342b33b0..3276436a6eec6f578fe393e434c2225ae3a402ca 100644 (file)
@@ -47,7 +47,7 @@
 void wxAppBase::ProcessPendingEvents()
 {
     // ensure that we're the only thread to modify the pending events list
-    wxCRIT_SECT_LOCKER(locker, wxPendingEventsLocker);
+    wxCRIT_SECT_LOCKER(locker, *wxPendingEventsLocker);
 
     if ( !wxPendingEvents )
         return;
index fb953f101acdfd9b4adf8c371d30f0ad53f0d1f8..e6190d9674e9f057fab8489bd94bbfbad063e8de 100644 (file)
@@ -609,13 +609,13 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event)
 
     m_pendingEvents->Append(event2);
 
-    wxENTER_CRIT_SECT(wxPendingEventsLocker);
+    wxENTER_CRIT_SECT(*wxPendingEventsLocker);
 
     if ( !wxPendingEvents )
         wxPendingEvents = new wxList;
     wxPendingEvents->Append(this);
 
-    wxLEAVE_CRIT_SECT(wxPendingEventsLocker);
+    wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
 
     wxWakeUpIdle();
 }
@@ -623,9 +623,9 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event)
 void wxEvtHandler::ProcessPendingEvents()
 {
 #if defined(__VISAGECPP__)
-    wxCRIT_SECT_LOCKER(locker, &m_eventsLocker);
-#else
     wxCRIT_SECT_LOCKER(locker, m_eventsLocker);
+#else
+    wxCRIT_SECT_LOCKER(locker, *m_eventsLocker);
 #endif
 
     wxNode *node = m_pendingEvents->First();
index 846026eb938e5503cdf9db2945f578b56a5c6b11..0fa42d7d8f7fda405c2e1cf19e7e720218d753d7 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "wx/module.h"
 
-
 // ----------------------------------------------------------------------------
 // global vars
 // ----------------------------------------------------------------------------
index 01f2b0b01b4b028ed28cfcfeef2bfa5e75e6ccaa..a4647eee3c027f20017ac1f47597a6d1f52a2ada 100644 (file)
@@ -48,6 +48,7 @@
 #include  "wx/utils.h"
 #include  "wx/wxchar.h"
 #include  "wx/log.h"
+#include  "wx/thread.h"
 
 // other standard headers
 #include  <errno.h>
@@ -55,9 +56,7 @@
 #include  <time.h>
 
 #ifdef  __WXMSW__
-  #include  <windows.h>
-  // Redefines OutputDebugString if necessary
-  #include  "wx/msw/private.h"
+  #include  "wx/msw/private.h"      // includes windows.h for OutputDebugString
 #else   //Unix
   #include  <signal.h>
 #endif  //Win/Unix
 // ============================================================================
 
 // ----------------------------------------------------------------------------
-// implementation of Log functions
-//
-// NB: unfortunately we need all these distinct functions, we can't make them
-//     macros and not all compilers inline vararg functions.
+// globals
 // ----------------------------------------------------------------------------
 
 // log functions can't allocate memory (LogError("out of memory...") should
 // work!), so we use a static buffer for all log messages
 #define LOG_BUFFER_SIZE   (4096)
 
-// static buffer for error messages (FIXME MT-unsafe)
+// static buffer for error messages
 static wxChar s_szBuf[LOG_BUFFER_SIZE];
 
+#if wxUSE_THREADS
+
+// the critical section protecting the static buffer
+static wxCriticalSection gs_csLogBuf;
+
+#endif // wxUSE_THREADS
+
+// ----------------------------------------------------------------------------
+// implementation of Log functions
+//
+// NB: unfortunately we need all these distinct functions, we can't make them
+//     macros and not all compilers inline vararg functions.
+// ----------------------------------------------------------------------------
+
 // generic log function
 void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...)
 {
   if ( wxLog::GetActiveTarget() != NULL ) {
+    wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
     va_list argptr;
     va_start(argptr, szFormat);
     wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -108,6 +120,8 @@ void wxLogGeneric(wxLogLevel level, const wxChar *szFormat, ...)
   void wxLog##level(const wxChar *szFormat, ...)                  \
   {                                                               \
     if ( wxLog::GetActiveTarget() != NULL ) {                     \
+      wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);                    \
+                                                                  \
       va_list argptr;                                             \
       va_start(argptr, szFormat);                                 \
       wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);  \
@@ -129,6 +143,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
 {
   wxLog *pLog = wxLog::GetActiveTarget();
   if ( pLog != NULL && pLog->GetVerbose() ) {
+    wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
     va_list argptr;
     va_start(argptr, szFormat);
     wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -144,6 +160,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
   void wxLog##level(const wxChar *szFormat, ...)                  \
   {                                                               \
     if ( wxLog::GetActiveTarget() != NULL ) {                     \
+      wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);                    \
+                                                                  \
       va_list argptr;                                             \
       va_start(argptr, szFormat);                                 \
       wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);  \
@@ -158,6 +176,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
     wxLog *pLog = wxLog::GetActiveTarget();
 
     if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) {
+      wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
       va_list argptr;
       va_start(argptr, szFormat);
       wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -175,6 +195,8 @@ void wxLogVerbose(const wxChar *szFormat, ...)
     // that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something
     // if both bits are set.
     if ( pLog != NULL && ((pLog->GetTraceMask() & mask) == mask) ) {
+      wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
       va_list argptr;
       va_start(argptr, szFormat);
       wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -207,6 +229,8 @@ void wxLogSysErrorHelper(long lErrCode)
 
 void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...)
 {
+    wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
     va_list argptr;
     va_start(argptr, szFormat);
     wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -217,6 +241,8 @@ void WXDLLEXPORT wxLogSysError(const wxChar *szFormat, ...)
 
 void WXDLLEXPORT wxLogSysError(long lErrCode, const wxChar *szFormat, ...)
 {
+    wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
+
     va_list argptr;
     va_start(argptr, szFormat);
     wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
@@ -361,15 +387,16 @@ void wxLogStderr::DoLogString(const wxChar *szString, time_t WXUNUSED(t))
 {
     wxString str;
     TimeStamp(&str);
-    str << szString << wxT('\n');
+    str << szString;
 
     fputs(str.mb_str(), m_fp);
+    fputc(_T('\n'), m_fp);
     fflush(m_fp);
 
     // under Windows, programs usually don't have stderr at all, so show the
-    // messages also under debugger
-#ifdef __WXMSW__
-    OutputDebugString(str + wxT('\r'));
+    // messages also under debugger - unless it's a console program
+#if defined(__WXMSW__) && wxUSE_GUI
+    OutputDebugString(str + wxT("\r\n"));
 #endif // MSW
 }
 
index 796a19f06214f7ae9477693a4b7fe8af14540031..11e01b729154c5205b4e11e6c2d0ee2c8cb90c06 100644 (file)
@@ -771,6 +771,7 @@ bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
 
 bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
 {
+#if wxUSE_GUI
     if ( m_info ) {
         // we don't have icons in the fallback resources
         return FALSE;
@@ -819,6 +820,8 @@ bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
     }
 
     // no such file type or no value or incorrect icon entry
+#endif // wxUSE_GUI
+
     return FALSE;
 }
 
index 9582bca6d9ef09033f3d35ed93ae123acc4711ec..280e105f2539c09d15fb2b75b1bf7c9ba53e5990 100644 (file)
@@ -200,7 +200,12 @@ extern int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len,
 
     return iLen;
 #else // ANSI
-    return wxVsnprintfA(buf, len, format, argptr);
+    // vsnprintf() will not terminate the string with '\0' if there is not
+    // enough place, but we want the string to always be NUL terminated
+    int rc = wxVsnprintfA(buf, len - 1, format, argptr);
+    buf[len] = 0;
+
+    return rc;
 #endif // Unicode/ANSI
 }
 
index 3528af8915a0543eafbe717db1f6991b9dbcef02..0b947a540974716b12f63b748328cf06709b090f 100644 (file)
@@ -100,7 +100,6 @@ extern wxList WXDLLEXPORT wxPendingDelete;
 extern void wxSetKeyboardHook(bool doIt);
 extern wxCursor *g_globalCursor;
 
-HINSTANCE wxhInstance = 0;
 MSG s_currentMsg;
 wxApp *wxTheApp = NULL;
 
@@ -1217,11 +1216,16 @@ void wxWakeUpIdle()
 {
     // Send the top window a dummy message so idle handler processing will
     // start up again.  Doing it this way ensures that the idle handler
-    // wakes up in the right thread.
+    // wakes up in the right thread (see also wxWakeUpMainThread() which does
+    // the same for the main app thread only)
     wxWindow *topWindow = wxTheApp->GetTopWindow();
-    if ( topWindow ) {
-        HWND hWnd = (HWND)topWindow->GetHWND();
-        ::PostMessage(hWnd, WM_NULL, 0, 0);
+    if ( topWindow )
+    {
+        if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
+        {
+            // should never happen
+            wxLogLastError("PostMessage(WM_NULL)");
+        }
     }
 }
 
@@ -1250,17 +1254,6 @@ wxApp::GetStdIcon(int which) const
     }
 }
 
-
-HINSTANCE wxGetInstance()
-{
-    return wxhInstance;
-}
-
-void wxSetInstance(HINSTANCE hInst)
-{
-    wxhInstance = hInst;
-}
-
 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
 // if in a separate file. So include it here to ensure it's linked.
 #if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))
index 3565e7fa23885d4c1922c07c811c8695e2159ecc..cfa9a598c97e602a55a5864e8999ade95e54fbec 100644 (file)
@@ -1,36 +1,59 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        main.cpp
+// Name:        msw/main.cpp
 // Purpose:     Main/DllMain
 // Author:      Julian Smart
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:    wxWindows license
+// Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 #ifdef __GNUG__
-#pragma implementation
+    #pragma implementation
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #include "wx/event.h"
 #include "wx/app.h"
-#include <windows.h>
+
+#include "wx/msw/private.h"
+
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+HINSTANCE wxhInstance = 0;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// various entry points
+// ----------------------------------------------------------------------------
 
 // May wish not to have a DllMain or WinMain, e.g. if we're programming
-// a Netscape plugin.
-#ifndef NOMAIN
+// a Netscape plugin or if we're writing a console application
+#if wxUSE_GUI && !defined(NOMAIN)
 
 // NT defines APIENTRY, 3.x not
 #if !defined(APIENTRY)
-#define APIENTRY FAR PASCAL
+    #define APIENTRY FAR PASCAL
 #endif
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -78,25 +101,39 @@ BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
 #endif
 {
     switch (fdwReason)
-       {
-       case DLL_PROCESS_ATTACH:
-        // Only call wxEntry if the application itself is part of the DLL.
-        // If only the wxWindows library is in the DLL, then the initialisation
-        // will be called when the application implicitly calls WinMain.
+    {
+        case DLL_PROCESS_ATTACH:
+            // Only call wxEntry if the application itself is part of the DLL.
+            // If only the wxWindows library is in the DLL, then the initialisation
+            // will be called when the application implicitly calls WinMain.
 
 #if !defined(WXMAKINGDLL)
-        return wxEntry((WXHINSTANCE) hModule);
+            return wxEntry((WXHINSTANCE) hModule);
 #endif
-           break;
+            break;
 
-       case DLL_PROCESS_DETACH:
-       default:
-           break;
-       }
-  return TRUE;
+        case DLL_PROCESS_DETACH:
+        default:
+            break;
+    }
+    return TRUE;
 }
 
-#endif
+#endif // _WINDLL
 
-#endif
+#endif // !NOMAIN
+
+// ----------------------------------------------------------------------------
+// global functions
+// ----------------------------------------------------------------------------
+
+HINSTANCE wxGetInstance()
+{
+    return wxhInstance;
+}
+
+void wxSetInstance(HINSTANCE hInst)
+{
+    wxhInstance = hInst;
+}
 
index 4fb34f240d9a1ff3030e7de0b44b4c3662b4bc8e..e62511ca68015e8ed19a3e509b696af4a3a0290a 100644 (file)
@@ -160,13 +160,25 @@ void wxRegConfig::SetPath(const wxString& strPath)
   }
 
   // recombine path parts in one variable
-  wxString strRegPath;
+  wxString strOldPath = m_strPath, strRegPath;
   m_strPath.Empty();
   for ( size_t n = 0; n < aParts.Count(); n++ ) {
     strRegPath << '\\' << aParts[n];
     m_strPath << wxCONFIG_PATH_SEPARATOR << aParts[n];
   }
 
+  if ( m_strPath == strOldPath )
+      return;
+
+  // as we create the registry key when SetPath(key) is done, we can be left
+  // with plenty of empty keys if this was only done to try to read some value
+  // which, in fact, doesn't exist - to prevent this from happening we
+  // automatically delete the old key if it was empty
+  if ( m_keyLocal.IsEmpty() )
+  {
+      m_keyLocal.DeleteSelf();
+  }
+
   // change current key(s)
   m_keyLocal.SetName(m_keyLocalRoot, strRegPath);
   m_keyGlobal.SetName(m_keyGlobalRoot, strRegPath);
index 22cc54ffe0b91afa0b129275b6fb06c362a7537a..a3929b693f4d5373e5e38fc8e390f10ae6f0a753 100644 (file)
 #include "wx/module.h"
 #include "wx/thread.h"
 
+// must have this symbol defined to get _beginthread/_endthread declarations
+#ifndef _MT
+    #define _MT
+#endif
+
+#ifdef __VISUALC__
+    #include <process.h>
+#endif
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
 // the possible states of the thread ("=>" shows all possible transitions from
 // this state)
 enum wxThreadState
@@ -48,32 +61,32 @@ enum wxThreadState
 };
 
 // ----------------------------------------------------------------------------
-// static variables
+// this module globals
 // ----------------------------------------------------------------------------
 
 // TLS index of the slot where we store the pointer to the current thread
-static DWORD s_tlsThisThread = 0xFFFFFFFF;
+static DWORD gs_tlsThisThread = 0xFFFFFFFF;
 
 // id of the main thread - the one which can call GUI functions without first
 // calling wxMutexGuiEnter()
-static DWORD s_idMainThread = 0;
+static DWORD gs_idMainThread = 0;
 
 // if it's FALSE, some secondary thread is holding the GUI lock
-static bool s_bGuiOwnedByMainThread = TRUE;
+static bool gs_bGuiOwnedByMainThread = TRUE;
 
 // critical section which controls access to all GUI functions: any secondary
 // thread (i.e. except the main one) must enter this crit section before doing
 // any GUI calls
-static wxCriticalSection *s_critsectGui = NULL;
+static wxCriticalSection *gs_critsectGui = NULL;
 
-// critical section which protects s_nWaitingForGui variable
-static wxCriticalSection *s_critsectWaitingForGui = NULL;
+// critical section which protects gs_nWaitingForGui variable
+static wxCriticalSection *gs_critsectWaitingForGui = NULL;
 
 // number of threads waiting for GUI in wxMutexGuiEnter()
-static size_t s_nWaitingForGui = 0;
+static size_t gs_nWaitingForGui = 0;
 
 // are we waiting for a thread termination?
-static bool s_waitingForThread = FALSE;
+static bool gs_waitingForThread = FALSE;
 
 // ============================================================================
 // Windows implementation of thread classes
@@ -169,6 +182,46 @@ wxMutexError wxMutex::Unlock()
 class wxConditionInternal
 {
 public:
+    wxConditionInternal()
+    {
+        event = ::CreateEvent(
+                              NULL,   // default secutiry
+                              FALSE,  // not manual reset
+                              FALSE,  // nonsignaled initially
+                              NULL    // nameless event
+                             );
+        if ( !event )
+        {
+            wxLogSysError(_("Can not create event object."));
+        }
+        waiters = 0;
+    }
+
+    bool Wait(wxMutex& mutex, DWORD timeout)
+    {
+        mutex.Unlock();
+        waiters++;
+
+        // FIXME this should be MsgWaitForMultipleObjects() as well probably
+        DWORD rc = ::WaitForSingleObject(event, timeout);
+
+        waiters--;
+        mutex.Lock();
+
+        return rc != WAIT_TIMEOUT;
+    }
+
+    ~wxConditionInternal()
+    {
+        if ( event )
+        {
+            if ( !::CloseHandle(event) )
+            {
+                wxLogLastError("CloseHandle(event)");
+            }
+        }
+    }
+
     HANDLE event;
     int waiters;
 };
@@ -176,59 +229,46 @@ public:
 wxCondition::wxCondition()
 {
     p_internal = new wxConditionInternal;
-    p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if ( !p_internal->event )
-    {
-        wxLogSysError(_("Can not create event object."));
-    }
-
-    p_internal->waiters = 0;
 }
 
 wxCondition::~wxCondition()
 {
-    CloseHandle(p_internal->event);
+    delete p_internal;
 }
 
 void wxCondition::Wait(wxMutex& mutex)
 {
-    mutex.Unlock();
-    p_internal->waiters++;
-    WaitForSingleObject(p_internal->event, INFINITE);
-    p_internal->waiters--;
-    mutex.Lock();
+    (void)p_internal->Wait(mutex, INFINITE);
 }
 
 bool wxCondition::Wait(wxMutex& mutex,
                        unsigned long sec,
                        unsigned long nsec)
 {
-    DWORD ret;
-
-    mutex.Unlock();
-    p_internal->waiters++;
-    ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000));
-    p_internal->waiters--;
-    mutex.Lock();
-
-    return (ret != WAIT_TIMEOUT);
+    return p_internal->Wait(mutex, sec*1000 + nsec/1000000);
 }
 
 void wxCondition::Signal()
 {
-    SetEvent(p_internal->event);
+    // set the event to signaled: if a thread is already waiting on it, it will
+    // be woken up, otherwise the event will remain in the signaled state until
+    // someone waits on it. In any case, the system will return it to a non
+    // signalled state afterwards. If multiple threads are waiting, only one
+    // will be woken up.
+    if ( !::SetEvent(p_internal->event) )
+    {
+        wxLogLastError("SetEvent");
+    }
 }
 
 void wxCondition::Broadcast()
 {
-    int i;
-
-    for (i=0;i<p_internal->waiters;i++)
+    // this works because all these threads are already waiting and so each
+    // SetEvent() inside Signal() is really a PulseEvent() because the event
+    // state is immediately returned to non-signaled
+    for ( int i = 0; i < p_internal->waiters; i++ )
     {
-        if ( SetEvent(p_internal->event) == 0 )
-        {
-            wxLogSysError(_("Couldn't change the state of event object."));
-        }
+        Signal();
     }
 }
 
@@ -238,7 +278,7 @@ void wxCondition::Broadcast()
 
 wxCriticalSection::wxCriticalSection()
 {
-    wxASSERT_MSG( sizeof(CRITICAL_SECTION) == sizeof(m_buffer),
+    wxASSERT_MSG( sizeof(CRITICAL_SECTION) <= sizeof(m_buffer),
                   _T("must increase buffer size in wx/thread.h") );
 
     ::InitializeCriticalSection((CRITICAL_SECTION *)m_buffer);
@@ -276,6 +316,24 @@ public:
         m_priority = WXTHREAD_DEFAULT_PRIORITY;
     }
 
+    ~wxThreadInternal()
+    {
+        Free();
+    }
+
+    void Free()
+    {
+        if ( m_hThread )
+        {
+            if ( !::CloseHandle(m_hThread) )
+            {
+                wxLogLastError("CloseHandle(thread)");
+            }
+
+            m_hThread = 0;
+        }
+    }
+
     // create a new (suspended) thread (for the given thread object)
     bool Create(wxThread *thread);
 
@@ -289,7 +347,7 @@ public:
     wxThreadState GetState() const { return m_state; }
 
     // thread priority
-    void SetPriority(unsigned int priority) { m_priority = priority; }
+    void SetPriority(unsigned int priority);
     unsigned int GetPriority() const { return m_priority; }
 
     // thread handle and id
@@ -309,41 +367,38 @@ private:
 DWORD wxThreadInternal::WinThreadStart(wxThread *thread)
 {
     // store the thread object in the TLS
-    if ( !::TlsSetValue(s_tlsThisThread, thread) )
+    if ( !::TlsSetValue(gs_tlsThisThread, thread) )
     {
         wxLogSysError(_("Can not start thread: error writing TLS."));
 
         return (DWORD)-1;
     }
 
-    DWORD ret = (DWORD)thread->Entry();
+    DWORD rc = (DWORD)thread->Entry();
+
+    // enter m_critsect before changing the thread state
+    thread->m_critsect.Enter();
+    bool wasCancelled = thread->p_internal->GetState() == STATE_CANCELED;
     thread->p_internal->SetState(STATE_EXITED);
+    thread->m_critsect.Leave();
+
     thread->OnExit();
 
-    delete thread;
+    // if the thread was cancelled (from Delete()), then it the handle is still
+    // needed there
+    if ( thread->IsDetached() && !wasCancelled )
+    {
+        // auto delete
+        delete thread;
+    }
+    //else: the joinable threads handle will be closed when Wait() is done
 
-    return ret;
+    return rc;
 }
 
-bool wxThreadInternal::Create(wxThread *thread)
+void wxThreadInternal::SetPriority(unsigned int priority)
 {
-    m_hThread = ::CreateThread
-                  (
-                    NULL,                               // default security
-                    0,                                  // default stack size
-                    (LPTHREAD_START_ROUTINE)            // thread entry point
-                    wxThreadInternal::WinThreadStart,   //
-                    (LPVOID)thread,                     // parameter
-                    CREATE_SUSPENDED,                   // flags
-                    &m_tid                              // [out] thread id
-                  );
-
-    if ( m_hThread == NULL )
-    {
-        wxLogSysError(_("Can't create thread"));
-
-        return FALSE;
-    }
+    m_priority = priority;
 
     // translate wxWindows priority to the Windows one
     int win_priority;
@@ -363,10 +418,49 @@ bool wxThreadInternal::Create(wxThread *thread)
         win_priority = THREAD_PRIORITY_NORMAL;
     }
 
-    if ( ::SetThreadPriority(m_hThread, win_priority) == 0 )
+    if ( !::SetThreadPriority(m_hThread, win_priority) )
     {
         wxLogSysError(_("Can't set thread priority"));
     }
+}
+
+bool wxThreadInternal::Create(wxThread *thread)
+{
+    // for compilers which have it, we should use C RTL function for thread
+    // creation instead of Win32 API one because otherwise we will have memory
+    // leaks if the thread uses C RTL (and most threads do)
+#ifdef __VISUALC__
+    typedef unsigned (__stdcall *RtlThreadStart)(void *);
+
+    m_hThread = (HANDLE)_beginthreadex(NULL, 0,
+                                       (RtlThreadStart)    
+                                       wxThreadInternal::WinThreadStart,
+                                       thread, CREATE_SUSPENDED,
+                                       (unsigned int *)&m_tid);
+#else // !VC++
+    m_hThread = ::CreateThread
+                  (
+                    NULL,                               // default security
+                    0,                                  // default stack size
+                    (LPTHREAD_START_ROUTINE)            // thread entry point
+                    wxThreadInternal::WinThreadStart,   //
+                    (LPVOID)thread,                     // parameter
+                    CREATE_SUSPENDED,                   // flags
+                    &m_tid                              // [out] thread id
+                  );
+#endif // VC++/!VC++
+
+    if ( m_hThread == NULL )
+    {
+        wxLogSysError(_("Can't create thread"));
+
+        return FALSE;
+    }
+
+    if ( m_priority != WXTHREAD_DEFAULT_PRIORITY )
+    {
+        SetPriority(m_priority);
+    }
 
     return TRUE;
 }
@@ -406,7 +500,7 @@ bool wxThreadInternal::Resume()
 
 wxThread *wxThread::This()
 {
-    wxThread *thread = (wxThread *)::TlsGetValue(s_tlsThisThread);
+    wxThread *thread = (wxThread *)::TlsGetValue(gs_tlsThisThread);
 
     // be careful, 0 may be a valid return value as well
     if ( !thread && (::GetLastError() != NO_ERROR) )
@@ -421,16 +515,13 @@ wxThread *wxThread::This()
 
 bool wxThread::IsMain()
 {
-    return ::GetCurrentThreadId() == s_idMainThread;
+    return ::GetCurrentThreadId() == gs_idMainThread;
 }
 
-#ifdef Yield
-    #undef Yield
-#endif
-
 void wxThread::Yield()
 {
-    // 0 argument to Sleep() is special
+    // 0 argument to Sleep() is special and means to just give away the rest of
+    // our timeslice
     ::Sleep(0);
 }
 
@@ -439,11 +530,28 @@ void wxThread::Sleep(unsigned long milliseconds)
     ::Sleep(milliseconds);
 }
 
+// ctor and dtor
+// -------------
+
+wxThread::wxThread(wxThreadKind kind)
+{
+    p_internal = new wxThreadInternal();
+
+    m_isDetached = kind == wxTHREAD_DETACHED;
+}
+
+wxThread::~wxThread()
+{
+    delete p_internal;
+}
+
 // create/start thread
 // -------------------
 
 wxThreadError wxThread::Create()
 {
+    wxCriticalSectionLocker lock(m_critsect);
+
     if ( !p_internal->Create(this) )
         return wxTHREAD_NO_RESOURCE;
 
@@ -460,6 +568,7 @@ wxThreadError wxThread::Run()
         return wxTHREAD_RUNNING;
     }
 
+    // the thread has just been created and is still suspended - let it run
     return Resume();
 }
 
@@ -483,7 +592,23 @@ wxThreadError wxThread::Resume()
 // stopping thread
 // ---------------
 
-wxThread::ExitCode wxThread::Delete()
+wxThread::ExitCode wxThread::Wait()
+{
+    // although under Windows we can wait for any thread, it's an error to
+    // wait for a detached one in wxWin API
+    wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
+                 _T("can't wait for detached thread") );
+
+    ExitCode rc = (ExitCode)-1;
+
+    (void)Delete(&rc);
+
+    p_internal->Free();
+
+    return rc;
+}
+
+wxThreadError wxThread::Delete(ExitCode *pRc)
 {
     ExitCode rc = 0;
 
@@ -491,24 +616,28 @@ wxThread::ExitCode wxThread::Delete()
     if ( IsPaused() )
         Resume();
 
+    HANDLE hThread = p_internal->GetHandle();
+
     if ( IsRunning() )
     {
         if ( IsMain() )
         {
             // set flag for wxIsWaitingForThread()
-            s_waitingForThread = TRUE;
+            gs_waitingForThread = TRUE;
 
+#if wxUSE_GUI
             wxBeginBusyCursor();
+#endif // wxUSE_GUI
         }
 
-        HANDLE hThread;
+        // ask the thread to terminate
         {
             wxCriticalSectionLocker lock(m_critsect);
 
             p_internal->Cancel();
-            hThread = p_internal->GetHandle();
         }
 
+#if wxUSE_GUI
         // we can't just wait for the thread to terminate because it might be
         // calling some GUI functions and so it will never terminate before we
         // process the Windows messages that result from these functions
@@ -530,7 +659,7 @@ wxThread::ExitCode wxThread::Delete()
                     // error
                     wxLogSysError(_("Can not wait for thread termination"));
                     Kill();
-                    return (ExitCode)-1;
+                    return wxTHREAD_KILLED;
 
                 case WAIT_OBJECT_0:
                     // thread we're waiting for terminated
@@ -543,14 +672,14 @@ wxThread::ExitCode wxThread::Delete()
                         // WM_QUIT received: kill the thread
                         Kill();
 
-                        return (ExitCode)-1;
+                        return wxTHREAD_KILLED;
                     }
 
                     if ( IsMain() )
                     {
                         // give the thread we're waiting for chance to exit
                         // from the GUI call it might have been in
-                        if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
+                        if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
                         {
                             wxMutexGuiLeave();
                         }
@@ -562,28 +691,50 @@ wxThread::ExitCode wxThread::Delete()
                     wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
             }
         } while ( result != WAIT_OBJECT_0 );
+#else // !wxUSE_GUI
+        // simply wait for the thread to terminate
+        //
+        // OTOH, even console apps create windows (in wxExecute, for WinSock
+        // &c), so may be use MsgWaitForMultipleObject() too here?
+        if ( WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0 )
+        {
+            wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject"));
+        }
+#endif // wxUSE_GUI/!wxUSE_GUI
 
         if ( IsMain() )
         {
-            s_waitingForThread = FALSE;
+            gs_waitingForThread = FALSE;
 
+#if wxUSE_GUI
             wxEndBusyCursor();
+#endif // wxUSE_GUI
         }
+    }
 
-        if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
-        {
-            wxLogLastError("GetExitCodeThread");
-
-            rc = (ExitCode)-1;
-        }
+    if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
+    {
+        wxLogLastError("GetExitCodeThread");
 
-        wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE,
-                      wxT("thread must be already terminated.") );
+        rc = (ExitCode)-1;
+    }
 
-        ::CloseHandle(hThread);
+    if ( IsDetached() )
+    {
+        // if the thread exits normally, this is done in WinThreadStart, but in
+        // this case it would have been too early because
+        // MsgWaitForMultipleObject() would fail if the therad handle was
+        // closed while we were waiting on it, so we must do it here
+        delete this;
     }
 
-    return rc;
+    wxASSERT_MSG( (DWORD)rc != STILL_ACTIVE,
+                  wxT("thread must be already terminated.") );
+
+    if ( pRc )
+        *pRc = rc;
+
+    return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
 }
 
 wxThreadError wxThread::Kill()
@@ -598,20 +749,37 @@ wxThreadError wxThread::Kill()
         return wxTHREAD_MISC_ERROR;
     }
 
-    delete this;
+    p_internal->Free();
+
+    if ( IsDetached() )
+    {
+        delete this;
+    }
 
     return wxTHREAD_NO_ERROR;
 }
 
-void wxThread::Exit(void *status)
+void wxThread::Exit(ExitCode status)
 {
-    delete this;
+    p_internal->Free();
 
+    if ( IsDetached() )
+    {
+        delete this;
+    }
+
+#ifdef __VISUALC__
+    _endthreadex((unsigned)status);
+#else // !VC++
     ::ExitThread((DWORD)status);
+#endif // VC++/!VC++
 
     wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
 }
 
+// priority setting
+// ----------------
+
 void wxThread::SetPriority(unsigned int prio)
 {
     wxCriticalSectionLocker lock(m_critsect);
@@ -621,28 +789,28 @@ void wxThread::SetPriority(unsigned int prio)
 
 unsigned int wxThread::GetPriority() const
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
     return p_internal->GetPriority();
 }
 
-unsigned long wxThread::GetID() const
+unsigned long wxThread::GetId() const
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
     return (unsigned long)p_internal->GetId();
 }
 
 bool wxThread::IsRunning() const
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
     return p_internal->GetState() == STATE_RUNNING;
 }
 
 bool wxThread::IsAlive() const
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
     return (p_internal->GetState() == STATE_RUNNING) ||
            (p_internal->GetState() == STATE_PAUSED);
@@ -650,28 +818,18 @@ bool wxThread::IsAlive() const
 
 bool wxThread::IsPaused() const
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
-    return (p_internal->GetState() == STATE_PAUSED);
+    return p_internal->GetState() == STATE_PAUSED;
 }
 
 bool wxThread::TestDestroy()
 {
-    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+    wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
 
     return p_internal->GetState() == STATE_CANCELED;
 }
 
-wxThread::wxThread()
-{
-    p_internal = new wxThreadInternal();
-}
-
-wxThread::~wxThread()
-{
-    delete p_internal;
-}
-
 // ----------------------------------------------------------------------------
 // Automatic initialization for thread module
 // ----------------------------------------------------------------------------
@@ -691,8 +849,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
 bool wxThreadModule::OnInit()
 {
     // allocate TLS index for storing the pointer to the current thread
-    s_tlsThisThread = ::TlsAlloc();
-    if ( s_tlsThisThread == 0xFFFFFFFF )
+    gs_tlsThisThread = ::TlsAlloc();
+    if ( gs_tlsThisThread == 0xFFFFFFFF )
     {
         // in normal circumstances it will only happen if all other
         // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other
@@ -706,10 +864,10 @@ bool wxThreadModule::OnInit()
 
     // main thread doesn't have associated wxThread object, so store 0 in the
     // TLS instead
-    if ( !::TlsSetValue(s_tlsThisThread, (LPVOID)0) )
+    if ( !::TlsSetValue(gs_tlsThisThread, (LPVOID)0) )
     {
-        ::TlsFree(s_tlsThisThread);
-        s_tlsThisThread = 0xFFFFFFFF;
+        ::TlsFree(gs_tlsThisThread);
+        gs_tlsThisThread = 0xFFFFFFFF;
 
         wxLogSysError(_("Thread module initialization failed: "
                         "can not store value in thread local storage"));
@@ -717,36 +875,37 @@ bool wxThreadModule::OnInit()
         return FALSE;
     }
 
-    s_critsectWaitingForGui = new wxCriticalSection();
+    gs_critsectWaitingForGui = new wxCriticalSection();
 
-    s_critsectGui = new wxCriticalSection();
-    s_critsectGui->Enter();
+    gs_critsectGui = new wxCriticalSection();
+    gs_critsectGui->Enter();
 
     // no error return for GetCurrentThreadId()
-    s_idMainThread = ::GetCurrentThreadId();
+    gs_idMainThread = ::GetCurrentThreadId();
 
     return TRUE;
 }
 
 void wxThreadModule::OnExit()
 {
-    if ( !::TlsFree(s_tlsThisThread) )
+    if ( !::TlsFree(gs_tlsThisThread) )
     {
         wxLogLastError("TlsFree failed.");
     }
 
-    if ( s_critsectGui )
+    if ( gs_critsectGui )
     {
-        s_critsectGui->Leave();
-        delete s_critsectGui;
-        s_critsectGui = NULL;
+        gs_critsectGui->Leave();
+        delete gs_critsectGui;
+        gs_critsectGui = NULL;
     }
 
-    wxDELETE(s_critsectWaitingForGui);
+    delete gs_critsectWaitingForGui;
+    gs_critsectWaitingForGui = NULL;
 }
 
 // ----------------------------------------------------------------------------
-// under Windows, these functions are implemented usign a critical section and
+// under Windows, these functions are implemented using a critical section and
 // not a mutex, so the names are a bit confusing
 // ----------------------------------------------------------------------------
 
@@ -760,38 +919,38 @@ void WXDLLEXPORT wxMutexGuiEnter()
 
     // set the flag telling to the main thread that we want to do some GUI
     {
-        wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
+        wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
 
-        s_nWaitingForGui++;
+        gs_nWaitingForGui++;
     }
 
     wxWakeUpMainThread();
 
     // now we may block here because the main thread will soon let us in
     // (during the next iteration of OnIdle())
-    s_critsectGui->Enter();
+    gs_critsectGui->Enter();
 }
 
 void WXDLLEXPORT wxMutexGuiLeave()
 {
-    wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
+    wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
 
     if ( wxThread::IsMain() )
     {
-        s_bGuiOwnedByMainThread = FALSE;
+        gs_bGuiOwnedByMainThread = FALSE;
     }
     else
     {
         // decrement the number of waiters now
-        wxASSERT_MSG( s_nWaitingForGui > 0,
+        wxASSERT_MSG( gs_nWaitingForGui > 0,
                       wxT("calling wxMutexGuiLeave() without entering it first?") );
 
-        s_nWaitingForGui--;
+        gs_nWaitingForGui--;
 
         wxWakeUpMainThread();
     }
 
-    s_critsectGui->Leave();
+    gs_critsectGui->Leave();
 }
 
 void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
@@ -799,17 +958,17 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
     wxASSERT_MSG( wxThread::IsMain(),
                   wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
 
-    wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
+    wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
 
-    if ( s_nWaitingForGui == 0 )
+    if ( gs_nWaitingForGui == 0 )
     {
         // no threads are waiting for GUI - so we may acquire the lock without
         // any danger (but only if we don't already have it)
         if ( !wxGuiOwnedByMainThread() )
         {
-            s_critsectGui->Enter();
+            gs_critsectGui->Enter();
 
-            s_bGuiOwnedByMainThread = TRUE;
+            gs_bGuiOwnedByMainThread = TRUE;
         }
         //else: already have it, nothing to do
     }
@@ -826,14 +985,14 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
 
 bool WXDLLEXPORT wxGuiOwnedByMainThread()
 {
-    return s_bGuiOwnedByMainThread;
+    return gs_bGuiOwnedByMainThread;
 }
 
 // wake up the main thread if it's in ::GetMessage()
 void WXDLLEXPORT wxWakeUpMainThread()
 {
     // sending any message would do - hopefully WM_NULL is harmless enough
-    if ( !::PostThreadMessage(s_idMainThread, WM_NULL, 0, 0) )
+    if ( !::PostThreadMessage(gs_idMainThread, WM_NULL, 0, 0) )
     {
         // should never happen
         wxLogLastError("PostThreadMessage(WM_NULL)");
@@ -842,7 +1001,7 @@ void WXDLLEXPORT wxWakeUpMainThread()
 
 bool WXDLLEXPORT wxIsWaitingForThread()
 {
-    return s_waitingForThread;
+    return gs_waitingForThread;
 }
 
 #endif // wxUSE_THREADS
index 8b36c7a3dea710996c2d85960a334f131e0da05b..d2a287299580c3849a629bb0e39aec0e6cc1b52d 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        utils.cpp
+// Name:        mse/utils.cpp
 // Purpose:     Various utilities
 // Author:      Julian Smart
 // Modified by:
@@ -9,6 +9,14 @@
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 #ifdef __GNUG__
 // #pragma implementation "utils.h"   // Note: this is done in utilscmn.cpp now.
 #endif
 #endif
 
 #ifndef WX_PRECOMP
-    #include "wx/setup.h"
     #include "wx/utils.h"
     #include "wx/app.h"
     #include "wx/cursor.h"
 #endif  //WX_PRECOMP
 
-#include "wx/msw/private.h"
+#include "wx/msw/private.h"     // includes <windows.h>
+
 #include "wx/timer.h"
 #include "wx/intl.h"
 
-#include <windows.h>
-
 #include <ctype.h>
 
 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
   // __VISUALC__
 /// END for console support
 
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
 // In the WIN.INI file
 static const wxChar WX_SECTION[] = wxT("wxWindows");
+static const wxChar eUSERNAME[]  = wxT("UserName");
+
+// these are only used under Win16
+#ifndef __WIN32__
 static const wxChar eHOSTNAME[]  = wxT("HostName");
 static const wxChar eUSERID[]    = wxT("UserId");
-static const wxChar eUSERNAME[]  = wxT("UserName");
+#endif // !Win32
 
-// For the following functions we SHOULD fill in support
-// for Windows-NT (which I don't know) as I assume it begin
-// a POSIX Unix (so claims MS) that it has some special
-// functions beyond those provided by WinSock
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// get host name and related
+// ----------------------------------------------------------------------------
 
 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
 bool wxGetHostName(wxChar *buf, int maxSize)
 {
 #if defined(__WIN32__) && !defined(__TWIN32__)
-  DWORD nSize = maxSize;
-  return (::GetComputerName(buf, &nSize) != 0);
+    // TODO should use GetComputerNameEx() when available
+
+    DWORD nSize = maxSize;
+    if ( !::GetComputerName(buf, &nSize) )
+    {
+        wxLogLastError("GetComputerName");
+
+        return FALSE;
+    }
+
+    return TRUE;
 #else
-  wxChar *sysname;
-  const wxChar *default_host = wxT("noname");
-
-  if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) {
-     GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
-  } else
-    wxStrncpy(buf, sysname, maxSize - 1);
-  buf[maxSize] = wxT('\0');
-  return *buf ? TRUE : FALSE;
+    wxChar *sysname;
+    const wxChar *default_host = wxT("noname");
+
+    if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) {
+        GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
+    } else
+        wxStrncpy(buf, sysname, maxSize - 1);
+    buf[maxSize] = wxT('\0');
+    return *buf ? TRUE : FALSE;
 #endif
 }
 
+bool wxGetFullHostName(wxChar *buf, int maxSize)
+{
+    return wxGetHostName(buf, maxSize);
+}
+
 // Get user ID e.g. jacs
 bool wxGetUserId(wxChar *buf, int maxSize)
 {
@@ -166,23 +197,23 @@ bool wxGetUserId(wxChar *buf, int maxSize)
 
     return TRUE;
 #else   // Win16 or Win32s
-  wxChar *user;
-  const wxChar *default_id = wxT("anonymous");
+    wxChar *user;
+    const wxChar *default_id = wxT("anonymous");
 
-  // Can't assume we have NIS (PC-NFS) or some other ID daemon
-  // So we ...
-  if (  (user = wxGetenv(wxT("USER"))) == NULL &&
-        (user = wxGetenv(wxT("LOGNAME"))) == NULL )
-  {
-     // Use wxWindows configuration data (comming soon)
-     GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
-  }
-  else
-  {
-    wxStrncpy(buf, user, maxSize - 1);
-  }
+    // Can't assume we have NIS (PC-NFS) or some other ID daemon
+    // So we ...
+    if (  (user = wxGetenv(wxT("USER"))) == NULL &&
+            (user = wxGetenv(wxT("LOGNAME"))) == NULL )
+    {
+        // Use wxWindows configuration data (comming soon)
+        GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
+    }
+    else
+    {
+        wxStrncpy(buf, user, maxSize - 1);
+    }
 
-  return *buf ? TRUE : FALSE;
+    return *buf ? TRUE : FALSE;
 #endif
 }
 
@@ -190,244 +221,263 @@ bool wxGetUserId(wxChar *buf, int maxSize)
 bool wxGetUserName(wxChar *buf, int maxSize)
 {
 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__)
-  extern HANDLE g_hPenWin; // PenWindows Running?
-  if (g_hPenWin)
-  {
-    // PenWindows Does have a user concept!
-    // Get the current owner of the recognizer
-    GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
-    strncpy(buf, wxBuffer, maxSize - 1);
-  }
-  else
+    extern HANDLE g_hPenWin; // PenWindows Running?
+    if (g_hPenWin)
+    {
+        // PenWindows Does have a user concept!
+        // Get the current owner of the recognizer
+        GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
+        strncpy(buf, wxBuffer, maxSize - 1);
+    }
+    else
 #endif
-  {
+    {
 #ifdef USE_NET_API
-    CHAR szUserName[256];
-    if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
-        return FALSE;
+        CHAR szUserName[256];
+        if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
+            return FALSE;
 
-    // TODO how to get the domain name?
-    CHAR *szDomain = "";
+        // TODO how to get the domain name?
+        CHAR *szDomain = "";
 
-    // the code is based on the MSDN example (also see KB article Q119670)
-    WCHAR wszUserName[256];          // Unicode user name
-    WCHAR wszDomain[256];
-    LPBYTE ComputerName;
+        // the code is based on the MSDN example (also see KB article Q119670)
+        WCHAR wszUserName[256];          // Unicode user name
+        WCHAR wszDomain[256];
+        LPBYTE ComputerName;
 
-    USER_INFO_2 *ui2;         // User structure
+        USER_INFO_2 *ui2;         // User structure
 
-    // Convert ANSI user name and domain to Unicode
-    MultiByteToWideChar( CP_ACP, 0, szUserName, strlen(szUserName)+1,
-                          wszUserName, WXSIZEOF(wszUserName) );
-    MultiByteToWideChar( CP_ACP, 0, szDomain, strlen(szDomain)+1,
-                         wszDomain, WXSIZEOF(wszDomain) );
+        // Convert ANSI user name and domain to Unicode
+        MultiByteToWideChar( CP_ACP, 0, szUserName, strlen(szUserName)+1,
+                wszUserName, WXSIZEOF(wszUserName) );
+        MultiByteToWideChar( CP_ACP, 0, szDomain, strlen(szDomain)+1,
+                wszDomain, WXSIZEOF(wszDomain) );
 
-    // Get the computer name of a DC for the domain.
-    if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
-    {
-        wxLogError(wxT("Can not find domain controller"));
+        // Get the computer name of a DC for the domain.
+        if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
+        {
+            wxLogError(wxT("Can not find domain controller"));
 
-        goto error;
-    }
+            goto error;
+        }
 
-    // Look up the user on the DC
-    NET_API_STATUS status = NetUserGetInfo( (LPWSTR)ComputerName,
-                                            (LPWSTR)&wszUserName,
-                                            2, // level - we want USER_INFO_2
-                                            (LPBYTE *) &ui2 );
-    switch ( status )
-    {
-        case NERR_Success:
-            // ok
-            break;
+        // Look up the user on the DC
+        NET_API_STATUS status = NetUserGetInfo( (LPWSTR)ComputerName,
+                (LPWSTR)&wszUserName,
+                2, // level - we want USER_INFO_2
+                (LPBYTE *) &ui2 );
+        switch ( status )
+        {
+            case NERR_Success:
+                // ok
+                break;
 
-        case NERR_InvalidComputer:
-            wxLogError(wxT("Invalid domain controller name."));
+            case NERR_InvalidComputer:
+                wxLogError(wxT("Invalid domain controller name."));
 
-            goto error;
+                goto error;
 
-        case NERR_UserNotFound:
-            wxLogError(wxT("Invalid user name '%s'."), szUserName);
+            case NERR_UserNotFound:
+                wxLogError(wxT("Invalid user name '%s'."), szUserName);
 
-            goto error;
+                goto error;
 
-        default:
-            wxLogSysError(wxT("Can't get information about user"));
+            default:
+                wxLogSysError(wxT("Can't get information about user"));
 
-            goto error;
-    }
+                goto error;
+        }
 
-    // Convert the Unicode full name to ANSI
-    WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1,
-                         buf, maxSize, NULL, NULL );
+        // Convert the Unicode full name to ANSI
+        WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1,
+                buf, maxSize, NULL, NULL );
 
-    return TRUE;
+        return TRUE;
 
 error:
-  wxLogError(wxT("Couldn't look up full user name."));
+        wxLogError(wxT("Couldn't look up full user name."));
 
-  return FALSE;
+        return FALSE;
 #else  // !USE_NET_API
-    // Could use NIS, MS-Mail or other site specific programs
-    // Use wxWindows configuration data
-    bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxT(""), buf, maxSize - 1) != 0;
-    if ( !ok )
-    {
-        ok = wxGetUserId(buf, maxSize);
-    }
+        // Could use NIS, MS-Mail or other site specific programs
+        // Use wxWindows configuration data
+        bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxT(""), buf, maxSize - 1) != 0;
+        if ( !ok )
+        {
+            ok = wxGetUserId(buf, maxSize);
+        }
 
-    if ( !ok )
-    {
-        wxStrncpy(buf, wxT("Unknown User"), maxSize);
-    }
+        if ( !ok )
+        {
+            wxStrncpy(buf, wxT("Unknown User"), maxSize);
+        }
 #endif // Win32/16
-  }
+    }
 
-  return TRUE;
+    return TRUE;
 }
 
-int wxKill(long pid, int sig)
+const wxChar* wxGetHomeDir(wxString *pstr)
 {
-  return 0;
-}
+  wxString& strDir = *pstr;
 
-//
-// Execute a program in an Interactive Shell
-//
-bool
-wxShell(const wxString& command)
-{
-  wxChar *shell;
-  if ((shell = wxGetenv(wxT("COMSPEC"))) == NULL)
-    shell = wxT("\\COMMAND.COM");
+  #if defined(__UNIX__) && !defined(__TWIN32__)
+    const wxChar *szHome = wxGetenv("HOME");
+    if ( szHome == NULL ) {
+      // we're homeless...
+      wxLogWarning(_("can't find user's HOME, using current directory."));
+      strDir = wxT(".");
+    }
+    else
+       strDir = szHome;
 
-  wxChar tmp[255];
-  if (command != wxT(""))
-    wxSprintf(tmp, wxT("%s /c %s"), shell, WXSTRINGCAST command);
-  else
-    wxStrcpy(tmp, shell);
+    // add a trailing slash if needed
+    if ( strDir.Last() != wxT('/') )
+      strDir << wxT('/');
+  #else   // Windows
+    #ifdef  __WIN32__
+      const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
+      if ( szHome != NULL )
+        strDir << szHome;
+      szHome = wxGetenv(wxT("HOMEPATH"));
+      if ( szHome != NULL ) {
+        strDir << szHome;
 
-  return (wxExecute((wxChar *)tmp, FALSE) != 0);
-}
+        // the idea is that under NT these variables have default values
+        // of "%systemdrive%:" and "\\". As we don't want to create our
+        // config files in the root directory of the system drive, we will
+        // create it in our program's dir. However, if the user took care
+        // to set HOMEPATH to something other than "\\", we suppose that he
+        // knows what he is doing and use the supplied value.
+        if ( wxStrcmp(szHome, wxT("\\")) != 0 )
+          return strDir.c_str();
+      }
 
-// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
-long wxGetFreeMemory()
-{
-#if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__)
-  MEMORYSTATUS memStatus;
-  memStatus.dwLength = sizeof(MEMORYSTATUS);
-  GlobalMemoryStatus(&memStatus);
-  return memStatus.dwAvailPhys;
-#else
-  return (long)GetFreeSpace(0);
-#endif
-}
+    #else   // Win16
+      // Win16 has no idea about home, so use the working directory instead
+    #endif  // WIN16/32
 
-// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
-static bool inTimer = FALSE;
-class wxSleepTimer: public wxTimer
-{
- public:
-  inline void Notify()
-  {
-    inTimer = FALSE;
-    Stop();
-  }
-};
+    // 260 was taken from windef.h
+    #ifndef MAX_PATH
+      #define MAX_PATH  260
+    #endif
 
-static wxTimer *wxTheSleepTimer = NULL;
+    wxString strPath;
+    ::GetModuleFileName(::GetModuleHandle(NULL),
+                        strPath.GetWriteBuf(MAX_PATH), MAX_PATH);
+    strPath.UngetWriteBuf();
 
-void wxUsleep(unsigned long milliseconds)
-{
-#ifdef __WIN32__
-    ::Sleep(milliseconds);
-#else
-  if (inTimer)
-    return;
+    // extract the dir name
+    wxSplitPath(strPath, &strDir, NULL, NULL);
 
-  wxTheSleepTimer = new wxSleepTimer;
-  inTimer = TRUE;
-  wxTheSleepTimer->Start(milliseconds);
-  while (inTimer)
-  {
-    if (wxTheApp->Pending())
-      wxTheApp->Dispatch();
-  }
-  delete wxTheSleepTimer;
-  wxTheSleepTimer = NULL;
-#endif
+  #endif  // UNIX/Win
+
+  return strDir.c_str();
 }
 
-void wxSleep(int nSecs)
+wxChar *wxGetUserHome(const wxString& user)
 {
-#if 0 // WIN32 hangs app
-  Sleep( 1000*nSecs );
-#else
-  if (inTimer)
-    return;
+    // VZ: the old code here never worked for user != "" anyhow! Moreover, it
+    //     returned sometimes a malloc()'d pointer, sometimes a pointer to a
+    //     static buffer and sometimes I don't even know what.
+    static wxString s_home;
 
-  wxTheSleepTimer = new wxSleepTimer;
-  inTimer = TRUE;
-  wxTheSleepTimer->Start(nSecs*1000);
-  while (inTimer)
-  {
-    if (wxTheApp->Pending())
-      wxTheApp->Dispatch();
-  }
-  delete wxTheSleepTimer;
-  wxTheSleepTimer = NULL;
-#endif
+    return (wxChar *)wxGetHomeDir(&s_home);
 }
 
-// Consume all events until no more left
-void wxFlushEvents()
+bool wxDirExists(const wxString& dir)
 {
-//  wxYield();
-}
+#if defined(__WIN32__)
+    WIN32_FIND_DATA fileInfo;
+#else // Win16
+    #ifdef __BORLANDC__
+        struct ffblk fileInfo;
+    #else
+        struct find_t fileInfo;
+    #endif
+#endif // Win32/16
 
-// Output a debug mess., in a system dependent fashion.
-void wxDebugMsg(const wxChar *fmt ...)
-{
-  va_list ap;
-  static wxChar buffer[512];
+#if defined(__WIN32__)
+    HANDLE h = ::FindFirstFile(dir, &fileInfo);
 
-  if (!wxTheApp->GetWantDebugOutput())
-    return ;
+    if ( h == INVALID_HANDLE_VALUE )
+    {
+        wxLogLastError("FindFirstFile");
 
-  va_start(ap, fmt);
+        return FALSE;
+    }
 
-  wvsprintf(buffer,fmt,ap) ;
-  OutputDebugString((LPCTSTR)buffer) ;
+    ::FindClose(h);
+
+    return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+#else // Win16
+    // In Borland findfirst has a different argument
+    // ordering from _dos_findfirst. But _dos_findfirst
+    // _should_ be ok in both MS and Borland... why not?
+    #ifdef __BORLANDC__
+        return (findfirst(dir, &fileInfo, _A_SUBDIR) == 0 &&
+               (fileInfo.ff_attrib & _A_SUBDIR) != 0);
+    #else
+        return (_dos_findfirst(dir, _A_SUBDIR, &fileInfo) == 0) &&
+               ((fileInfo.attrib & _A_SUBDIR) != 0);
+    #endif
+#endif // Win32/16
+}
 
-  va_end(ap);
+// ----------------------------------------------------------------------------
+// process management
+// ----------------------------------------------------------------------------
+
+int wxKill(long pid, int sig)
+{
+    // TODO use SendMessage(WM_QUIT) and TerminateProcess() if needed
+
+    return 0;
 }
 
-// Non-fatal error: pop up message box and (possibly) continue
-void wxError(const wxString& msg, const wxString& title)
+// Execute a program in an Interactive Shell
+bool wxShell(const wxString& command)
 {
-  wxSprintf(wxBuffer, wxT("%s\nContinue?"), WXSTRINGCAST msg);
-  if (MessageBox(NULL, (LPCTSTR)wxBuffer, (LPCTSTR)WXSTRINGCAST title,
-             MB_ICONSTOP | MB_YESNO) == IDNO)
-    wxExit();
+    wxChar *shell = wxGetenv(wxT("COMSPEC"));
+    if ( !shell )
+        shell = wxT("\\COMMAND.COM");
+
+    wxString cmd;
+    if ( !command )
+    {
+        // just the shell
+        cmd = shell;
+    }
+    else
+    {
+        // pass the command to execute to the command processor
+        cmd.Printf(wxT("%s /c %s"), shell, command.c_str());
+    }
+
+    return wxExecute(cmd, FALSE) != 0;
 }
 
-// Fatal error: pop up message box and abort
-void wxFatalError(const wxString& msg, const wxString& title)
+// ----------------------------------------------------------------------------
+// misc
+// ----------------------------------------------------------------------------
+
+// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
+long wxGetFreeMemory()
 {
-  wxSprintf(wxBuffer, wxT("%s: %s"), WXSTRINGCAST title, WXSTRINGCAST msg);
-  FatalAppExit(0, (LPCTSTR)wxBuffer);
+#if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__)
+    MEMORYSTATUS memStatus;
+    memStatus.dwLength = sizeof(MEMORYSTATUS);
+    GlobalMemoryStatus(&memStatus);
+    return memStatus.dwAvailPhys;
+#else
+    return (long)GetFreeSpace(0);
+#endif
 }
 
 // Emit a beeeeeep
 void wxBell()
 {
-    // Removed by RD because IHMO syncronous sound is a Bad Thing.  MessageBeep
-    // will do a similar thing anyway if there is no sound card...
-//#ifdef __WIN32__
-//  Beep(1000,1000) ; // 1kHz during 1 sec.
-//#else
-  MessageBeep((UINT)-1) ;
-//#endif
+    ::MessageBeep((UINT)-1);        // default sound
 }
 
 // Chris Breeze 27/5/98: revised WIN32 code to
@@ -477,6 +527,128 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 #endif
 }
 
+// ----------------------------------------------------------------------------
+// sleep functions
+// ----------------------------------------------------------------------------
+
+#if wxUSE_GUI
+
+// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
+static bool gs_inTimer = FALSE;
+
+class wxSleepTimer: public wxTimer
+{
+public:
+    virtual void Notify()
+    {
+        gs_inTimer = FALSE;
+        Stop();
+    }
+};
+
+static wxTimer *wxTheSleepTimer = NULL;
+
+void wxUsleep(unsigned long milliseconds)
+{
+#ifdef __WIN32__
+    ::Sleep(milliseconds);
+#else
+    if (gs_inTimer)
+        return;
+
+    wxTheSleepTimer = new wxSleepTimer;
+    gs_inTimer = TRUE;
+    wxTheSleepTimer->Start(milliseconds);
+    while (gs_inTimer)
+    {
+        if (wxTheApp->Pending())
+            wxTheApp->Dispatch();
+    }
+    delete wxTheSleepTimer;
+    wxTheSleepTimer = NULL;
+#endif
+}
+
+void wxSleep(int nSecs)
+{
+    if (gs_inTimer)
+        return;
+
+    wxTheSleepTimer = new wxSleepTimer;
+    gs_inTimer = TRUE;
+    wxTheSleepTimer->Start(nSecs*1000);
+    while (gs_inTimer)
+    {
+        if (wxTheApp->Pending())
+            wxTheApp->Dispatch();
+    }
+    delete wxTheSleepTimer;
+    wxTheSleepTimer = NULL;
+}
+
+// Consume all events until no more left
+void wxFlushEvents()
+{
+//  wxYield();
+}
+
+#elif defined(__WIN32__) // wxUSE_GUI
+
+void wxUsleep(unsigned long milliseconds)
+{
+    ::Sleep(milliseconds);
+}
+
+void wxSleep(int nSecs)
+{
+    wxUsleep(1000*nSecs);
+}
+
+#endif // wxUSE_GUI/!wxUSE_GUI
+
+// ----------------------------------------------------------------------------
+// deprecated (in favour of wxLog) log functions
+// ----------------------------------------------------------------------------
+
+#if wxUSE_GUI
+
+// Output a debug mess., in a system dependent fashion.
+void wxDebugMsg(const wxChar *fmt ...)
+{
+  va_list ap;
+  static wxChar buffer[512];
+
+  if (!wxTheApp->GetWantDebugOutput())
+    return ;
+
+  va_start(ap, fmt);
+
+  wvsprintf(buffer,fmt,ap) ;
+  OutputDebugString((LPCTSTR)buffer) ;
+
+  va_end(ap);
+}
+
+// Non-fatal error: pop up message box and (possibly) continue
+void wxError(const wxString& msg, const wxString& title)
+{
+  wxSprintf(wxBuffer, wxT("%s\nContinue?"), WXSTRINGCAST msg);
+  if (MessageBox(NULL, (LPCTSTR)wxBuffer, (LPCTSTR)WXSTRINGCAST title,
+             MB_ICONSTOP | MB_YESNO) == IDNO)
+    wxExit();
+}
+
+// Fatal error: pop up message box and abort
+void wxFatalError(const wxString& msg, const wxString& title)
+{
+  wxSprintf(wxBuffer, wxT("%s: %s"), WXSTRINGCAST title, WXSTRINGCAST msg);
+  FatalAppExit(0, (LPCTSTR)wxBuffer);
+}
+
+// ----------------------------------------------------------------------------
+// functions to work with .INI files
+// ----------------------------------------------------------------------------
+
 // Reading and writing resources (eg WIN.INI, .Xdefaults)
 #if wxUSE_RESOURCES
 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
@@ -495,84 +667,87 @@ bool wxWriteResource(const wxString& section, const wxString& entry, const wxStr
 
 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
 {
-  wxChar buf[50];
-  wxSprintf(buf, wxT("%.4f"), value);
-  return wxWriteResource(section, entry, buf, file);
+    wxString buf;
+    buf.Printf(wxT("%.4f"), value);
+
+    return wxWriteResource(section, entry, buf, file);
 }
 
 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
 {
-  wxChar buf[50];
-  wxSprintf(buf, wxT("%ld"), value);
-  return wxWriteResource(section, entry, buf, file);
+    wxString buf;
+    buf.Printf(wxT("%ld"), value);
+
+    return wxWriteResource(section, entry, buf, file);
 }
 
 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
 {
-  wxChar buf[50];
-  wxSprintf(buf, wxT("%d"), value);
-  return wxWriteResource(section, entry, buf, file);
+    wxString buf;
+    buf.Printf(wxT("%d"), value);
+
+    return wxWriteResource(section, entry, buf, file);
 }
 
 bool wxGetResource(const wxString& section, const wxString& entry, wxChar **value, const wxString& file)
 {
-  static const wxChar defunkt[] = wxT("$$default");
-  if (file != wxT(""))
-  {
-    int n = GetPrivateProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
-                                    (LPTSTR)wxBuffer, 1000, (LPCTSTR)WXSTRINGCAST file);
-    if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
-     return FALSE;
-  }
-  else
-  {
-    int n = GetProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
-                                    (LPTSTR)wxBuffer, 1000);
-    if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
-      return FALSE;
-  }
-  if (*value) delete[] (*value);
-      *value = copystring(wxBuffer);
-      return TRUE;
+    static const wxChar defunkt[] = wxT("$$default");
+    if (file != wxT(""))
+    {
+        int n = GetPrivateProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
+                (LPTSTR)wxBuffer, 1000, (LPCTSTR)WXSTRINGCAST file);
+        if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
+            return FALSE;
+    }
+    else
+    {
+        int n = GetProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
+                (LPTSTR)wxBuffer, 1000);
+        if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
+            return FALSE;
     }
+    if (*value) delete[] (*value);
+    *value = copystring(wxBuffer);
+    return TRUE;
+}
 
 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
 {
-  wxChar *s = NULL;
-  bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-  if (succ)
-  {
-    *value = (float)wxStrtod(s, NULL);
-    delete[] s;
-    return TRUE;
-  }
-  else return FALSE;
+    wxChar *s = NULL;
+    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
+    if (succ)
+    {
+        *value = (float)wxStrtod(s, NULL);
+        delete[] s;
+        return TRUE;
+    }
+    else return FALSE;
 }
 
 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
 {
-  wxChar *s = NULL;
-  bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-  if (succ)
-  {
-    *value = wxStrtol(s, NULL, 10);
-    delete[] s;
-    return TRUE;
-  }
-  else return FALSE;
+    wxChar *s = NULL;
+    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
+    if (succ)
+    {
+        *value = wxStrtol(s, NULL, 10);
+        delete[] s;
+        return TRUE;
+    }
+    else return FALSE;
 }
 
 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
 {
-  wxChar *s = NULL;
-  bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-  if (succ)
-  {
-    *value = (int)wxStrtol(s, NULL, 10);
-    delete[] s;
-    return TRUE;
-  }
-  else return FALSE;
+    wxChar *s = NULL;
+    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
+    if (succ)
+    {
+        *value = (int)wxStrtol(s, NULL, 10);
+        delete[] s;
+        return TRUE;
+    }
+    else return FALSE;
 }
 #endif // wxUSE_RESOURCES
 
@@ -615,228 +790,89 @@ bool wxIsBusy()
   return (gs_wxBusyCursorCount > 0);
 }
 
-// ---------------------------------------------------------------------------
-const wxChar* wxGetHomeDir(wxString *pstr)
-{
-  wxString& strDir = *pstr;
-
-  #if defined(__UNIX__) && !defined(__TWIN32__)
-    const wxChar *szHome = wxGetenv("HOME");
-    if ( szHome == NULL ) {
-      // we're homeless...
-      wxLogWarning(_("can't find user's HOME, using current directory."));
-      strDir = wxT(".");
-    }
-    else
-       strDir = szHome;
-
-    // add a trailing slash if needed
-    if ( strDir.Last() != wxT('/') )
-      strDir << wxT('/');
-  #else   // Windows
-    #ifdef  __WIN32__
-      const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
-      if ( szHome != NULL )
-        strDir << szHome;
-      szHome = wxGetenv(wxT("HOMEPATH"));
-      if ( szHome != NULL ) {
-        strDir << szHome;
-
-        // the idea is that under NT these variables have default values
-        // of "%systemdrive%:" and "\\". As we don't want to create our
-        // config files in the root directory of the system drive, we will
-        // create it in our program's dir. However, if the user took care
-        // to set HOMEPATH to something other than "\\", we suppose that he
-        // knows what he is doing and use the supplied value.
-        if ( wxStrcmp(szHome, wxT("\\")) != 0 )
-          return strDir.c_str();
-      }
-
-    #else   // Win16
-      // Win16 has no idea about home, so use the working directory instead
-    #endif  // WIN16/32
-
-    // 260 was taken from windef.h
-    #ifndef MAX_PATH
-      #define MAX_PATH  260
-    #endif
-
-    wxString strPath;
-    ::GetModuleFileName(::GetModuleHandle(NULL),
-                        strPath.GetWriteBuf(MAX_PATH), MAX_PATH);
-    strPath.UngetWriteBuf();
-
-    // extract the dir name
-    wxSplitPath(strPath, &strDir, NULL, NULL);
-
-  #endif  // UNIX/Win
-
-  return strDir.c_str();
-}
-
-// Hack for MS-DOS
-wxChar *wxGetUserHome (const wxString& user)
-{
-  wxChar *home;
-  wxString user1(user);
-
-  if (user1 != wxT("")) {
-    wxChar tmp[64];
-    if (wxGetUserId(tmp, sizeof(tmp)/sizeof(char))) {
-      // Guests belong in the temp dir
-      if (wxStricmp(tmp, wxT("annonymous")) == 0) {
-        if ((home = wxGetenv(wxT("TMP"))) != NULL ||
-            (home = wxGetenv(wxT("TMPDIR"))) != NULL ||
-            (home = wxGetenv(wxT("TEMP"))) != NULL)
-            return *home ? home : (wxChar*)wxT("\\");
-      }
-      if (wxStricmp(tmp, WXSTRINGCAST user1) == 0)
-        user1 = wxT("");
-    }
-  }
-  if (user1 == wxT(""))
-    if ((home = wxGetenv(wxT("HOME"))) != NULL)
-    {
-      wxStrcpy(wxBuffer, home);
-      Unix2DosFilename(wxBuffer);
-      return wxBuffer;
-    }
-  return NULL; // No home known!
-}
-
 // Check whether this window wants to process messages, e.g. Stop button
 // in long calculations.
 bool wxCheckForInterrupt(wxWindow *wnd)
 {
-  if(wnd){
+    wxCHECK( wnd, FALSE );
+
     MSG msg;
-    HWND win= (HWND) wnd->GetHWND();
-    while(PeekMessage(&msg,win,0,0,PM_REMOVE)){
-      TranslateMessage(&msg);
-      DispatchMessage(&msg);
+    while ( ::PeekMessage(&msg, GetHwndOf(wnd), 0, 0, PM_REMOVE) )
+    {
+        ::TranslateMessage(&msg);
+        ::DispatchMessage(&msg);
     }
-    return TRUE;//*** temporary?
-  }
-  else{
-    wxFAIL_MSG(wxT("wnd==NULL !!!"));
 
-    return FALSE;//*** temporary?
-  }
+    return TRUE;
 }
 
+#endif // wxUSE_GUI
+
 // MSW only: get user-defined resource from the .res file.
 // Returns NULL or newly-allocated memory, so use delete[] to clean up.
 
-#ifdef __WXMSW__
 wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
 {
-  wxChar *s = NULL;
-#if !defined(__WIN32__) || defined(__TWIN32__)
-  HRSRC hResource = ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
-#else
-#ifdef UNICODE
-  HRSRC hResource = ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
-#else
-  HRSRC hResource = ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
-#endif
-#endif
+    HRSRC hResource = ::FindResource(wxGetInstance(), resourceName, resourceType);
+    if ( hResource == 0 )
+        return NULL;
+
+    HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
+    if ( hData == 0 )
+        return NULL;
 
-  if (hResource == 0)
-    return NULL;
-  HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
-  if (hData == 0)
-    return NULL;
-  wxChar *theText = (wxChar *)LockResource(hData);
-  if (!theText)
-    return NULL;
+    wxChar *theText = (wxChar *)::LockResource(hData);
+    if ( !theText )
+        return NULL;
 
-  s = copystring(theText);
+    wxChar *s = copystring(theText);
 
-  // Obsolete in WIN32
+    // Obsolete in WIN32
 #ifndef __WIN32__
-  UnlockResource(hData);
+    UnlockResource(hData);
 #endif
 
-  // No need??
-//  GlobalFree(hData);
+    // No need??
+    //  GlobalFree(hData);
 
-  return s;
+    return s;
 }
-#endif
+
+// ----------------------------------------------------------------------------
+// get display info
+// ----------------------------------------------------------------------------
 
 void wxGetMousePosition( int* x, int* y )
 {
-  POINT pt;
-  GetCursorPos( & pt );
-  *x = pt.x;
-  *y = pt.y;
+    POINT pt;
+    GetCursorPos( & pt );
+    if ( x ) *x = pt.x;
+    if ( y ) *y = pt.y;
 };
 
 // Return TRUE if we have a colour display
 bool wxColourDisplay()
 {
-  HDC dc = ::GetDC((HWND) NULL);
-  bool flag;
-  int noCols = GetDeviceCaps(dc, NUMCOLORS);
-  if ((noCols == -1) || (noCols > 2))
-    flag = TRUE;
-  else
-    flag = FALSE;
-  ReleaseDC((HWND) NULL, dc);
-  return flag;
+    ScreenHDC dc;
+    int noCols = GetDeviceCaps(dc, NUMCOLORS);
+
+    return (noCols == -1) || (noCols > 2);
 }
 
 // Returns depth of screen
 int wxDisplayDepth()
 {
-  HDC dc = ::GetDC((HWND) NULL);
-  int planes = GetDeviceCaps(dc, PLANES);
-  int bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
-  int depth = planes*bitsPerPixel;
-  ReleaseDC((HWND) NULL, dc);
-  return depth;
+    ScreenHDC dc;
+    return GetDeviceCaps(dc, PLANES) * GetDeviceCaps(dc, BITSPIXEL);
 }
 
 // Get size of display
 void wxDisplaySize(int *width, int *height)
 {
-  HDC dc = ::GetDC((HWND) NULL);
-  *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES);
-  ReleaseDC((HWND) NULL, dc);
-}
-
-bool wxDirExists(const wxString& dir)
-{
-  /* MATTHEW: [6] Always use same code for Win32, call FindClose */
-#if defined(__WIN32__)
-  WIN32_FIND_DATA fileInfo;
-#else
-#ifdef __BORLANDC__
-  struct ffblk fileInfo;
-#else
-  struct find_t fileInfo;
-#endif
-#endif
-
-#if defined(__WIN32__)
-  HANDLE h = FindFirstFile((LPTSTR) WXSTRINGCAST dir,(LPWIN32_FIND_DATA)&fileInfo);
+    ScreenHDC dc;
 
-  if (h==INVALID_HANDLE_VALUE)
-   return FALSE;
-  else {
-   FindClose(h);
-   return ((fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
-  }
-#else
-  // In Borland findfirst has a different argument
-  // ordering from _dos_findfirst. But _dos_findfirst
-  // _should_ be ok in both MS and Borland... why not?
-#ifdef __BORLANDC__
-  return ((findfirst(WXSTRINGCAST dir, &fileInfo, _A_SUBDIR) == 0  && (fileInfo.ff_attrib & _A_SUBDIR) != 0));
-#else
-  return (((_dos_findfirst(WXSTRINGCAST dir, _A_SUBDIR, &fileInfo) == 0) && (fileInfo.attrib & _A_SUBDIR)) != 0);
-#endif
-#endif
+    if ( width ) *width = GetDeviceCaps(dc, HORZRES);
+    if ( height ) *height = GetDeviceCaps(dc, VERTRES);
 }
 
 // ---------------------------------------------------------------------------
index e6570d80a32335080ed32637c974da706d75306a..9d778c9d5b67475fa7d9922d1b88a9fc3ffe9eb9 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        utilsexec.cpp
+// Name:        msw/utilsexec.cpp
 // Purpose:     Various utilities
 // Author:      Julian Smart
 // Modified by:
@@ -9,48 +9,51 @@
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 #ifdef __GNUG__
-#pragma implementation
+    #pragma implementation
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #ifndef WX_PRECOMP
-#include "wx/setup.h"
-#include "wx/utils.h"
-#include "wx/app.h"
-#include "wx/intl.h"
+    #include "wx/utils.h"
+    #include "wx/app.h"
+    #include "wx/intl.h"
 #endif
 
 #include "wx/log.h"
 
 #ifdef __WIN32__
-#include "wx/process.h"
+    #include "wx/process.h"
 #endif
 
 #include "wx/msw/private.h"
 
-#include <windows.h>
-
 #include <ctype.h>
 
 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
-#include <direct.h>
+    #include <direct.h>
 #ifndef __MWERKS__
-#include <dos.h>
+    #include <dos.h>
 #endif
 #endif
 
-#ifdef __GNUWIN32__
-#ifndef __TWIN32__
-#include <sys/unistd.h>
-#include <sys/stat.h>
-#endif
+#if defined(__GNUWIN32__) && !defined(__TWIN32__)
+    #include <sys/unistd.h>
+    #include <sys/stat.h>
 #endif
 
 #if defined(__WIN32__) && !defined(__WXWINE__)
 #endif
 #include <stdarg.h>
 
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
 // this message is sent when the process we're waiting for terminates
 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
 
+// ----------------------------------------------------------------------------
+// this module globals
+// ----------------------------------------------------------------------------
+
+// we need to create a hidden window to receive the process termination
+// notifications and for this we need a (Win) class name for it which we will
+// register the first time it's needed
+static const wxChar *gs_classForHiddenWindow = NULL;
+
+// ----------------------------------------------------------------------------
+// private types
+// ----------------------------------------------------------------------------
+
 // structure describing the process we're being waiting for
 struct wxExecuteData
 {
@@ -96,6 +116,9 @@ public:
     bool       state;         // set to FALSE when the process finishes
 };
 
+// ============================================================================
+// implementation
+// ============================================================================
 
 #ifdef __WIN32__
 static DWORD wxExecuteThread(wxExecuteData *data)
@@ -150,8 +173,6 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
 }
 #endif
 
-extern wxChar wxPanelClassName[];
-
 long wxExecute(const wxString& command, bool sync, wxProcess *handler)
 {
     wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
@@ -242,17 +263,31 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler)
     if ( !::CloseHandle(pi.hThread) )
         wxLogLastError("CloseHandle(hThread)");
 
+    if ( !gs_classForHiddenWindow )
+    {
+        gs_classForHiddenWindow = _T("wxHiddenWindow");
+
+        WNDCLASS wndclass;
+        wxZeroMemory(wndclass);
+        wndclass.lpfnWndProc   = (WNDPROC)wxExecuteWindowCbk;
+        wndclass.hInstance     = wxGetInstance();
+        wndclass.lpszClassName = gs_classForHiddenWindow;
+
+        if ( !::RegisterClass(&wndclass) )
+        {
+            wxLogLastError("RegisterClass(hidden window)");
+
+            return FALSE;
+        }
+    }
+
     // create a hidden window to receive notification about process
     // termination
-    HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
+    HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL,
+                               0, 0, 0, 0, 0, NULL,
                                (HMENU)NULL, wxGetInstance(), 0);
     wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
 
-    FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
-                                                     wxGetInstance());
-
-    ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
-
     // Alloc data
     wxExecuteData *data = new wxExecuteData;
     data->hProcess    = pi.hProcess;
@@ -338,33 +373,3 @@ long wxExecute(char **argv, bool sync, wxProcess *handler)
     return wxExecute(command, sync, handler);
 }
 
-bool wxGetFullHostName(wxChar *buf, int maxSize)
-{
-#if defined(__WIN32__) && !defined(__TWIN32__)
-    DWORD nSize = maxSize ;
-    if ( !::GetComputerName(buf, &nSize) )
-    {
-        wxLogLastError("GetComputerName");
-
-        return FALSE;
-    }
-#else
-    char *sysname;
-    const char *default_host = "noname";
-static const char WX_SECTION[] = "wxWindows";
-static const char eHOSTNAME[]  = "HostName";
-
-    if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
-       GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
-    } else
-      strncpy(buf, sysname, maxSize - 1);
-    buf[maxSize] = '\0';
-    if ( *buf == '\0' )
-    {
-        wxLogLastError("GetComputerName");
-
-        return FALSE;
-    }
-#endif
-    return TRUE;
-}
index e1ea13a436368548343d2b11f1325067919f4874..0b33684eaefc8a637212f13481e2bed33a072bb7 100644 (file)
@@ -685,7 +685,14 @@ wxThreadError wxThread::Resume()
 // exiting thread
 // -----------------------------------------------------------------------------
 
-wxThread::ExitCode wxThread::Delete()
+wxThread::ExitCode Wait()
+{
+    wxFAIL_MSG("TODO");
+
+    return 0;
+}
+
+wxThreadError wxThread::Delete(ExitCode *rc)
 {
     if (IsPaused())
       Resume();
@@ -745,7 +752,7 @@ wxThreadError wxThread::Kill()
     }
 }
 
-void wxThread::Exit(void *status)
+void wxThread::Exit(ExitCode status)
 {
     // first call user-level clean up code
     OnExit();