Ejemplo n.º 1
0
bool wxEventLoopBase::YieldFor(long eventsToProcess)
{
#if wxUSE_THREADS
    if ( !wxThread::IsMain() )
    {
        // Don't ever dispatch events from non-main threads.
        return false;
    }
#endif // wxUSE_THREADS

    // set the flag and don't forget to reset it before returning
    m_isInsideYield = true;
    m_eventsToProcessInsideYield = eventsToProcess;

    wxON_BLOCK_EXIT_SET(m_isInsideYield, false);

#if wxUSE_LOG
    // disable log flushing from here because a call to wxYield() shouldn't
    // normally result in message boxes popping up &c
    wxLog::Suspend();

    // ensure the logs will be flashed again when we exit
    wxON_BLOCK_EXIT0(wxLog::Resume);
#endif

    DoYieldFor(eventsToProcess);

    return true;
}
Ejemplo n.º 2
0
void wxLogGui::Flush()
{
    wxLog::Flush();

    if ( !m_bHasMessages )
        return;

    // do it right now to block any new calls to Flush() while we're here
    m_bHasMessages = false;

    // note that this must be done before examining m_aMessages as it may log
    // yet another message
    const unsigned repeatCount = LogLastRepeatIfNeeded();

    const size_t nMsgCount = m_aMessages.size();

    if ( repeatCount > 0 )
    {
        m_aMessages[nMsgCount - 1] << " (" << m_aMessages[nMsgCount - 2] << ")";
    }

    const wxString title = GetTitle();
    const int style = GetSeverityIcon();

    // avoid showing other log dialogs until we're done with the dialog we're
    // showing right now: nested modal dialogs make for really bad UI!
    Suspend();

    // and ensure that we allow showing the log again afterwards, even if an
    // exception is thrown
    wxON_BLOCK_EXIT0(wxLog::Resume);

    if ( nMsgCount == 1 )
    {
        // make a copy before calling Clear()
        const wxString message(m_aMessages[0]);
        Clear();

        DoShowSingleLogMessage(message, title, style);
    }
    else // more than one message
    {
        wxArrayString messages;
        wxArrayInt severities;
        wxArrayLong times;

        messages.swap(m_aMessages);
        severities.swap(m_aSeverity);
        times.swap(m_aTimes);

        Clear();

        DoShowMultipleLogMessages(messages, severities, times, title, style);
    }
}
Ejemplo n.º 3
0
bool wxEventLoopBase::YieldFor(long eventsToProcess)
{
#if wxUSE_THREADS
    if ( !wxThread::IsMain() )
    {
        // Don't ever dispatch events from non-main threads.
        return false;
    }
#endif // wxUSE_THREADS

    // set the flag and don't forget to reset it before returning
    const int yieldLevelOld = m_yieldLevel;
    const long eventsToProcessOld = m_eventsToProcessInsideYield;

    m_yieldLevel++;
    wxON_BLOCK_EXIT_SET(m_yieldLevel, yieldLevelOld);

    m_eventsToProcessInsideYield = eventsToProcess;
    wxON_BLOCK_EXIT_SET(m_eventsToProcessInsideYield, eventsToProcessOld);

#if wxUSE_LOG
    // disable log flushing from here because a call to wxYield() shouldn't
    // normally result in message boxes popping up &c
    wxLog::Suspend();

    // ensure the logs will be flashed again when we exit
    wxON_BLOCK_EXIT0(wxLog::Resume);
#endif

    DoYieldFor(eventsToProcess);

#if wxUSE_EXCEPTIONS
    // If any handlers called from inside DoYieldFor() threw exceptions, they
    // may have been stored for later rethrow as it's unsafe to let them escape
    // from inside DoYieldFor() itself, as it calls native functions through
    // which the exceptions can't propagate. But now that we're back to our own
    // code, we may rethrow them.
    if ( wxTheApp )
        wxTheApp->RethrowStoredException();
#endif // wxUSE_EXCEPTIONS

    return true;
}
Ejemplo n.º 4
0
void ScopeGuardTestCase::BlockExit()
{
    int n = 1,
        m = 2;

    {
        gs_count = 1;

        wxON_BLOCK_EXIT0(IncGlobal);
        wxON_BLOCK_EXIT1(Inc, &n);
        wxON_BLOCK_EXIT2(IncBy, &m, 15);

        CPPUNIT_ASSERT_EQUAL( 1, gs_count );
        CPPUNIT_ASSERT_EQUAL( 1, n );
        CPPUNIT_ASSERT_EQUAL( 2, m );
    }

    CPPUNIT_ASSERT_EQUAL( 2, gs_count );
    CPPUNIT_ASSERT_EQUAL( 2, n );
    CPPUNIT_ASSERT_EQUAL( 17, m );
}
Ejemplo n.º 5
0
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
{
    // set the flag and don't forget to reset it before returning
    m_isInsideYield = true;
    m_eventsToProcessInsideYield = eventsToProcess;

    wxON_BLOCK_EXIT_SET(m_isInsideYield, false);

#if wxUSE_LOG
    // disable log flushing from here because a call to wxYield() shouldn't
    // normally result in message boxes popping up &c
    wxLog::Suspend();

    // ensure the logs will be flashed again when we exit
    wxON_BLOCK_EXIT0(wxLog::Resume);
#endif // wxUSE_LOG

    // we don't want to process WM_QUIT from here - it should be processed in
    // the main event loop in order to stop it
    MSG msg;
    int nPaintsReceived = 0;
    while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
            msg.message != WM_QUIT )
    {
#if wxUSE_THREADS
        wxMutexGuiLeaveOrEnter();
#endif // wxUSE_THREADS

        if (msg.message == WM_PAINT)
        {
            // NOTE: WM_PAINTs are categorized as wxEVT_CATEGORY_UI
            if ((eventsToProcess & wxEVT_CATEGORY_UI) == 0)
            {
                // this msg is not going to be dispatched...
                // however WM_PAINT is special: until there are damaged
                // windows, Windows will keep sending it forever!
                if (nPaintsReceived > 10)
                {
                    // we got 10 WM_PAINT consecutive messages...
                    // we must have reached the tail of the message queue:
                    // we're now getting _only_ WM_PAINT events and this will
                    // continue forever (since we don't dispatch them
                    // because of the user-specified eventsToProcess mask)...
                    // break out of this loop!
                    break;
                }
                else
                    nPaintsReceived++;
            }
            //else: we're going to dispatch it below,
            //      so we don't need to take any special action
        }
        else
        {
            // reset the counter of consecutive WM_PAINT messages received:
            nPaintsReceived = 0;
        }

        // choose a wxEventCategory for this Windows message
        bool processNow;
        switch (msg.message)
        {
#if !defined(__WXWINCE__)
            case WM_NCMOUSEMOVE:

            case WM_NCLBUTTONDOWN:
            case WM_NCLBUTTONUP:
            case WM_NCLBUTTONDBLCLK:
            case WM_NCRBUTTONDOWN:
            case WM_NCRBUTTONUP:
            case WM_NCRBUTTONDBLCLK:
            case WM_NCMBUTTONDOWN:
            case WM_NCMBUTTONUP:
            case WM_NCMBUTTONDBLCLK:
#endif

            case WM_KEYDOWN:
            case WM_KEYUP:
            case WM_CHAR:
            case WM_DEADCHAR:
            case WM_SYSKEYDOWN:
            case WM_SYSKEYUP:
            case WM_SYSCHAR:
            case WM_SYSDEADCHAR:
#ifdef WM_UNICHAR
            case WM_UNICHAR:
#endif
            case WM_HOTKEY:
            case WM_IME_STARTCOMPOSITION:
            case WM_IME_ENDCOMPOSITION:
            case WM_IME_COMPOSITION:
            case WM_COMMAND:
            case WM_SYSCOMMAND:

            case WM_IME_SETCONTEXT:
            case WM_IME_NOTIFY:
            case WM_IME_CONTROL:
            case WM_IME_COMPOSITIONFULL:
            case WM_IME_SELECT:
            case WM_IME_CHAR:
            case WM_IME_KEYDOWN:
            case WM_IME_KEYUP:

#if !defined(__WXWINCE__)
            case WM_MOUSEHOVER:
            case WM_MOUSELEAVE:
#endif
#ifdef WM_NCMOUSELEAVE
            case WM_NCMOUSELEAVE:
#endif

            case WM_CUT:
            case WM_COPY:
            case WM_PASTE:
            case WM_CLEAR:
            case WM_UNDO:

            case WM_MOUSEMOVE:
            case WM_LBUTTONDOWN:
            case WM_LBUTTONUP:
            case WM_LBUTTONDBLCLK:
            case WM_RBUTTONDOWN:
            case WM_RBUTTONUP:
            case WM_RBUTTONDBLCLK:
            case WM_MBUTTONDOWN:
            case WM_MBUTTONUP:
            case WM_MBUTTONDBLCLK:
            case WM_MOUSEWHEEL:
                processNow = (eventsToProcess & wxEVT_CATEGORY_USER_INPUT) != 0;
                break;

            case WM_TIMER:
                processNow = (eventsToProcess & wxEVT_CATEGORY_TIMER) != 0;
                break;

            default:
                if (msg.message < WM_USER)
                {
                    // 0;WM_USER-1 is the range of message IDs reserved for use
                    // by the system.
                    // there are too many of these types of messages to handle
                    // them in this switch
                    processNow = (eventsToProcess & wxEVT_CATEGORY_UI) != 0;
                }
                else
                {
                    // Process all the unknown messages. We must do it because
                    // failure to process some of them can be fatal, e.g. if we
                    // don't dispatch WM_APP+2 then embedded IE ActiveX
                    // controls don't work any more, see #14027. And there may
                    // be more examples like this, so dispatch all unknown
                    // messages immediately to be safe.
                    processNow = true;
                }
        }

        // should we process this event now?
        if ( processNow )
        {
            if ( !wxTheApp->Dispatch() )
                break;
        }
        else
        {
            // remove the message and store it
            ::GetMessage(&msg, NULL, 0, 0);
            m_arrMSG.Add(msg);
        }
    }

    // if there are pending events, we must process them.
    if (wxTheApp)
        wxTheApp->ProcessPendingEvents();

    // put back unprocessed events in the queue
    DWORD id = GetCurrentThreadId();
    for (size_t i=0; i<m_arrMSG.GetCount(); i++)
    {
        PostThreadMessage(id, m_arrMSG[i].message,
                          m_arrMSG[i].wParam, m_arrMSG[i].lParam);
    }

    m_arrMSG.Clear();

    return true;
}
Ejemplo n.º 6
0
int wxFileDialog::ShowModal()
{
    WX_HOOK_MODAL_DIALOG();

    HWND hWnd = 0;
    if (m_parent) hWnd = (HWND) m_parent->GetHWND();
    if (!hWnd && wxTheApp->GetTopWindow())
        hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();

    static wxChar fileNameBuffer [ wxMAXPATH ];           // the file-name
    wxChar        titleBuffer    [ wxMAXFILE+1+wxMAXEXT ];  // the file-name, without path

    *fileNameBuffer = wxT('\0');
    *titleBuffer    = wxT('\0');

    long msw_flags = OFN_HIDEREADONLY;

    if ( HasFdFlag(wxFD_NO_FOLLOW) )
        msw_flags |= OFN_NODEREFERENCELINKS;

    if ( HasFdFlag(wxFD_FILE_MUST_EXIST) )
        msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
    /*
        If the window has been moved the programmer is probably
        trying to center or position it.  Thus we set the callback
        or hook function so that we can actually adjust the position.
        Without moving or centering the dlg, it will just stay
        in the upper left of the frame, it does not center
        automatically.
    */
    if (m_bMovedWindow || HasExtraControlCreator()) // we need these flags.
    {
        ChangeExceptionPolicy();
        msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK;
#ifndef __WXWINCE__
        msw_flags |= OFN_ENABLESIZING;
#endif
    }

    wxON_BLOCK_EXIT0(RestoreExceptionPolicy);

    if ( HasFdFlag(wxFD_MULTIPLE) )
    {
        // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT
        msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
    }

    // if wxFD_CHANGE_DIR flag is not given we shouldn't change the CWD which the
    // standard dialog does by default (notice that under NT it does it anyhow,
    // OFN_NOCHANGEDIR or not, see below)
    if ( !HasFdFlag(wxFD_CHANGE_DIR) )
    {
        msw_flags |= OFN_NOCHANGEDIR;
    }

    if ( HasFdFlag(wxFD_OVERWRITE_PROMPT) )
    {
        msw_flags |= OFN_OVERWRITEPROMPT;
    }

    wxOPENFILENAME of;
    wxZeroMemory(of);

    of.lStructSize       = gs_ofStructSize;
    of.hwndOwner         = hWnd;
    of.lpstrTitle        = m_message.t_str();
    of.lpstrFileTitle    = titleBuffer;
    of.nMaxFileTitle     = wxMAXFILE + 1 + wxMAXEXT;

#ifndef __WXWINCE__
    GlobalPtr hgbl;
    if ( HasExtraControlCreator() )
    {
        msw_flags |= OFN_ENABLETEMPLATEHANDLE;

        hgbl.Init(256, GMEM_ZEROINIT);
        GlobalPtrLock hgblLock(hgbl);
        LPDLGTEMPLATE lpdt = static_cast<LPDLGTEMPLATE>(hgblLock.Get());

        // Define a dialog box.

        lpdt->style = DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS;
        lpdt->cdit = 0;         // Number of controls
        lpdt->x = 0;
        lpdt->y = 0;

        // convert the size of the extra controls to the dialog units
        const wxSize extraSize = GetExtraControlSize();
        const LONG baseUnits = ::GetDialogBaseUnits();
        lpdt->cx = ::MulDiv(extraSize.x, 4, LOWORD(baseUnits));
        lpdt->cy = ::MulDiv(extraSize.y, 8, HIWORD(baseUnits));

        // after the DLGTEMPLATE there are 3 additional WORDs for dialog menu,
        // class and title, all three set to zeros.

        of.hInstance = (HINSTANCE)lpdt;
    }
#endif // __WXWINCE__

    // Convert forward slashes to backslashes (file selector doesn't like
    // forward slashes) and also squeeze multiple consecutive slashes into one
    // as it doesn't like two backslashes in a row neither

    wxString  dir;
    size_t    i, len = m_dir.length();
    dir.reserve(len);
    for ( i = 0; i < len; i++ )
    {
        wxChar ch = m_dir[i];
        switch ( ch )
        {
        case wxT('/'):
            // convert to backslash
            ch = wxT('\\');

        // fall through

        case wxT('\\'):
            while ( i < len - 1 )
            {
                wxChar chNext = m_dir[i + 1];
                if ( chNext != wxT('\\') && chNext != wxT('/') )
                    break;

                // ignore the next one, unless it is at the start of a UNC path
                if (i > 0)
                    i++;
                else
                    break;
            }
        // fall through

        default:
            // normal char
            dir += ch;
        }
    }

    of.lpstrInitialDir   = dir.c_str();

    of.Flags             = msw_flags;
    of.lpfnHook          = wxFileDialogHookFunction;
    of.lCustData         = (LPARAM)this;

    wxArrayString wildDescriptions, wildFilters;

    size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters);

    wxASSERT_MSG( items > 0 , wxT("empty wildcard list") );

    wxString filterBuffer;

    for (i = 0; i < items ; i++)
    {
        filterBuffer += wildDescriptions[i];
        filterBuffer += wxT("|");
        filterBuffer += wildFilters[i];
        filterBuffer += wxT("|");
    }

    // Replace | with \0
    for (i = 0; i < filterBuffer.length(); i++ ) {
        if ( filterBuffer.GetChar(i) == wxT('|') ) {
            filterBuffer[i] = wxT('\0');
        }
    }

    of.lpstrFilter  = filterBuffer.t_str();
    of.nFilterIndex = m_filterIndex + 1;

    //=== Setting defaultFileName >>=========================================

    wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));

    of.lpstrFile = fileNameBuffer;  // holds returned filename
    of.nMaxFile  = wxMAXPATH;

    // we must set the default extension because otherwise Windows would check
    // for the existing of a wrong file with wxFD_OVERWRITE_PROMPT (i.e. if the
    // user types "foo" and the default extension is ".bar" we should force it
    // to check for "foo.bar" existence and not "foo")
    wxString defextBuffer; // we need it to be alive until GetSaveFileName()!
    if (HasFdFlag(wxFD_SAVE))
    {
        const wxChar* extension = filterBuffer.t_str();
        int maxFilter = (int)(of.nFilterIndex*2L) - 1;

        for( int i = 0; i < maxFilter; i++ )           // get extension
            extension = extension + wxStrlen( extension ) + 1;

        // use dummy name a to avoid assert in AppendExtension
        defextBuffer = AppendExtension(wxT("a"), extension);
        if (defextBuffer.StartsWith(wxT("a.")))
        {
            defextBuffer = defextBuffer.Mid(2); // remove "a."
            of.lpstrDefExt = defextBuffer.c_str();
        }
    }

    // store off before the standard windows dialog can possibly change it
    const wxString cwdOrig = wxGetCwd();

    //== Execute FileDialog >>=================================================

    if ( !ShowCommFileDialog(&of, m_windowStyle) )
        return wxID_CANCEL;

    // GetOpenFileName will always change the current working directory on
    // (according to MSDN) "Windows NT 4.0/2000/XP" because the flag
    // OFN_NOCHANGEDIR has no effect.  If the user did not specify
    // wxFD_CHANGE_DIR let's restore the current working directory to what it
    // was before the dialog was shown.
    if ( msw_flags & OFN_NOCHANGEDIR )
    {
        wxSetWorkingDirectory(cwdOrig);
    }

    m_fileNames.Empty();

    if ( ( HasFdFlag(wxFD_MULTIPLE) ) &&
#if defined(OFN_EXPLORER)
            ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') )
#else
            ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') )
#endif // OFN_EXPLORER
       )
    {
#if defined(OFN_EXPLORER)
        m_dir = fileNameBuffer;
        i = of.nFileOffset;
        m_fileName = &fileNameBuffer[i];
        m_fileNames.Add(m_fileName);
        i += m_fileName.length() + 1;

        while (fileNameBuffer[i] != wxT('\0'))
        {
            m_fileNames.Add(&fileNameBuffer[i]);
            i += wxStrlen(&fileNameBuffer[i]) + 1;
        }
#else
        wxStringTokenizer toke(fileNameBuffer, wxT(" \t\r\n"));
        m_dir = toke.GetNextToken();
        m_fileName = toke.GetNextToken();
        m_fileNames.Add(m_fileName);

        while (toke.HasMoreTokens())
            m_fileNames.Add(toke.GetNextToken());
#endif // OFN_EXPLORER

        wxString dir(m_dir);
        if ( m_dir.Last() != wxT('\\') )
            dir += wxT('\\');

        m_path = dir + m_fileName;
        m_filterIndex = (int)of.nFilterIndex - 1;
    }
    else
    {
        //=== Adding the correct extension >>=================================

        m_filterIndex = (int)of.nFilterIndex - 1;

        if ( !of.nFileExtension ||
                (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) )
        {
            // User has typed a filename without an extension:
            const wxChar* extension = filterBuffer.t_str();
            int   maxFilter = (int)(of.nFilterIndex*2L) - 1;

            for( int i = 0; i < maxFilter; i++ )           // get extension
                extension = extension + wxStrlen( extension ) + 1;

            m_fileName = AppendExtension(fileNameBuffer, extension);
            wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
        }

        m_path = fileNameBuffer;
        m_fileName = wxFileNameFromPath(fileNameBuffer);
        m_fileNames.Add(m_fileName);
        m_dir = wxPathOnly(fileNameBuffer);
    }

    return wxID_OK;

}
Ejemplo n.º 7
0
void *wxThread::CallEntry()
{
    wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp);
    return Entry();
}