]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/utilsexc.cpp
treectrl -> treetest
[wxWidgets.git] / src / msw / utilsexc.cpp
index 26f8ca415f3e93750fe4a568d12ef699190e87b2..8fcae76c3c5789222d8cab80b2d7614bd1735ec6 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <ctype.h>
 
-#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
+#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__)
     #include <direct.h>
 #ifndef __MWERKS__
     #include <dos.h>
@@ -57,7 +57,7 @@
     #include <sys/stat.h>
 #endif
 
-#if defined(__WIN32__) && !defined(__WXWINE__)
+#if defined(__WIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
 #include <io.h>
 
 #ifndef __GNUWIN32__
@@ -259,8 +259,10 @@ size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t len)
 
 #ifdef __WIN32__
 
-static DWORD wxExecuteThread(wxExecuteData *data)
+static DWORD __stdcall wxExecuteThread(void *arg)
 {
+    wxExecuteData *data = (wxExecuteData*)arg;
+
     WaitForSingleObject(data->hProcess, INFINITE);
 
     // get the exit code
@@ -315,6 +317,49 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
 }
 #endif // Win32
 
+#if wxUSE_IPC
+
+// connect to the given server via DDE and ask it to execute the command
+static bool wxExecuteDDE(const wxString& ddeServer,
+                         const wxString& ddeTopic,
+                         const wxString& ddeCommand)
+{
+    bool ok;
+
+    wxDDEClient client;
+    wxConnectionBase *conn = client.MakeConnection(_T(""),
+                                                   ddeServer,
+                                                   ddeTopic);
+    if ( !conn )
+    {
+        ok = FALSE;
+    }
+    else // connected to DDE server
+    {
+        // the added complication here is that although most
+        // programs use XTYP_EXECUTE for their DDE API, some
+        // important ones - like IE and other MS stuff - use
+        // XTYP_REQUEST!
+        //
+        // so we try it first and then the other one if it
+        // failed
+        {
+            wxLogNull noErrors;
+            ok = conn->Request(ddeCommand) != NULL;
+        }
+
+        if ( !ok )
+        {
+            // now try execute - but show the errors
+            ok = conn->Execute(ddeCommand);
+        }
+    }
+
+    return ok;
+}
+
+#endif // wxUSE_IPC
+
 long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
 {
     wxCHECK_MSG( !!cmd, 0, wxT("empty command in wxExecute") );
@@ -334,6 +379,11 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
     static const size_t lenDdePrefix = 7;   // strlen("WX_DDE:")
     if ( cmd.Left(lenDdePrefix) == _T("WX_DDE#") )
     {
+        // speed up the concatenations below
+        ddeServer.reserve(256);
+        ddeTopic.reserve(256);
+        ddeCommand.reserve(256);
+
         const wxChar *p = cmd.c_str() + 7;
         while ( *p && *p != _T('#') )
         {
@@ -385,27 +435,21 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
             ddeCommand += *p++;
         }
 
-        // maybe we don't have to launch the DDE server at all - if it is
-        // already running, for example
-        wxDDEClient client;
-        wxLogNull nolog;
-        wxConnectionBase *conn = client.MakeConnection(_T(""),
-                                                       ddeServer,
-                                                       ddeTopic);
-        if ( conn )
+        // if we want to just launch the program and not wait for its
+        // termination, try to execute DDE command right now, it can succeed if
+        // the process is already running - but as it fails if it's not
+        // running, suppress any errors it might generate
+        if ( !sync )
         {
-            // FIXME we don't check the return code as for some strange reason
-            //       it will sometimes be FALSE - it is probably a bug in our
-            //       DDE code but I don't see anything wrong there
-            (void)conn->Execute(ddeCommand);
-
-            // ok, the command executed - return value indicating success,
-            // making it up for async case as we really don't have any way to
-            // get the real PID of the DDE server here
-            return sync ? 0 : -1;
+            wxLogNull noErrors;
+            if ( wxExecuteDDE(ddeServer, ddeTopic, ddeCommand) )
+            {
+                // a dummy PID - this is a hack, of course, but it's well worth
+                // it as we don't open a new server each time we're called
+                // which would be quite bad
+                return -1;
+            }
         }
-        //else: couldn't establish DDE conversation, now try launching the app
-        //      and sending the DDE request again
     }
     else
 #endif // wxUSE_IPC
@@ -421,9 +465,9 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
 #if wxUSE_STREAMS
     // the first elements are reading ends, the second are the writing ones
     HANDLE hpipeStdin[2],
-           hpipeStdinWrite = INVALID_HANDLE_VALUE,
            hpipeStdout[2],
            hpipeStderr[2];
+    HANDLE hpipeStdinWrite = INVALID_HANDLE_VALUE;
 
     // open the pipes to which child process IO will be redirected if needed
     if ( handler && handler->IsRedirected() )
@@ -604,7 +648,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
     DWORD tid;
     HANDLE hThread = ::CreateThread(NULL,
                                     0,
-                                    (LPTHREAD_START_ROUTINE)wxExecuteThread,
+                                    wxExecuteThread,
                                     (void *)data,
                                     0,
                                     &tid);
@@ -637,40 +681,33 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
 #if wxUSE_IPC
     // second part of DDE hack: now establish the DDE conversation with the
     // just launched process
-    if ( !!ddeServer )
+    if ( !ddeServer.empty() )
     {
-        wxDDEClient client;
-        wxConnectionBase *conn;
-
+        bool ok;
+
+        // give the process the time to init itself
+        //
+        // we use a very big timeout hoping that WaitForInputIdle() will return
+        // much sooner, but not INFINITE just in case the process hangs
+        // completely - like this we will regain control sooner or later
+        switch ( ::WaitForInputIdle(pi.hProcess, 10000 /* 10 seconds */) )
         {
-            // try doing it the first time without error messages
-            wxLogNull nolog;
+            default:
+                wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") );
+                // fall through
 
-            conn = client.MakeConnection(_T(""), ddeServer, ddeTopic);
-        }
+            case -1:
+                wxLogLastError(_T("WaitForInputIdle() in wxExecute"));
 
-        if ( !conn )
-        {
-            // give the app some time to initialize itself: in fact, a common
-            // reason for failure is that we tried to open DDE conversation too
-            // soon (before the app had time to setup its DDE server), so wait
-            // a bit and try again
-            ::Sleep(2000);
-
-            wxConnectionBase *conn = client.MakeConnection(_T(""),
-                                                           ddeServer,
-                                                           ddeTopic);
-            if ( !conn )
-            {
-                wxLogError(_("Couldn't launch DDE server '%s'."), command.c_str());
-            }
-        }
+            case WAIT_TIMEOUT:
+                wxLogDebug(_T("Timeout too small in WaitForInputIdle"));
 
-        if ( conn )
-        {
-            // FIXME just as above we don't check Execute() return code
-            wxLogNull nolog;
-            (void)conn->Execute(ddeCommand);
+                ok = FALSE;
+                break;
+
+            case 0:
+                // ok, process ready to accept DDE requests
+                ok = wxExecuteDDE(ddeServer, ddeTopic, ddeCommand);
         }
     }
 #endif // wxUSE_IPC
@@ -733,40 +770,3 @@ long wxExecute(char **argv, bool sync, wxProcess *handler)
     return wxExecute(command, sync, handler);
 }
 
-#if wxUSE_GUI
-
-// ----------------------------------------------------------------------------
-// Metafile helpers
-// ----------------------------------------------------------------------------
-
-extern void PixelToHIMETRIC(LONG *x, LONG *y)
-{
-    ScreenHDC hdcRef;
-
-    int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
-        iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
-        iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
-        iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
-
-    *x *= (iWidthMM * 100);
-    *x /= iWidthPels;
-    *y *= (iHeightMM * 100);
-    *y /= iHeightPels;
-}
-
-extern void HIMETRICToPixel(LONG *x, LONG *y)
-{
-    ScreenHDC hdcRef;
-
-    int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
-        iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
-        iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
-        iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
-
-    *x *= iWidthPels;
-    *x /= (iWidthMM * 100);
-    *y *= iHeightPels;
-    *y /= (iHeightMM * 100);
-}
-
-#endif // wxUSE_GUI