Example #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);
}
Example #2
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);
}
Example #3
0
// Убьет из стека отсутствующих и поместит tab на верх стека
bool CTabBarClass::AddStack(CTab& tab)
{
	if (tab.Tab() == mp_DummyTab)
		return false;

	bool bStackChanged = false;
	_ASSERTE(isMainThread());
	bool lbExist = false;

	if (!m_TabStack.empty())
	{
		int iter = 0;

		while (iter < m_TabStack.size())
		{
			if (m_TabStack[iter] == tab.Tab())
			{
				if ((iter > 0) && !IsInSwitch())
				{
					CTabID* pTab = m_TabStack[iter];
					m_TabStack.erase(iter);
					m_TabStack.insert(0, pTab);
					bStackChanged = true;
				}

				lbExist = true;
				break;
			}

			++iter;
		}
	}

	// поместить наверх стека
	if (!lbExist)
	{
		CTabID* pTab = tab.AddRef("TabBar.cpp:m_TabStack",0);
		m_TabStack.insert(0, pTab);
		bStackChanged = true;
	}

	return bStackChanged;
}
Example #4
0
int CTabBarClass::PrepareTab(CTab& pTab, CVirtualConsole *apVCon)
{
	int iTabIcon = -1;

	#ifdef _DEBUG
	if (this != gpConEmu->mp_TabBar)
	{
		_ASSERTE(this == gpConEmu->mp_TabBar);
	}
	#endif

	MCHKHEAP
	// get file name
	TCHAR dummy[MAX_PATH*2];
	TCHAR fileName[MAX_PATH+4]; fileName[0] = 0;
	TCHAR szFormat[32];
	TCHAR szEllip[MAX_PATH+1];
	//wchar_t /**tFileName=NULL,*/ *pszNo=NULL, *pszTitle=NULL;
	int nSplit = 0;
	int nMaxLen = 0; //gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;
	int origLength = 0; //_tcslen(tFileName);

	CRealConsole* pRCon = apVCon ? apVCon->RCon() : NULL;
	bool bIsFar = pRCon ? pRCon->isFar() : false;

	// Far 4040 - new "Desktop" window type has "0" index
	if (apVCon && (pTab->Info.nFarWindowID == 0 || pTab->Type() == fwt_Panels))
	{
		iTabIcon = apVCon->RCon()->GetRootProcessIcon();
	}

	LPCWSTR pszTabName = pRCon->GetTabTitle(pTab);

	if (pTab->Name.Empty() || (pTab->Type() == fwt_Panels))
	{
		//_tcscpy(szFormat, _T("%s"));
		lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat));
		nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;

		lstrcpyn(fileName, pszTabName, countof(fileName));

		if (gpSet->pszTabSkipWords && *gpSet->pszTabSkipWords)
		{
			StripWords(fileName, gpSet->pszTabSkipWords);
		}
		origLength = _tcslen(fileName);
		//if (origLength>6) {
		//    // Чтобы в заголовке было что-то вроде "{C:\Program Fil...- Far"
		//    //                              вместо "{C:\Program F...} - Far"
		//	После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце
		//    if (lstrcmp(tFileName + origLength - 6, L" - Far") == 0)
		//        nSplit = nMaxLen - 6;
		//}
	}
	else
	{

		LPTSTR tFileName = NULL;
		if (GetFullPathName(pszTabName, countof(dummy), dummy, &tFileName) && tFileName && *tFileName)
			lstrcpyn(fileName, tFileName, countof(fileName));
		else
			lstrcpyn(fileName, pszTabName, countof(fileName));

		if (pTab->Type() == fwt_Editor)
		{
			if (pTab->Flags() & fwt_ModifiedFarWnd)
				lstrcpyn(szFormat, gpSet->szTabEditorModified, countof(szFormat));
			else
				lstrcpyn(szFormat, gpSet->szTabEditor, countof(szFormat));
		}
		else if (pTab->Type() == fwt_Viewer)
		{
			lstrcpyn(szFormat, gpSet->szTabViewer, countof(szFormat));
		}
		else
		{
			_ASSERTE(FALSE && "Must be processed in previous branch");
			lstrcpyn(szFormat, bIsFar ? gpSet->szTabPanels : gpSet->szTabConsole, countof(szFormat));
		}
	}

	// restrict length
	if (!nMaxLen)
		nMaxLen = gpSet->nTabLenMax - _tcslen(szFormat) + 2/* %s */;

	if (!origLength)
		origLength = _tcslen(fileName);
	if (nMaxLen<15) nMaxLen=15; else if (nMaxLen>=MAX_PATH) nMaxLen=MAX_PATH-1;

	if (origLength > nMaxLen)
	{
		/*_tcsnset(fileName, _T('\0'), MAX_PATH);
		_tcsncat(fileName, tFileName, 10);
		_tcsncat(fileName, _T("..."), 3);
		_tcsncat(fileName, tFileName + origLength - 10, 10);*/
		//if (!nSplit)
		//    nSplit = nMaxLen*2/3;
		//// 2009-09-20 Если в заголовке нет расширения (отсутствует точка)
		//const wchar_t* pszAdmin = gpSet->szAdminTitleSuffix;
		//const wchar_t* pszFrom = tFileName + origLength - (nMaxLen - nSplit);
		//if (!wcschr(pszFrom, L'.') && (*pszAdmin && !wcsstr(tFileName, pszAdmin)))
		//{
		//	// то троеточие ставить в конец, а не середину
		//	nSplit = nMaxLen;
		//}
		// "{C:\Program Files} - Far 2.1283 Administrator x64"
		// После добавления суффиков к заголовку фара - оно уже влезать не будет в любом случае... Так что если панели - '...' строго ставить в конце
		nSplit = nMaxLen;
		_tcsncpy(szEllip, fileName, nSplit); szEllip[nSplit]=0;
		szEllip[nSplit] = L'\x2026' /*"…"*/;
		szEllip[nSplit+1] = 0;
		//_tcscat(szEllip, L"\x2026" /*"…"*/);
		//_tcscat(szEllip, tFileName + origLength - (nMaxLen - nSplit));
		//tFileName = szEllip;
		lstrcpyn(fileName, szEllip, countof(fileName));
	}

	// szFormat различается для Panel/Viewer(*)/Editor(*)
	// Пример: "%i-[%s] *"
	////pszNo = wcsstr(szFormat, L"%i");
	////pszTitle = wcsstr(szFormat, L"%s");
	////if (pszNo == NULL)
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName);
	////else if (pszNo < pszTitle || pszTitle == NULL)
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, pTab->Pos, tFileName);
	////else
	////	_wsprintf(fileName, SKIPLEN(countof(fileName)) szFormat, tFileName, pTab->Pos);
	//wcscpy(pTab->Name, fileName);
	const TCHAR* pszFmt = szFormat;
	TCHAR* pszDst = dummy;
	TCHAR* pszStart = pszDst;
	TCHAR* pszEnd = dummy + countof(dummy) - 1; // в конце еще нужно зарезервировать место для '\0'

	if (!pszFmt || !*pszFmt)
	{
		pszFmt = _T("%s");
	}
	*pszDst = 0;

	bool bRenamedTab = false;
	if (pTab->Flags() & fwt_Renamed)
	{
		if (wcsstr(pszFmt, L"%s") == NULL)
		{
			if (wcsstr(pszFmt, L"%n") != NULL)
				bRenamedTab = true;
			else
				pszFmt = _T("%s");
		}
	}

	TCHAR szTmp[64];
	CmdArg szArg;
	bool  bAppendAdmin = gpSet->isAdminSuffix() && (pTab->Flags() & fwt_Elevated);

	while (*pszFmt && pszDst < pszEnd)
	{
		if (*pszFmt == _T('%'))
		{
			pszFmt++;
			LPCTSTR pszText = NULL;
			switch (*pszFmt)
			{
				case _T('s'): case _T('S'):
					pszText = fileName;
					break;
				case _T('i'): case _T('I'):
					_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%i"), pTab->Info.nIndex);
					pszText = szTmp;
					break;
				case _T('p'): case _T('P'):
					if (!apVCon || !apVCon->RCon())
					{
						wcscpy_c(szTmp, _T("?"));
					}
					else
					{
						_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), apVCon->RCon()->GetActivePID());
					}
					pszText = szTmp;
					break;
				case _T('c'): case _T('C'):
					{
						int iCon = gpConEmu->isVConValid(apVCon);
						if (iCon > 0)
							_wsprintf(szTmp, SKIPLEN(countof(szTmp)) _T("%u"), iCon);
						else
							wcscpy_c(szTmp, _T("?"));
						pszText = szTmp;
					}
					break;
				case _T('n'): case _T('N'):
					{
						pszText = bRenamedTab ? fileName : pRCon ? pRCon->GetActiveProcessName() : NULL;
						wcscpy_c(szTmp, (pszText && *pszText) ? pszText : L"?");
						pszText = szTmp;
					}
					break;
				case _T('d'): case _T('D'):
					{
						pszText = pRCon ? pRCon->GetConsoleCurDir(szArg) : NULL;
						if (!pszText || !*pszText)
							pszText = L"?";
					}
					break;
				case _T('a'): case _T('A'):
					pszText = bAppendAdmin ? gpSet->szAdminTitleSuffix : NULL;
					bAppendAdmin = false;
					break;
				case _T('%'):
					pszText = L"%";
					break;
				case 0:
					pszFmt--;
					break;
			}
			pszFmt++;
			if (pszText)
			{
				if ((*(pszDst-1) == L' ') && (*pszText == L' '))
					pszText = SkipNonPrintable(pszText);
				while (*pszText && pszDst < pszEnd)
				{
					*(pszDst++) = *(pszText++);
				}
			}
		}
		else if ((pszDst > pszStart) && (*(pszDst-1) == L' ') && (*pszFmt == L' '))
		{
			pszFmt++; // Avoid adding sequential spaces (e.g. if some macros was empty)
		}
		else
		{
			*(pszDst++) = *(pszFmt++);
		}
	}

	// Fin. Append smth else?
	if (bAppendAdmin)
	{
		LPCTSTR pszText = gpSet->szAdminTitleSuffix;
		if (pszText)
		{
			while (*pszText && pszDst < pszEnd)
			{
				*(pszDst++) = *(pszText++);
			}
		}
	}

	*pszDst = 0;

	#ifdef _DEBUG
	if (dummy[0] && *(pszDst-1) == L' ')
		*pszDst = 0;
	#endif

	pTab->SetLabel(dummy);

	MCHKHEAP;

	return iTabIcon;
}
Example #5
0
// Должен вызываться только из 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;
}
Example #6
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;
}
Example #7
0
size_t CConEmuCtrl::GetOpenedTabs(CESERVER_REQ_GETALLTABS::TabInfo*& pTabs)
{
	_ASSERTE(pTabs==NULL);
	int nConCount = gpConEmu->GetConCount();
	int nActiveCon = gpConEmu->ActiveConNum();
	size_t cchMax = nConCount*16;
	size_t cchCount = 0;
	CVirtualConsole* pVCon;
	pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)calloc(cchMax, sizeof(*pTabs));
	for (int V = 0; (pVCon = gpConEmu->GetVCon(V)) != NULL; V++)
	{
		if (!pTabs)
		{
			_ASSERTE(pTabs!=NULL);
			break;
		}

		CRealConsole* pRCon = pVCon->RCon();
		if (!pRCon)
			continue;

		CTab tab;
		wchar_t szMark[6];
		for (int T = 0; pRCon->GetTab(T, tab); T++)
		{
			if (cchCount >= cchMax)
			{
				pTabs = (CESERVER_REQ_GETALLTABS::TabInfo*)realloc(pTabs, (cchMax+32)*sizeof(*pTabs));
				if (!pTabs)
				{
					_ASSERTE(pTabs!=NULL);
					break;
				}
				cchMax += 32;
				_ASSERTE(cchCount<cchMax);
			}

			pTabs[cchCount].ActiveConsole = (V == nActiveCon);
			pTabs[cchCount].ActiveTab = ((tab->Flags() & fwt_CurrentFarWnd) == fwt_CurrentFarWnd);
			pTabs[cchCount].Disabled = ((tab->Flags() & fwt_Disabled) == fwt_Disabled);
			pTabs[cchCount].ConsoleIdx = V;
			pTabs[cchCount].TabIdx = T;

			// Text
			//wcscpy_c(szMark, tab.Modified ? L" * " : L"   ");
			switch (tab->Type())
			{
				case fwt_Editor:
					wcscpy_c(szMark, (tab->Flags() & fwt_ModifiedFarWnd) ? L" * " : L" E "); break;
				case fwt_Viewer:
					wcscpy_c(szMark, L" V "); break;
				default:
					wcscpy_c(szMark, L"   ");
			}
				
			if (V == nActiveCon)
			{
				if (T <= 9)
					_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/&%i]%s", V+1, T, szMark);
				//else if (T == 9)
				//	_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/1&0]%s", V+1, szMark);
				else
					_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T, szMark);
			}
			else
			{
				_wsprintf(pTabs[cchCount].Title, SKIPLEN(countof(pTabs[cchCount].Title)) L"[%i/%i]%s", V+1, T, szMark);
			}

			int nCurLen = lstrlen(pTabs[cchCount].Title);
			lstrcpyn(pTabs[cchCount].Title+nCurLen, tab->Name.Ptr(), countof(pTabs[cchCount].Title)-nCurLen);

			cchCount++;
		}
	}
	return cchCount;
}