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 CTabStack::RecheckPassive() { if (mn_UpdatePos < mn_Used) { // Освободить все элементы за mn_UpdatePos int i = mn_UpdatePos; DEBUGTEST(int iPrev = mn_Used); while (i < mn_Used) { CTabID *pTab = mpp_Stack[i]; if (pTab) { _ASSERTE(pTab->Info.pVCon!=NULL); if (abRConTabs && pTab->Info.pVCon) { bool bVConValid = false, bPidValid = false, bPassive = false; // Only for RCon->tabs.m_Tabs we must to check, if tab is: // 'Still Alive' // 'Hidden' (Another started Far hides editor/viewer of parent Far) // 'Terminated' (Editor/viewer was closed or Far instance terminated) CVConGroup::CheckTabValid(pTab, bVConValid, bPidValid, bPassive); if (bPidValid) { if (bPassive) { // Пока оставить этот таб i++; continue; } } } // If we get here - tab was terminated if (abRConTabs) pTab->Info.Status = tisInvalid; #ifdef TAB_REF_PLACE pTab->DelPlace(m_rp); #endif // Kill this tab pTab->Release(); mpp_Stack[i] = NULL; } DEBUGTEST(iPrev = mn_Used); PRAGMA_ERROR("FAIL. Нужно убрать из стека все NULL-ячейки"); TabDeleted(pUpdateLock, i); _ASSERTE(mn_Used < iPrev); } mn_Used = mn_UpdatePos; } }
// Возвращает "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; }