Esempio n. 1
0
void CPluginW2800::SetWindow(int nTab)
{
	if (!InfoW2800 || !InfoW2800->AdvControl)
		return;

	// We have to find **current** window ID because Far entangles them constantly
	INT_PTR iNewPos = -1;
	if (pwList && (nTab >= 0) && (nTab < pwList->size()))
	{
		MArray<WindowInfo> wCurrent;
		// Load window list
		WLoadWindows(wCurrent, GetWindowCount());
		INT_PTR i = WExists((*pwList)[nTab], wCurrent);
		if (i >= 0)
			iNewPos = wCurrent[i].Pos;
	}

	if ((iNewPos >= 0)
		&& InfoW2800->AdvControl(&guid_ConEmu, ACTL_SETCURRENTWINDOW, iNewPos, NULL))
		InfoW2800->AdvControl(&guid_ConEmu, ACTL_COMMIT, 0, 0);
}
bool CPluginW2800::UpdateConEmuTabsApi(int windowCount)
{
	if (!InfoW2800 || !InfoW2800->AdvControl || gbIgnoreUpdateTabs)
		return false;

	bool lbCh = false, lbDummy = false;
	WindowInfo WInfo = {sizeof(WindowInfo)};
	wchar_t szWNameBuffer[CONEMUTABMAX];
	int tabCount = 0;
	bool lbActiveFound = false;

	_ASSERTE(GetCurrentThreadId() == gnMainThreadId);

	WindowInfo WActive = {sizeof(WActive)};
	WActive.Pos = -1;
	bool bActiveInfo = InfoW2800->AdvControl(&guid_ConEmu, ACTL_GETWINDOWINFO, 0, &WActive)!=0;
	// Если фар запущен с ключом "/e" (как standalone редактор) - будет ассерт при первой попытке
	// считать информацию об окне (редактор еще не создан?, а панелей вообще нет)
	_ASSERTE(bActiveInfo && (WActive.Flags & WIF_CURRENT));
	static WindowInfo WLastActive;

	if (!pwList)
		pwList = new MArray<WindowInfo>();

	// Another weird Far API breaking change. How more?..
	MArray<WindowInfo> wCurrent;
	// Load window list
	for (int i = 0; i < windowCount; i++)
	{
		ZeroStruct(WInfo);
		WInfo.StructSize = sizeof(WInfo);
		WInfo.Pos = i;
		if (!InfoW2800->AdvControl(&guid_ConEmu, ACTL_GETWINDOWINFO, 0, &WInfo))
			continue;
		if (WInfo.Type != WTYPE_EDITOR && WInfo.Type != WTYPE_VIEWER && WInfo.Type != WTYPE_PANELS)
			continue;

		if (WInfo.Type == WTYPE_PANELS)
		{
			if ((wCurrent.size() > 0) && (wCurrent[0].Type == WTYPE_PANELS))
				wCurrent[0] = WInfo;
			else
				wCurrent.insert(0, WInfo);
		}
		else
		{
			wCurrent.push_back(WInfo);
		}
	}
	// Clear closed windows
	for (INT_PTR i = 0; i < pwList->size();)
	{
		const WindowInfo& L = (*pwList)[i];

		INT_PTR iFound = WExists(L, wCurrent);

		if (iFound < 0)
			pwList->erase(i);
		else
			i++;
	}
	// Add new windows
	for (INT_PTR i = 0; i < wCurrent.size(); i++)
	{
		const WindowInfo& C = wCurrent[i];

		INT_PTR iFound = WExists(C, *pwList);

		if (iFound >= 0)
		{
			(*pwList)[iFound] = C;
		}
		else
		{
			if (C.Type == WTYPE_PANELS)
			{
				if ((pwList->size() > 0) && ((*pwList)[0].Type == WTYPE_PANELS))
					(*pwList)[0] = C;
				else
					pwList->insert(0, C);
			}
			else
			{
				pwList->push_back(C);
			}
		}
	}
	// And check the count
	windowCount = pwList->size();

	// Проверить, есть ли активный редактор/вьювер/панель
	if (bActiveInfo && (WActive.Type == WTYPE_EDITOR || WActive.Type == WTYPE_VIEWER || WActive.Type == WTYPE_PANELS))
	{
		if (!(WActive.Flags & WIF_MODAL))
			WLastActive = WActive;
	}
	else
	{
		int nTabs = 0, nModalTabs = 0;
		bool bFound = false;
		WindowInfo WModal, WFirst;
		// Поскольку в табах диалоги не отображаются - надо подменить "активное" окно
		// т.е. предпочитаем тот таб, который был активен ранее
		for (int i = 0; i < windowCount; i++)
		{
			WInfo = (*pwList)[i];
			_ASSERTE(WInfo.Type == WTYPE_EDITOR || WInfo.Type == WTYPE_VIEWER || WInfo.Type == WTYPE_PANELS);

			if (!nTabs)
				WFirst = WInfo;
			nTabs++;
			if (WInfo.Flags & WIF_MODAL)
			{
				nModalTabs++;
				WModal = WInfo;
			}

			if (WLastActive.StructSize && (WInfo.Type == WLastActive.Type) && (WInfo.Id == WLastActive.Id))
			{
				bActiveInfo = bFound = true;
				WActive = WInfo;
			}
		}

		if (!bFound)
		{
			if (nModalTabs)
			{
				bActiveInfo = true;
				WActive = WModal;
			}
			else if (nTabs)
			{
				bActiveInfo = true;
				WActive = WFirst;
			}
		}
	}

	for (int i = 0; i < windowCount; i++)
	{
		WInfo = (*pwList)[i];

		if (WInfo.Type == WTYPE_EDITOR || WInfo.Type == WTYPE_VIEWER || WInfo.Type == WTYPE_PANELS)
		{
			WInfo.Name = szWNameBuffer;
			WInfo.NameSize = CONEMUTABMAX;
			InfoW2800->AdvControl(&guid_ConEmu, ACTL_GETWINDOWINFO, 0, &WInfo);
			WARNING("Для получения имени нужно пользовать ECTL_GETFILENAME");

			//// Проверить, чего там...
			//_ASSERTE((WInfo.Flags & WIF_MODAL) == 0);

			if (WInfo.Type == WTYPE_EDITOR || WInfo.Type == WTYPE_VIEWER || WInfo.Type == WTYPE_PANELS)
			{
				if ((WInfo.Flags & WIF_CURRENT))
				{
					lbActiveFound = true;
				}
				else if (bActiveInfo && (WInfo.Type == WActive.Type) && (WInfo.Id == WActive.Id))
				{
					WInfo.Flags |= WIF_CURRENT;
					lbActiveFound = true;
				}

				TODO("Определение ИД редактора/вьювера");
				lbCh |= AddTab(tabCount, WInfo.Pos, false/*losingFocus*/, false/*editorSave*/,
				               WInfo.Type, WInfo.Name, /*editorSave ? ei.FileName :*/ NULL,
				               (WInfo.Flags & WIF_CURRENT), (WInfo.Flags & WIF_MODIFIED), (WInfo.Flags & WIF_MODAL),
							   WInfo.Id);
			}
		}
	}

	bool bHasPanels = this->CheckPanelExist();

	if (!lbActiveFound)
	{
		// Порядок инициализации поменялся, при запуске "far /e ..." редактора сначала вообще "нет".
		_ASSERTE((!bHasPanels && windowCount==0 && bActiveInfo && WActive.Type == WTYPE_DESKTOP) && "Active window must be detected already!");

		if (tabCount == 0)
		{
			// Добавить в табы хоть что-то
			lbCh |= AddTab(tabCount, 0, false/*losingFocus*/, false/*editorSave*/,
					               WTYPE_PANELS, L"far", /*editorSave ? ei.FileName :*/ NULL,
					               1/*Current*/, 0/*Modified*/, 1/*Modal*/, 0);
		}

		if (tabCount > 0)
		{
			gpTabs->Tabs.CurrentType = gnCurrentWindowType = gpTabs->Tabs.tabs[tabCount-1].Type;
		}
		else
		{
			_ASSERTE(tabCount>0);
		}
	}

	// 101224 - сразу запомнить количество!
	gpTabs->Tabs.nTabCount = tabCount;

	return lbCh;
}