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); }
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); }
// Должен вызываться только из CRealConsole! // Возвращает "true" если были изменения bool CTabStack::UpdateFarWindow(HANDLE hUpdate, CVirtualConsole* apVCon, LPCWSTR asName, CEFarWindowType anType, int anPID, int anFarWindowID, int anViewEditID, CTab& rActiveTab) { MSectionLockSimple* pUpdateLock = (MSectionLockSimple*)hUpdate; // Функция должна вызваться ТОЛЬКО между UpdateBegin & UpdateEnd if (mn_UpdatePos < 0 || !pUpdateLock) { _ASSERTE(mn_UpdatePos>=0); _ASSERTE(pUpdateLock!=NULL); return false; } bool bChanged = false; CTabID* pTab = NULL; mb_FarUpdateMode = true; // Теперь - поехали обновлять. Правила такие: // 1. Новая вкладка в ФАР может появиться ТОЛЬКО в конце // 2. Закрыта может быть любая вкладка // 3. панели НЕ должны перебиваться на редактор при запуске "far /e" // 4. и вообще, первый таб мог быть добавлен изначально как редактор! int i = mn_UpdatePos; while (i < mn_Used) { if (!mpp_Stack[i]) { i++; continue; } if (mpp_Stack[i]->IsEqual(apVCon, asName, anType, anPID, anViewEditID, fwt_TypeMask)) { // OK, таб совпадает pTab = mpp_Stack[i]; // Refresh status and title if (pTab->Set(asName, anType, anPID, anFarWindowID, anViewEditID, fwt_UpdateFlags)) bChanged = true; _ASSERTE(pTab->Info.Status == tisValid); if (anType & fwt_CurrentFarWnd) rActiveTab.Init(pTab); mn_UpdatePos = i+1; // Закончили break; } // Tab was closed or gone to background bChanged = true; mpp_Stack[i]->Info.Status = tisPassive; i++; } // Если таб новый if (pTab == NULL) { // это новая вкладка, добавляемая в конец pTab = new CTabID(apVCon, asName, anType, anPID, anFarWindowID, anViewEditID); _ASSERTE(pTab->RefCount()==1); _ASSERTE(mn_Used == i); i = AppendInt(pTab, FALSE/*abMoveFirst*/, pUpdateLock); _ASSERTE(pTab->RefCount()==2); if (anType & fwt_CurrentFarWnd) rActiveTab.Init(pTab); pTab->Release(); bChanged = true; mn_UpdatePos = i+1; } _ASSERTE(mn_UpdatePos>=1 && mn_UpdatePos<=mn_Used); return bChanged; }
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; }