bool CTabStack::GetNextTab(const CTabID* pTab, BOOL abForward, /*OUT*/ CTab& rTab) { MSectionLockSimple SC; SC.Lock(mpc_Section); CTabID* pNextTab = NULL; for (int i = 0; i < mn_Used; i++) { if (mpp_Stack[i] == pTab) { if (abForward) { if ((i + 1) < mn_Used) pNextTab = mpp_Stack[i+1]; } else { if (i > 0) pNextTab = mpp_Stack[i-1]; } break; } } rTab.Init(pNextTab); SC.Unlock(); return (pNextTab!=NULL); }
void CTabStack::ReleaseTabs(BOOL abInvalidOnly /*= TRUE*/) { if (!this || !mpp_Stack || !mn_Used || !mn_MaxCount) return; MSectionLockSimple SC; SC.Lock(mpc_Section); // Сразу Exclusive lock // Идем сзади, т.к. нужно будет сдвигать элементы for (int i = (mn_Used - 1); i >= 0; i--) { if (!mpp_Stack[i]) continue; if (abInvalidOnly) { if (mpp_Stack[i]->Info.Status == tisValid || mpp_Stack[i]->Info.Status == tisPassive) continue; } CTabID *p = mpp_Stack[i]; mpp_Stack[i] = NULL; #ifdef TAB_REF_PLACE p->DelPlace(m_rp); #endif // Именно Release, т.к. ИД может быть использован в других стеках p->Release(); mn_Used--; // Сдвинуть хвост, если есть if (abInvalidOnly && (mn_Used > 1) && (i < (mn_Used-1))) { memmove(mpp_Stack+i, mpp_Stack+i+1, sizeof(CTabID**) * (mn_Used - i)); } } }
void CRunQueue::RequestRConStartup(CRealConsole* pRCon) { bool bFound = false; CVirtualConsole* pVCon = pRCon->VCon(); // Должен вызываться в главной нити, чтобы соблюсти порядок создания при запуске группы _ASSERTE(isMainThread() == true); MSectionLockSimple cs; cs.Lock(mpcs_QueueLock); // May be exist already in queue? for (INT_PTR i = m_RunQueue.size(); (--i) >= 0;) { if (m_RunQueue[i].pVCon == pVCon) { bFound = true; break; } } // push if (!bFound) { RunQueueItem item = {pVCon}; m_RunQueue.push_back(item); } cs.Unlock(); // Trigger our thread AdvanceQueue(); }
bool CTabStack::GetTabDrawRect(int anIndex, RECT* rcTab) { bool lbExist = false; MSectionLockSimple SC; SC.Lock(mpc_Section); int iReal = GetVisualToRealIndex(anIndex); if (iReal >= 0 && iReal < mn_Used) { CTabID* pTab = mpp_Stack[iReal]; if (pTab) { if (rcTab) *rcTab = pTab->DrawInfo.rcTab; lbExist = true; } else { _ASSERTE(pTab!=NULL); } } else { _ASSERTE(iReal >= 0 && iReal < mn_Used); } SC.Unlock(); return lbExist; }
bool CTabStack::SetTabDrawRect(int anIndex, const RECT& rcTab) { bool lbExist = false; MSectionLockSimple SC; SC.Lock(mpc_Section); int iReal = GetVisualToRealIndex(anIndex); if (iReal >= 0 && iReal < mn_Used) { CTabID* pTab = mpp_Stack[iReal]; if (pTab) { if (memcmp(&pTab->DrawInfo.rcTab, &rcTab, sizeof(rcTab)) != 0) { pTab->ReleaseDrawRegion(); pTab->DrawInfo.rcTab = rcTab; } lbExist = true; } else { _ASSERTE(pTab!=NULL); } } else { _ASSERTE(iReal >= 0 && iReal < mn_Used); } SC.Unlock(); return lbExist; }
int CIconList::CreateTabIcon(LPCWSTR asIconDescr, bool bAdmin, LPCWSTR asWorkDir) { if (bAdmin && !gpSet->isAdminShield()) bAdmin = false; if (!asIconDescr || !*asIconDescr) return GetTabIcon(bAdmin); int iCreatedIcon = -1; MSectionLockSimple CS; CS.Lock(mpcs, 30000); for (INT_PTR i = 0; i < m_Icons.size(); i++) { const TabIconCache& icn = m_Icons[i]; if ((icn.bAdmin!=FALSE) != bAdmin) continue; if (lstrcmpi(icn.pszIconDescr, asIconDescr) != 0) continue; // Already was created! iCreatedIcon = icn.nIconIdx; goto wrap; } iCreatedIcon = CreateTabIconInt(asIconDescr, bAdmin, asWorkDir); if (iCreatedIcon == -1) { // To avoid numerous CreateTabIconInt calls - just remember "No icon" for that asIconDescr TabIconCache DummyIcon = {lstrdup(asIconDescr), bAdmin, -1}; m_Icons.push_back(DummyIcon); } wrap: return iCreatedIcon; }
void CDefTermHk::ReloadSettings() { MSectionLockSimple CS; CS.Lock(mcs); m_Opt.Serialize(); mn_LastCheck = GetTickCount(); }
bool CTabStack::GetTabByIndex(int anIndex, /*OUT*/ CTab& rTab) { MSectionLockSimple SC; SC.Lock(mpc_Section); int iReal = GetVisualToRealIndex(anIndex); if (iReal >= 0 && iReal < mn_Used) { rTab.Init(mpp_Stack[iReal]); } else { rTab.Init(NULL); } SC.Unlock(); return (rTab.Tab() != NULL); }
void CDefTermHk::ReloadSettings() { MSectionLockSimple CS; CS.Lock(mcs); m_Opt.Serialize(); mn_LastCheck = GetTickCount(); if (m_Opt.bDebugLog) { LogInit(); } else { SafeDelete(mp_FileLog); } }
bool CTabStack::GetTabInfoByIndex(int anIndex, /*OUT*/ TabInfo& rInfo) { bool lbFound = false; MSectionLockSimple SC; SC.Lock(mpc_Section); int iReal = GetVisualToRealIndex(anIndex); if (iReal >= 0 && iReal < mn_Used) { if (mpp_Stack[iReal]) { rInfo = mpp_Stack[iReal]->Info; lbFound = true; } } SC.Unlock(); return lbFound; }
// Вызывается при // а) закрытии консоли - убить все табы // б) рестарте консоли - убить все кроме панелей // в) смене активного Far (запуск "far /e ..." например) - пометить пассивными все кроме панелей (некрасиво немного) void CTabStack::MarkTabsInvalid(MatchTabEnum MatchTab, DWORD nFarPID) { MSectionLockSimple SC; SC.Lock(mpc_Section); // Сразу Exclusive lock int iSkipped = 0; for (int i = 0; i < mn_Used; i++) { if (!mpp_Stack[i]) continue; if (MatchTab == MatchNonPanel) { // Смысл в том, чтобы даже при рестарте консоли, при запуске Far->Cmd->Far, // и любых других изменениях табов - ПЕРВЫЙ таб всегда оставался живой // для этой консоли. Для того, чтобы на нем не терялись назначенные юзером // дополнительные флаги отрисовки (цвет таба или метка, например) // При [ре]старте консоли - таб панелей оставить // или при закрытии фара - убить все его редакторы/вьюверы if (nFarPID) { if (mpp_Stack[i]->Info.nPID != nFarPID) { iSkipped++; continue; } _ASSERTE(mpp_Stack[i]->Type() != fwt_Panels); } else if (mpp_Stack[i]->Type() == fwt_Panels) { if (!iSkipped) { iSkipped++; continue; } _ASSERTE(iSkipped==0 && "Must be only one fwt_Panels in RCon.m_Tabs"); } } mpp_Stack[i]->Info.Status = tisInvalid; } }
int CTabStack::GetIndexByTab(const CTabID* pTab) { MSectionLockSimple SC; SC.Lock(mpc_Section); int nIndex = -1; for (int i = 0; i < mn_Used; i++) { if (!mpp_Stack[i]) continue; if (mpp_Stack[i]->Info.Status == tisValid) nIndex++; else continue; if (mpp_Stack[i] == pTab) break; } SC.Unlock(); return nIndex; }
// Возвращает "true" если были изменения в КОЛИЧЕСТВЕ табов (ЗДЕСЬ больше ничего не проверяется) bool CTabStack::UpdateEnd(HANDLE hUpdate, DWORD anActiveFarPID) { MSectionLockSimple* pUpdateLock = (MSectionLockSimple*)hUpdate; // Функция должна вызваться ТОЛЬКО между UpdateBegin & UpdateEnd if (mn_UpdatePos < 0) { _ASSERTE(mn_UpdatePos>=0); return false; } bool bVConClosed = false; if (!mb_FarUpdateMode && (mn_UpdatePos == 0)) { if (!CVConGroup::isVConExists(0)) { bVConClosed = true; } else { // Фукнция UpdateFarWindow должна была быть вызвана хотя бы раз! //UpdateFarWindow(CVirtualConsole* apVCon, LPCWSTR asName, int anType, int anPID, int anFarWindowID, int anViewEditID, CEFarWindowType anFlags) _ASSERTE(mn_UpdatePos>0 || CVConGroup::GetConCount()==0); pUpdateLock->Unlock(); delete pUpdateLock; mn_UpdatePos = -1; return false; } } bool bChanged = (mn_Used != mn_UpdatePos); #if 1 _ASSERTE(pUpdateLock->isLocked()); #else pUpdateLock->RelockExclusive(); #endif if (mb_FarUpdateMode) { _ASSERTE(mn_UpdatePos > 0); // Все табы ПОСЛЕ последнего добавленного/обновленного - помечаем неактивными for (int i = mn_UpdatePos; i < mn_Used; i++) { CTabID *pTab = mpp_Stack[i]; if (pTab && (pTab->Info.Status != tisInvalid)) { pTab->Info.Status = tisPassive; } } // Активен Far? ВСЕ tisPassive табы этого Far-а - разрушаем if (anActiveFarPID) { for (int i = 0; i < mn_Used; i++) { CTabID *pTab = mpp_Stack[i]; // Проверяем только табы активного фара (пассивные [Far -> Far -> Far] не трогаем) if (!pTab || (pTab->Info.nPID != anActiveFarPID)) continue; // Панели и табы с не пассивным статусом - не трогаем if ((pTab->Type() == fwt_Panels) || (pTab->Info.Status != tisPassive)) continue; // Таб (редактор/вьювер) был закрыт, разрушаем _ASSERTE(pTab->Type()==fwt_Editor || pTab->Type()==fwt_Viewer); // Kill this tab pTab->Info.Status = tisInvalid; } } } else { // Для самого таббара - весь хвост просто выкинуть из списка, но сами CTabID не разрушать (tisInvalid не ставить) for (int i = mn_UpdatePos; i < mn_Used; i++) { CTabID *pTab = mpp_Stack[i]; if (pTab) { if (!CVConGroup::isValid((CVirtualConsole*)pTab->Info.pVCon)) pTab->Info.Status = tisInvalid; #ifdef TAB_REF_PLACE pTab->DelPlace(m_rp); #endif pTab->Release(); // Remove from list mpp_Stack[i] = NULL; bChanged = true; } } } for (int i = 0; i < mn_Used; i++) { CTabID *pTab = mpp_Stack[i]; // Kill all invalid tabs if (!pTab || (pTab->Info.Status != tisInvalid)) continue; #ifdef TAB_REF_PLACE pTab->DelPlace(m_rp); #endif pTab->Release(); // Remove from list mpp_Stack[i] = NULL; bChanged = true; } CleanNulls(); pUpdateLock->Unlock(); delete pUpdateLock; return bChanged; }
void CTabStack::UpdateAppend(HANDLE hUpdate, CTabID* pTab, BOOL abMoveFirst) { MSectionLockSimple* pUpdateLock = (MSectionLockSimple*)hUpdate; // Функция должна вызваться ТОЛЬКО между UpdateBegin & UpdateEnd if (mn_UpdatePos < 0 || !pUpdateLock) { _ASSERTE(mn_UpdatePos>=0); _ASSERTE(pUpdateLock!=NULL); return; } // Если таб в списке уже есть - то НИЧЕГО не делать (только переместить его в начало, если abActive) // Если таб новый - добавить в список и вызвать AddRef для таба if (!pTab) { _ASSERTE(pTab != NULL); return; } int nIndex = -1; for (int i = 0; i < mn_Used; i++) { if (mpp_Stack[i] == pTab) { nIndex = i; break; } } if (!abMoveFirst) { // "Обычное" население #ifdef _DEBUG if (nIndex == -1 || nIndex != mn_UpdatePos) { #if 1 _ASSERTE(pUpdateLock->isLocked()); #else pUpdateLock->RelockExclusive(); #endif } #endif RequestSize(mn_UpdatePos+1, pUpdateLock); if (nIndex != -1 && nIndex != mn_UpdatePos) { //_ASSERTE(nIndex > mn_UpdatePos); -- may happens when creating new split from active "far /e ..." tab // Do NOT release tab here! Behavior can differs by arguments of UpdateEnd! CTabID* p = mpp_Stack[mn_UpdatePos]; mpp_Stack[mn_UpdatePos] = mpp_Stack[nIndex]; mpp_Stack[nIndex] = p; // At the moment vector must be realigned! _ASSERTE(mpp_Stack[mn_UpdatePos] == pTab); } if (mpp_Stack[mn_UpdatePos] != pTab) { pTab->AddRef(); #ifdef TAB_REF_PLACE pTab->AddPlace(m_rp.filename, m_rp.fileline); #endif } mpp_Stack[mn_UpdatePos] = pTab; mn_UpdatePos++; if (mn_UpdatePos > mn_Used) { mn_Used = mn_UpdatePos; } } else { if (nIndex == -1) { // Таба в списке еще нет, добавляем AppendInt(pTab, abMoveFirst, pUpdateLock); } else if (abMoveFirst && nIndex > 0) { // Таб нужно переместить в начало списка #if 1 _ASSERTE(pUpdateLock->isLocked()); #else pUpdateLock->RelockExclusive(); #endif memmove(mpp_Stack+1, mpp_Stack, sizeof(CTabID**) * (nIndex-1)); mpp_Stack[0] = pTab; // AddRef не нужен, таб уже у нас в списке! } mn_UpdatePos++; } }
void CRunQueue::ProcessRunQueue() { #ifdef _DEBUG // We run in self thread if (mb_InExecution) { _ASSERTE(!mb_InExecution); } #endif // Block adding new requests from other threads MArray<RunQueueItem> Stack; MSectionLockSimple cs; cs.Lock(mpcs_QueueLock); RunQueueItem item = {}; while (m_RunQueue.pop_back(item)) { //item = m_RunQueue[0]; //m_RunQueue.erase(0); Stack.push_back(item); } cs.Unlock(); DWORD nCurDelay, nWaitExtra; bool bOpt; // And process stack while (!mb_Terminate && Stack.pop_back(item)) { if (!gpConEmu->isValid(item.pVCon)) continue; CVConGuard VCon(item.pVCon); if (!VCon.VCon()) continue; // Avoid too fast process creation? if (mn_LastExecutionTick) { nCurDelay = (GetTickCount() - mn_LastExecutionTick); if (nCurDelay < RUNQUEUE_CREATE_LAG) { nWaitExtra = (RUNQUEUE_CREATE_LAG - nCurDelay); Sleep(nWaitExtra); } } mb_InExecution = true; bOpt = gpConEmu->ExecuteProcessPrepare(); VCon->RCon()->OnStartProcessAllowed(); gpConEmu->ExecuteProcessFinished(bOpt); mb_InExecution = false; // Remember last execution moment mn_LastExecutionTick = GetTickCount(); } }
CDragDrop::~CDragDrop() { //DestroyDragImageBits(); //DestroyDragImageWindow(); if (mb_DragDropRegistered && ghWnd) { mb_DragDropRegistered = FALSE; RevokeDragDrop(ghWnd); } MSectionLockSimple CS; CS.Lock(mp_CrThreads); BOOL lbEmpty = m_OpThread.empty() && !InDragDrop(); CS.Unlock(); if (!lbEmpty) { if (MessageBox(ghWnd, L"Not all shell operations was finished!\r\nDo You want to terminate them (it's may be harmful)?", gpConEmu->GetDefaultTitle(), MB_YESNO|MB_ICONEXCLAMATION) == IDYES) { // Terminate all shell (copying) threads CS.Lock(mp_CrThreads); //std::vector<ThInfo>::iterator iter = m_OpThread.begin(); //while (iter != m_OpThread.end()) while (m_OpThread.size() > 0) { INT_PTR j = m_OpThread.size()-1; const ThInfo* iter = &(m_OpThread[j]); HANDLE hThread = iter->hThread; TerminateThread(hThread, 100); CloseHandle(hThread); //iter = m_OpThread.erase(iter); m_OpThread.erase(j); } CS.Unlock(); } else { // Wait until finished BOOL lbActive = TRUE; while (lbActive) { Sleep(100); CS.Lock(mp_CrThreads); lbActive = (!m_OpThread.empty()) || InDragDrop(); CS.Unlock(); } } } else { // незаконченных нитей нет // -- Leave Critical Section(&m_CrThreads); -- 101229 секция уже закрыта } // Завершение всех нитей драга TerminateDrag(); //if (m_pfpi) free(m_pfpi); m_pfpi=NULL; //if (mp_DesktopID) { CoTaskMemFree(mp_DesktopID); mp_DesktopID = NULL; } SafeDelete(mp_CrThreads); }
bool CTabStack::RefreshFarStatus(DWORD nFarPID, CTab& rActiveTab, int& rnActiveIndex, int& rnActiveCount, bool& rbHasModalTab) { MSectionLockSimple SC; SC.Lock(mpc_Section); // Сразу Exclusive lock bool bChanged = false; int iCount = 0; int iActive = -1; int iModal = -1; int iFirstAvailable = -1; int iFirstPanels = -1; DEBUGTEST(int iPanelsCount = 0); bool bPanels; for (int i = 0; i < mn_Used; i++) { if (!mpp_Stack[i]) continue; // fwt_Panels всегда должен быть bPanels = (mpp_Stack[i]->Type() == fwt_Panels); #ifdef _DEBUG if (bPanels) iPanelsCount++; #endif // When returning to Far - mark its editors/viewers as Valid if (nFarPID && (mpp_Stack[i]->Info.nPID == nFarPID)) { if (mpp_Stack[i]->Info.Status == tisPassive) { mpp_Stack[i]->Info.Status = tisValid; bChanged = true; } } else if (!bPanels) { if (mpp_Stack[i]->Info.Status == tisValid) { mpp_Stack[i]->Info.Status = tisPassive; bChanged = true; } } // Find active tabs if (mpp_Stack[i]->Info.Status == tisValid) { iCount++; if (mpp_Stack[i]->Info.Type & fwt_CurrentFarWnd) { _ASSERTE(iActive == -1 && "Only one active tab per console!"); iActive = i; } if (mpp_Stack[i]->Info.Type & fwt_ModalFarWnd) { _ASSERTE((mpp_Stack[i]->Info.Type & fwt_CurrentFarWnd) && "Modal must be current"); iModal = i; } if (iFirstAvailable < 0) { iFirstAvailable = i; } } else if ((iFirstPanels < 0) && bPanels && (mpp_Stack[i]->Info.Status == tisPassive)) { // May be when returning from "far /e ..." to cmd or another std Far instance iFirstPanels = i; } } _ASSERTE(iPanelsCount==1); // Во время закрытия фара могут быть пертурбации if (iActive < 0) { if (iModal >= 0) { iActive = iModal; } else if (iFirstAvailable >= 0) { iActive = iFirstAvailable; } else if (iFirstPanels >= 0) { _ASSERTE(iCount==0); iActive = iFirstPanels; // There was no one "Active" tab. Mark panels tab as active! _ASSERTE(nFarPID == 0); // returning from "far /e ..."? _ASSERTE(mpp_Stack[iFirstPanels] != NULL); // Protected with CS, no need to check mpp_Stack[iFirstPanels]->Info.Status = tisValid; iCount = 1; } // Check return value if (!bChanged) bChanged = (iActive >= 0); } _ASSERTE(iCount>0 && "At least one tab must be available"); // Во время закрытия фара может возникать... if ((iActive >= 0) && !(mpp_Stack[iActive]->Info.Type & fwt_CurrentFarWnd)) { mpp_Stack[iActive]->Info.Type |= fwt_CurrentFarWnd; } rbHasModalTab = (iModal >= 0); rnActiveCount = iCount; rActiveTab.Init((iActive >= 0) ? mpp_Stack[iActive] : NULL); rnActiveIndex = iActive; return bChanged; }