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; }
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); } }
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; }
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 ); }
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; }
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; }
void *wxThread::CallEntry() { wxON_BLOCK_EXIT0(wxThreadSpecificInfo::ThreadCleanUp); return Entry(); }