Пример #1
0
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);
}
Пример #2
0
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));
		}
	}
}
Пример #3
0
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();
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
void CDefTermHk::ReloadSettings()
{
	MSectionLockSimple CS;
	CS.Lock(mcs);

	m_Opt.Serialize();
	mn_LastCheck = GetTickCount();
}
Пример #8
0
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);
}
Пример #9
0
void CDefTermHk::ReloadSettings()
{
	MSectionLockSimple CS;
	CS.Lock(mcs);

	m_Opt.Serialize();
	mn_LastCheck = GetTickCount();

	if (m_Opt.bDebugLog)
	{
		LogInit();
	}
	else
	{
		SafeDelete(mp_FileLog);
	}
}
Пример #10
0
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;
}
Пример #11
0
// Вызывается при
// а) закрытии консоли - убить все табы
// б) рестарте консоли - убить все кроме панелей
// в) смене активного 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;
	}
}
Пример #12
0
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;
}
Пример #13
0
// Возвращает "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;
}
Пример #14
0
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++;
	}
}
Пример #15
0
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();
	}
}
Пример #16
0
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);
}
Пример #17
0
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;
}