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
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
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
dialup.cpp U
fontenum.cpp U
fontutil.cpp U
-threadpsx.cpp U
+threadpsx.cpp U B
utilsunx.cpp U B
gsocket.c U
# 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
# 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
--- /dev/null
+#!#############################################################################
+#! 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
# 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"
# 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"
#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
// ----------------------------------------------------------------------------
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())
// wxUninitialize()
extern void WXDLLEXPORT wxUninitialize();
-#endif // wxUSE_NOGUI
+#endif // !wxUSE_GUI
// ----------------------------------------------------------------------------
// macros for dynamic creation of the application object
// 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;
WXDLLEXPORT_DATA(extern HICON) wxDEFAULT_MDICHILDFRAME_ICON;
WXDLLEXPORT_DATA(extern HFONT) wxSTATUS_LINE_FONT;
+#endif // wxUSE_GUI
+
// ---------------------------------------------------------------------------
// define things missing from some compilers' headers
// ---------------------------------------------------------------------------
// 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;
// ---------------------------------------------------------------------------
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);
wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
}
+#endif // wxUSE_GUI
+
#endif
// _WX_PRIVATE_H_
}
#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
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
{
};
// ----------------------------------------------------------------------------
-// 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
{
// 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
// 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;
// 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
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.
// 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;
};
// ----------------------------------------------------------------------------
// 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
// 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
// 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);
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;
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
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();
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++ )
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;
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;
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;
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();
}
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();
#include "wx/module.h"
-
// ----------------------------------------------------------------------------
// global vars
// ----------------------------------------------------------------------------
#include "wx/utils.h"
#include "wx/wxchar.h"
#include "wx/log.h"
+#include "wx/thread.h"
// other standard headers
#include <errno.h>
#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);
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); \
{
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);
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); \
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);
// 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);
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);
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);
{
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
}
bool wxFileTypeImpl::GetIcon(wxIcon *icon) const
{
+#if wxUSE_GUI
if ( m_info ) {
// we don't have icons in the fallback resources
return FALSE;
}
// no such file type or no value or incorrect icon entry
+#endif // wxUSE_GUI
+
return FALSE;
}
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
}
extern void wxSetKeyboardHook(bool doIt);
extern wxCursor *g_globalCursor;
-HINSTANCE wxhInstance = 0;
MSG s_currentMsg;
wxApp *wxTheApp = NULL;
{
// 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)");
+ }
}
}
}
}
-
-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__))
/////////////////////////////////////////////////////////////////////////////
-// 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
/////////////////////////////////////////////////////////////////////////////////
#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;
+}
}
// 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);
#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
};
// ----------------------------------------------------------------------------
-// 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
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;
};
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();
}
}
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);
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);
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
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;
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;
}
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) )
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);
}
::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;
return wxTHREAD_RUNNING;
}
+ // the thread has just been created and is still suspended - let it run
return 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;
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
// 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
// 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();
}
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()
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);
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);
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
// ----------------------------------------------------------------------------
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
// 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"));
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
// ----------------------------------------------------------------------------
// 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()
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
}
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)");
bool WXDLLEXPORT wxIsWaitingForThread()
{
- return s_waitingForThread;
+ return gs_waitingForThread;
}
#endif // wxUSE_THREADS
/////////////////////////////////////////////////////////////////////////////
-// Name: utils.cpp
+// Name: mse/utils.cpp
// Purpose: Various utilities
// Author: Julian Smart
// Modified by:
// 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)
{
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
}
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
#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)
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
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);
}
// ---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
-// Name: utilsexec.cpp
+// Name: msw/utilsexec.cpp
// Purpose: Various utilities
// Author: Julian Smart
// Modified by:
// 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
{
bool state; // set to FALSE when the process finishes
};
+// ============================================================================
+// implementation
+// ============================================================================
#ifdef __WIN32__
static DWORD wxExecuteThread(wxExecuteData *data)
}
#endif
-extern wxChar wxPanelClassName[];
-
long wxExecute(const wxString& command, bool sync, wxProcess *handler)
{
wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") );
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;
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;
-}
// exiting thread
// -----------------------------------------------------------------------------
-wxThread::ExitCode wxThread::Delete()
+wxThread::ExitCode Wait()
+{
+ wxFAIL_MSG("TODO");
+
+ return 0;
+}
+
+wxThreadError wxThread::Delete(ExitCode *rc)
{
if (IsPaused())
Resume();
}
}
-void wxThread::Exit(void *status)
+void wxThread::Exit(ExitCode status)
{
// first call user-level clean up code
OnExit();